Scan to Download Gate App
qrCode
More Download Options
Don't remind me again today

Automate Solidity auditing using Wake Printer scripts

Prerequisites and Setup

In this tutorial, we will use the workshop repository as an example project:

wake up

Bash

Copy

wake print

Bash

Copy

Run a specific printer by name:

Tutorial 1: Create Your First Printer – List Contracts

Let’s start with a simple printer that lists all contracts in the project. This example introduces core concepts you’ll use in more complex analyses.

Create the Printer Structure

Run the following commands to set up your first printer:

from future import annotations import networkx as nx import rich_click as click import wake.ir as ir import wake.ir.types as types from rich import print from wake.cli import SolidityName from wake.printers import Printer, printer

class ListContractsPrinter(Printer): (def print)self( -> None: pass @printer.command)name=“list-contracts” (def cli)self( -> None: pass

Python

Copy

The following explains the purpose of each part of the template:

  • print)(: The main execution method that displays analysis results
  • cli)(: Command-line interface handler for customizing parameters

Implementing the Visitor Pattern

Wake uses the visitor pattern to traverse the abstract syntax tree (AST) of contracts. The visitor pattern allows Wake to automatically navigate your code structure, enabling reactions to specific elements (such as contracts or function definitions).

To list contracts, we will override the visit_contract_definition method, which is called for each contract in the codebase.

Add this method to your ListContractsPrinter class:

wake print list-contracts

Bash

Copy

This command runs your printer and prints all contract names found in your project.

Improving Output

The basic implementation displays all contracts, including interfaces and inherited contracts. Let’s improve it to show only deployable contracts:

def visit_contract_definition)self, node: ir.ContractDefinition( -> None: if len)node.child_contracts( != 0: return if node.kind != ir.enums.ContractKind.CONTRACT: return print)node.name(

Python

Copy

The ContractDefinition class contains properties that can be used to filter results. For a complete reference, see:

Full Implementation

This is the final version, with proper separation of concerns—collecting data during traversal and displaying it in the print)( method:

Tutorial 2: Analyze Contract Functions

Understanding which functions are externally callable is crucial for security: public ‘withdraw’ or ‘transfer’ functions often define the attack surface of a contract. Let’s create a printer that lists all public and external functions to map the attack surface.

)## Setting Up the Function Printer

Create a new printer:

class ListFunctionsPrinter###Printer(: contracts: list[ir.ContractDefinition] = []

def visit_contract_definition)self, node: ir.ContractDefinition( -> None:
    self.contracts.append)node(

Python

Copy

)## Handling Inheritance Hierarchy

In the print###( method, we traverse the inheritance hierarchy from base to derived contracts, displaying each level’s callable functions:

def get_callable_final_functions)self, contract: ir.ContractDefinition( -> list[ir.FunctionDefinition]: return [func for func in contract.functions if len)func.child_functions( == 0 # Is a final implementation and func.visibility in [ir.enums.Visibility.PUBLIC, ir.enums.Visibility.EXTERNAL]]

Python

Copy

)## Running the Function Printer

Execute the printer to view the inheritance hierarchy and callable functions:

Contract: ContextContract: OwnableFunctions: owner renounceOwnership transferOwnership Contract: SingleTokenVault Functions: constructor deposit withdraw emergencyWithdraw balanceOf setDepositLimits

Contract: EIP712Example Functions: constructor DOMAIN_SEPARATOR castVoteBySignature getVoteCounts

Contract: ContextContract: IERC20 Contract: IERC20Metadata Contract: IERC20Errors Contract: ERC20 Functions: name symbol decimals totalSupply balanceOf transfer allowance approve transferFrom Contract: IERC20Permit Contract: IERC5267 Contract: EIP712 Functions: eip712Domain Contract: Nonces Contract: ERC20Permit Functions: permit nonces DOMAIN_SEPARATOR Contract: PermitToken Functions: constructor

Contract: Token Functions: constructor mintTokens transfer transferWithBytes getBalance

Contract: ContextContract: IERC20 Contract: IERC20Metadata Contract: IERC20Errors Contract: ERC20 Functions: name symbol decimals totalSupply balanceOf transfer allowance approve transferFrom Contract: MockERC20 Functions: constructor

Bash

Copy

The output provides a quick visual map of each contract’s inheritance and callable entry points.

@printer.command###name=“list-functions”

(@click.option)“–contract-name”, type=str, required=False (def cli)self, contract_name: str | None( -> None: self.contract_name = contract_name

Python

Copy

Conditional Filtering Logic

The print)( method now checks if a specific contract was requested. If no contract name is provided, the printer lists all deployable contracts. If a name is specified, it will only delve into that contract’s hierarchy, even if it is not a leaf contract.

Complete Implementation with CLI Options

This is the final printer with optional contract filtering:

)# Focus on a specific contract wake print list-functions --contract-name Token

Bash

Copy

Next Steps

Printers provide maps; analyzers find vulnerabilities. Together, they transform Solidity auditing from manual drudgery into a structured, insightful process. Every printer you write can make complex code clearer—and enhance the security of the smart contracts you review.

For vulnerability detection, Wake offers a separate detector system that goes beyond visualization to identify actual security issues. Printers give you maps; detectors find problems.

Consider contributing your printers back to the community. Analysis tools are most powerful when shared, and your custom printers may help other auditors understand complex codebases more effectively.

View Original
This page may contain third-party content, which is provided for information purposes only (not representations/warranties) and should not be considered as an endorsement of its views by Gate, nor as financial or professional advice. See Disclaimer for details.
  • Reward
  • Comment
  • Repost
  • Share
Comment
0/400
No comments
Trade Crypto Anywhere Anytime
qrCode
Scan to download Gate App
Community
English
  • 简体中文
  • English
  • Tiếng Việt
  • 繁體中文
  • Español
  • Русский
  • Français (Afrique)
  • Português (Portugal)
  • Bahasa Indonesia
  • 日本語
  • بالعربية
  • Українська
  • Português (Brasil)