Ackee is finalizing an ERC-4337 detector to identify the use of forbidden opcodes and storage access, turning a very labor-intensive manual review into an automated process that reduces the chance of human error.

Let Wake detect ERC-4337 related vulnerabilities in your code. Want to get your code tested for free by our Wake ERC-4337 detector? Submit this deform!

The detector already found an issue in the Rhinestone modulekit examples project. The discovered finding shows that even when accessing a mapping using the correct key, the mapping may contain nested dynamic data structures that may trigger reading from forbidden storage slots. This example clearly shows the need of an automated tool that can discover such issues otherwise leading to denial-of-service for a smart account.

bytes memory validatorStorageData = $validator.data;

About Wake Framework

Wake is a Python-based framework for development and testing of Solidity smart contracts. It includes a static analysis engine to explore and report issues in Solidity code. Wake is developed and used by the Ackee Blockchain Security to perform smart contract audits – and it helped to discover a number of medium, high and critical vulnerabilities.

Develop, test, and write secure code using Wake inside VS Code via our extension: Tools for Solidity.

ERC-4337 forbidden opcodes and storage access

ERC-4337 defines a set of restrictions in the user operation validation phase that must be followed to protect user operation bundlers from denial of service attacks. The restrictions are fully described in ERC-7562.

The restrictions include:

  • forbidden opcodes and conditionally forbidden opcodes,
  • restricted access to storage of other contracts than the smart account being interacted with.

Ackee is finalizing an ERC-4337 detector that can analyze ERC-4337 validateUserOp function that serves as an entry point for the validation phase. All subsequently called functions are tested. The use of restricted opcodes is reported in the form of detections.

Detecting restricted storage access requires a more comprehensive approach. Storage access is only allowed to the slot A and slots keccak256(A || x) + offset, where A is the address of the smart account being interacted with, x is any bytes32 value, offset is a number up to 128 and || represents concatenation. The access to the slot A can only be achieved through assembly (the Yul language), while the second pattern (involving keccak256) is typical for accessing Solidity mappings with A as a key to the mapping.

Both problems involve the evaluation if a specific value (Yul sload and sstore argument, mapping key) is equal to the smart account address. The smart account address is always stored as a member (named sender) of the first argument of the validateUserOp. Thus, the problem may be re-defined as a verification if the given value depends on the sender of another variable defined elsewhere in the code. The dependent path may involve any number of function calls, re-assignments to new variables, or type casts.

The Wake ERC-4337 detector uses a Data Dependency Graph, a feature under active development, to analyze data relations between different parts of the code. The Data Dependency Graph is utilized in the ERC-4337 detector to achieve high precision of the reported detections.

Thanks to the ERC-4337 detector, it is very easy to detect the use of forbidden opcodes and storage accesses, which would be very labor-intensive to verify manually.

Get your code tested for free by our Wake ERC-4337 detector by submitting this deform!