Solidity Dialect
This documentation page is still a work-in-progress and may be subject to change.
This page contains reference documentation for the Solidity dialect of PAQL, describing every object type available, and the properties and iterators of each object type.
Contracts and Functions
Contract
Represents a smart contract of any kind (contract, interface, or library).
Properties
name: the name of the contractfilepath: the virtual file path of the contract, as computed by the Solidity compiler.kind: one ofcontract,interface, orlibraryisContract,isInterface,isLibrary: boolean values indicating whether the contract is of the specific kind, respectively.superClasses: an object that may be iterated over to obtain the superclasses (asContractobjects) of this contract.isConcrete: whether this contract has been compiled to bytecode. Usually, this includes non-abstract contracts and libraries.isAbstract: opposite ofisConcrete. Typically, this includes interfaces and abstract contracts.
Iterators
Function: the functions that this contract has. Note that this includes inherited functions, as well as internal library functions that are included in the Contract's bytecode.- Any
StatementorExpression: all of the corresponding Statements or Expressions that occur in the functions of this contract. StorageVar: the storage variables that this contract has. Note that this includes inherited storage variables.StorageRead,StorageWrite: the storage reads/writes that occur in this contract.
Examples
The following query finds all of the functions defined by interface contracts
that are in the src folder:
FIND
Contract contract,
Function function IN contract
WHERE
contract.kind == "interface",
regexMatch(contract.filepath, "src/.*"),
Function
Represents a function.
Properties
name(string): The name of the function, such astransfer.signature(string): The full name and type signature of the function used in the Solidity ABI, such astransfer(address,uint256). This is an empty string for functions that are not externally callable.selector(string): The selector of this function as a string without a0xprefix, such as1234abcd. Empty string if the function is not externally callable, or if it is a fallback, receive, or constructor function.isExternallyCallable(bool): a boolean value indicating whether this function may be invoked directly using an external call.visibility(string): the visibility of this function, such asexternal,public,internal, andprivate.mutability(string): the mutability of this function, such asnonpayable,payable,view, andpure.contract(Contract): theContractthat has this function. Note that this is not necessarily the same as the contract that defined this function; for example, ifAinheritsffromB, then theFunctionobject forA.fwill haveAas itscontractproperty, notB.definingContractName(string): The name of the contract that defined this function. For example, ifAinheritsffromB, thenf.definingContractNameisB.reachable: an object that may be iterated to get objects that are "reachable" from this function. Supports iteration overFunctions, expressions, statements, to get all functions/expressions/statements (respectively) that are reachable from thisFunction. Also supportsStorageReadandStorageWrite, for convenience. For example, iff()callsg()andg()callsh(), then when iteratingFunction x IN f.reachable,xwill iterate over bothgandh.
Iterators
Argument: the parameters of this function. Currently, this object only supports theforwardSlices/backwardSlicesproperties that are similar to the ones defined onExpressionandStatement.StorageRead: the storage reads that may occur specifically within this function (i.e., does not include those in nested internal calls).StorageWrite: the storage writes that may occur specifically within this function (i.e., does not include those in nested internal calls).- Every
ExpressionandStatement: all of the expressions/statements of the specified type that are directly in the function. Note that if you also want to get the expressions/statements in nested calls, you should iterate through the.reachableproperty instead.
Examples
Find all internal calls to _updateInterest() in functions named deposit:
FIND
Function f,
InternalCall c IN f
WHERE
f.name == "deposit",
c.callee.name == "_updateInterest",
Find all storage writes that may be performed as a result of calling an external function (i.e., in the external function itself and any internal functions that are reachable from that external function):
FIND
Function extFun,
StorageWrite w IN extFun.reachable,
WHERE
extFun.isExternallyCallable
StorageVar
Represents a storage variable. This does not include immutable variables or constants.
Properties
name(string): The name of this storage variable.contract(Contract): TheContractthat this storage variable has been inherited into.declaringContract(Contract): TheContractthat declared this storage variable.getterSignature(string): The signature of the getter function of this variable as a string, or empty string if this has no getter function.visibility(string): the declared visibility of this variable (eitherpublicorprivate).slot(integer): The (base) storage slot of this varible.offset(integer): The (base) offset of this variable.
Expressions and Statements
The Expression and Statement classes describe a family of PAQL objects that
cover Solidity expressions and control structures, respectively.
Common Properties
The following properties are available on all Expressions and Statements.
after: an object that may be iterated to get allExpressionorStatementthat may be executed after this one.before: an object that may be iterated to get allExpressionorStatementthat may be executed before this one.forwardSlices: an object that may be iterated to get allExpressionorStatementthat are influenced by the results of thisExpression/Statement.backwardSlices: an object that may be iterated to get allExpressionorStatementthat influence the operands of thisExpression/Statement.incomingPaths: (Experimental) an object that may be iterated to get allPaths from the external function entries to thisExpressionorStatement.outgoingPaths: (Experimental) an object that may be iterated to get allPaths from thisExpressionorStatementto the function return/revert.
Common Iterators
The following iterators are available on all Expressions and Statements.
StorageRead,StorageWrite: the storage accesses that are performed by thisExpression/Statement.
Expression Properties
The following properties are available on all Expressions.
results: an object that may be iterated to get theResultsof thisExpression.
Expression: ExternalCall
Represents an external call.
Properties
signature(string): the signature of the function that is invoked by this call. Empty string if the function target cannot be determined.name(string): the name of the function that is invoked by this call. Empty string if the function target cannot be determined.selector(string): the selector of the call target. Empty string if not known, or if the target is a fallback or receive.callees: an object that may be iterated to get all of the external functions that may be targets of this call.isLowLevelCall: whether this is a low-level call, such as in the Solidity codemsg.sender.call("").isSend, (bool): whether this is a Solidity.send/.transferof native currency.kind(string): indicates the type of EVM call opcode of this call, one ofcall,staticcall, ordelegatecall.isCall,isStaticcall,isDelegatecall(bool): indicates whether the call is the corresponding kind.address: theValuecorresponding to the address to which this call is made.
Iterators
CallArgument: objects representing the arguments to this call, excluding values such as address, call value, etc. Each of these objects provides a.argIndexproperty indicating the index of the argument, as well as a.valueproperty that has the actualValueprovided as the argument.
Expression: InternalCall
Represents an internal call (within the same contract).
Properties
callee(Function): the function that is called.
Iterators
CallArgument: same behavior as iterating overCallArgumentinExternalCall.
Expression: PrecompileCall
Represents a call to a precompiled contract.
Properties
address(string): the address of the precompiled contract.name(string): the name of the precompiled contract.
Arithmetic Expressions
These expressions represent arithmetic operations, and they include:
DivideExpressionMultiplyExpression
Generic Expressions
The following Solidity expressions are considered to be Expression objects,
but currently do not have any special object types:
+,-,%,**operators (checked and unchecked)<,>,==operators- assignment to storage variable
- use of a storage variable
Statement: RequireLike
Represents a pattern of expressions/statements that are similar to a
require(...) statement.
This currently includes the following:
require(condition, "withOrWithoutMessage");in Solidityif (!condition) revert WithOrWithoutError();in Solidity- Any similar patterns to the above that are automatically inserted by the Solidity compiler, such as for checking success status of function calls on contracts
Properties
condition(Expression): the boolean expression used as a condition to the require-like structure.
Statement: Revert
Represents any statement that is similar to a revert, including the following:
revert("withOrWithoutmessage")in Solidityrevert Error(...)in Solidity- Any
reverts or panics automatically inserted by the Solidity compiler
Generic Statements
The following Solidity statements are considered to be Statement objects,
but currently do not have any special object types:
return- some instances of
if (condition) { ... }
Storage Accesses
To allow reasoning about storage variable reads and writes, the Solidity
dialect provides two classes StorageRead and StorageWrite, which represent a
specific read from or write to (respectively) a specific storage variable.
Common Properties
location: a string representation of the storage variable location that was written, or empty string if unknown. For scalar variables, this is just the name of the variable. For aggregate data structures, such asstructormappings, this may also include fields or array/mapping indexes. Unknown fields or indices will be represented using*characters. For example, the location of a write to a struct field in a mapping may be represented with a string likemyMapping[*].myField.after,before,incomingPaths,outgoingPaths: similar to their corresponding properties onExpression/Statement.
Common Iterators
StorageVar: the storage variable(s) that may be directly involved in this storage access.
Values
Arguments to various operands and function parameters are represented using the
Value classes.
Three types of Values are supported:
- The
Argumentclass, representing function parameters. - The
Resultclass, representing results of an operation. - The generic
Valueclass, representing all values. This includes the above two classes as well as other generic values that currently do not have a specialized class.
Common Properties
source: returns an object that may be iterated to obtain theExpressionthat created thisValue. The object will have an empty iterator if this was not created by an expression, such as when thisValueis a function parameter.forwardSlices: an object that may be iterated to get allExpressionorStatementthat are influenced by the results of thisExpression/Statement.backwardSlices: an object that may be iterated to get allExpressionorStatementthat influence the operands of thisExpression/Statement.
Common Iterators
Use: represents the "uses" of this value (see below section).
Use
This feature is experimental and subject to change. Use at your own risk.
The Use class contains information about how a particular value is used in an
Expression/Statement.
It is not a Value itself.
Properties
user: theExpressionthat uses the value.argIndex(int): the index in theuser's argument list.
CallArgument
This feature is experimental and subject to change. Use at your own risk.
The CallArgument class represents an argument of a function call.
Note that this is currently unrelated to Use; it will be combined with Use
in the future.
Properties
value: theValueused as the argument.argIndex: the zero-indexed index of the value in the call's argument list. For example, in the callf(a, b), the call argumentahasargIndex0.forwardSlices,backwardSlices: similar to the corresponding properties onValue.
Paths
This feature is experimental and subject to change. Use at your own risk.
A Path represents a single possible control-flow path through a function,
where a path is a sequence of Expressions and Statements.
Properties
Iterators
- Every
Expression/Statement: theExpression/Statements that may be executed along this path.
Examples
The following query finds all of the functions that write to the balances
storage variable but may not always be guarded by a require statement involving
the owner storage variable:
FIND
Contract contract,
Function function IN contract,
StorageWrite w IN function,
Path p IN w.incomingPaths,
WHERE
w.location == "balances[*]",
!EXISTS
RequireLike req IN p,
Expression e IN req.backwardSlices,
StorageRead rd IN e,
WHERE {
rd.location == "owner",
}
This would report results for code such as:
pragma solidity ^0.8.10;
contract Example {
address owner;
mapping(address => uint256) balances;
function f(bool a) external {
if (a) {
require(msg.sender == owner); // okay: access control
} else {
// not okay: msg.sender is not checked to be owner
}
balances[msg.sender] += 1;
}
}