Useful Detector Patterns
This page will find common patterns used when developing custom Aderyn detectors.
Check out the official Aderyn GitHub repository for more examples of detectors and design patterns.
Traversing the Abstract Syntax Tree (AST)
When writing a detector, a typical pattern is to find an AST node (by getting it from the WorkspaceContext
and then traverse the tree to its parent node or a child node for more information.
An example of traversing up the tree to parent nodes is that you have a specific VariableDeclaration
but want to know which ContractDefinition
it is defined in. To do that, you must traverse up the tree.
Conversely, suppose you have a ContractDefinition
and want to find all the state variable VariableDeclaration
nodes defined within it. In that case, you must traverse down the tree from there ContractDefinition
to its children.
Aderyn provides useful patterns for traversing up and traversing down the tree from any AST node.
Traversing Down
Patterns available to you:
Extractor
Pattern - Get all descendents of a particular type from the current AST Node, regardless of depth..children()
- Get the immediate children Nodes of the current AST Node/.
1. Extractor
Pattern
From any ASTNode, you can extract all descendants of any particular Node type.
For example, to extract all VariableDeclaration
nodes from a ContractDefinition
node, the code would look like this:
Note that this obtains all VariableDeclaration
nodes within that ContractDefinition
, not just its immediate children. The full list of extractors is defined in extractor.rs
.
2. .children()
From any ASTNode, get the immediate child nodes.
For example, take this Counter contract:
The immediate children of the Counter
ContractDefinition
is:
uint256 public number;
-VariableDeclaration
function setNumber(uint256 newNumber) public
-FunctionDefinition
function increment() public
-FunctionDefinition
So this code will return those children:
Traversing Up
Patterns available to you:
.parent(WorkspaceContext)
- From the current AST Node, get its parent AST Node..closest_ancestor_of_type(WorkspaceContext, NodeType)
- From the current node, traverse up the AST until you find an ancestor of a particular NodeType..ancestral_line(WorkspaceContext)
- Get the entire ancestry chain from the current node to theSourceUnit
node.
1. .parent(WorkspaceContext)
From any AST Node, get the immediate parent node. For example, from a ContractDefinition
node, .parent()
will return the SourceUnit
parent.
2. .closest_ancestor_of_type(WorkspaceContext, NodeType)
From an AST Node, traverse upwards until an ancestor of a particular NodeType is found.
For example, from a FunctionDefinition
, find the SourceUnit
ancestor.
3. .ancestral_line(WorkspaceContext)
From an AST Node, get the entire chain of ancestors up to the SourceUnit
.
For example, from a FunctionDefinition
, .ancestral_line(context)
will return all ancestor nodes in an array, starting with the closest all the way to the SourceUnit
.
Last updated