A personal blog for Glider queries, tips, and guides.#
What Is Glider#
It’s a security/research tool that lets you query multiple contracts on EVM blockchains at once by certain logic, parameters, dependencies, variable names, or anything else you can think of.
In terms of traditional private audits (companies like Trail of Bits), bug bounties (like Immunefi), and public contests (like Code4rena), Glider differentiates because its purpose is to act on scale, while they only provide security to a researcher’s chosen project. With only one effective Glider query (aka glide) and a good negotiation team, you can contact tens or hundreds of projects that share some vulnerability.
The research part is the ability to get statistics on logic, libraries, standards, etc., directly from the source code of smart contracts. For example, it’s quite easy to get the total number of smart contracts named Test
, the total number of payable functions, or the total number of ecrecover
instructions. You can also find more specific occurrences of these instances based on your custom logic.
Disclaimer! Glider is still in beta; a lot of things to do, and a lot of things can go wrong. If you encounter any issues, please feel free to contact the team in the Discord channel.
Quick Start#
If you’re already familiar with smart contracts in general, I’d suggest you to:
- Go to the Glider official website
- Register an account
- Browse the provided basic queries
- Try to run and see how it works
Otherwise, start with this awesome repo!
Last sync with the repo: d728d31e1b7adc33060d46bc473acc3334afab44.
Alright, straight to business?
First things first, get familiar with these links; you’ll need to use them quite often:
Official guidelines API documentation Glider itself #glider channel in Discord Security wiki by Remedy to find interesting attack vectors (or contribute yours!) Hello, world! After registering on the website, you’ll see MY QUERIES on the left. Click New Query and give it some name, then copy and insert this:
from glider import * def query(): contracts = Contracts()....
Let’s take the query from the previous article and change the name we’re searching for to something more useful:
from glider import * def query(): contracts = Contracts().with_name("ERC721").exec() return contracts The first thing you’ll probably notice after you try this query is the number of contracts - more than 4000! To keep it simple, let’s limit this number:
from glider import * def query(): contracts = Contracts().with_name("ERC721").exec(10) return contracts The ....
We’re continuing to modify the glide:
from glider import * def query(): contracts = Contracts().with_name("ERC721").exec(10) return contracts This time, we’re going to add more logic to it besides the initial request to the DB.
contracts variable contains List[Contract], remember? What we can do is loop through the contracts, as was mentioned in Get Started, getting some properties.
Modifications To begin with, let’s add an additional variable between the two other instructions and change the return statement to this variable:...
The declarative DB query is so much more than just the Contracts object!
To be precise, it is:
Contracts Functions Modifiers Instructions StateVariables Each has many methods, and more importantly, you can combine them in the same query, filtering out unnecessary entities and improving the subsequent arbitrary logic part.
Example Take a look at this glide from the examples on the website:
from glider import * def query(): instructions = ( Functions() ....
Errors are frustrating and can cause aggression and violence towards your computer. Today, we’ll talk about a few methods of their location and correction.
The usual workflow for writing a new glide is as follows:
You start with the declarative query part and a small subset of instances (e.g., the limit is 10). Continue with the arbitrary logic part, gradually improving it and covering the subset. When you think the glide is ready, you run it on a larger subset (e....
The second element in the declarative part’s hierarchy, Functions.
With Functions, you can perform filtration by:
Function names (exact, negative exact, prefix, suffix, regexp) Function signatures (hashed, not hashed) Arguments (types, names, count) Modifiers Special properties (such as the Solidity function visibility) All the methods and properties of Callables (docs) also apply to Functions (docs) because the latter is a child class. Don’t forget to look at both classes when searching for a method in the documentation....
Instructions and its twin Instruction are perhaps the most complex objects in Glider, with the most methods, because they represent the never-ending combinations of Solidity calls, calculations, variable assignments, conditions, etc.
From Instructions, you can filter out:
Calls by type (external, delegate, static, low-level, internal…) Calls by name (exact, negative, signature, prefix, suffix) Conditions Assembly Entry points Example from glider import * def query(): instructions = ( Functions() .with_one_property([MethodProp.PUBLIC, MethodProp.EXTERNAL]) ....
We’ve covered the object a little in the previous articles, so you should already be quite familiar with it.
Anyway, Contracts is the starting point of a declarative query, the highest level, and the smallest number of instances. You can filter contracts by the following parameters:
Names (exact, negative, prefix, suffix, regexp) Compiler versions (by range, e.g., 0.6.0 - 0.8.25) Error and event names and signatures Function names Struct names and nested types Interfaces and main (high-level) contracts Example from glider import * def query(): contracts = ( Contracts() ....
Today, we will talk about the maintainability of your glides.
I know this is not the most exciting thing to read about, and I should’ve written about it after the first article, but I’d like to cover this topic before we get to more complex arbitrary code.
Glides require updates sometimes to cover a new version of Solidity or a library. And you don’t want to spend the entire morning analyzing the glide you made six months ago, do you?...
Now that we’re done with the easy stuff, let’s dive into complex arbitrary code. From top to bottom, we’ll start with the Contract object.
Methods Consider the following example from the article about Contracts:
from glider import * def query(): contracts = ( Contracts() .mains() .with_compiler_range("0.8.0", "0.8.26") .with_struct_name("Config") .exec(1, 1) ) result = [] for contract in contracts: # arbitrary logic print(contract.source_code()) result.append(contract) return result We can’t do much with the declarative query anymore without descending to Functions or Instructions, but there are still many methods for the logic in the loop....