acuarica / evm

A Symbolic Ethereum Virtual Machine (EVM) bytecode interpreter, parser and decompiler, along with several other utils for programmatically extracting information from EVM bytecode.
https://acuarica.github.io/evm/
MIT License
62 stars 9 forks source link

Fix `RangeError: Maximum BigInt size exceeded` in `Exp` #129

Closed acuarica closed 2 weeks ago

acuarica commented 3 months ago

When analyzing contract 0xEC702942609FaD2afC1489277d918611f0e17ceb, the following error is raised

RangeError: Maximum BigInt size exceeded

How to reproduce it

Run

$ sevm abi 0xEC702942609FaD2afC1489277d918611f0e17ceb
RangeError: Maximum BigInt size exceeded

After further investigation, the error stack is

RangeError: Maximum BigInt size exceeded
    at Exp.eval (<path>/evm/dist/src/ast/alu.js:122:47)
    at Local.eval (<path>/evm/dist/src/ast/index.js:140:66)
    at new Jumpi (<path>/evm/dist/src/ast/flow.js:41:30)
    at FrontierStep.JUMPI (<path>/evm/dist/src/step.js:713:24)
    at EVM.exec (<path>/evm/dist/src/evm.js:123:40)
    at EVM.run (<path>/evm/dist/src/evm.js:92:18)
    at new Contract (<path>/evm/dist/src/index.js:59:17)
    at Object.handler (file://<path>/evm/bin/sevm.mjs:165:32)

This issue is a follow up of https://github.com/acuarica/evm/issues/125, where some errors were reported when running sevm on a large contract dataset. The other errors encountered in the dataset were (these are already fixed)

acuarica commented 3 months ago

Creating a smaller contract based on 0xEC702942609FaD2afC1489277d918611f0e17ceb, the following contract causes this issue

interface IERC20 {
    function decimals() external view returns (uint256);
}

contract Test {
    function truToToken() external view returns (uint256) {
        return 10**IERC20(0xdAC17F958D2ee523a2206206994597C13D831ec7).decimals();
    }
}

The CFG for this contract (it was generated by temporarily patching the Exp eval to avoid the error) looks like

image

On pc 51 you can see the Exp AST node 0xa ** 0x313ce56700000000000000000000000000000000000000000000000000000000, which is causing the issue. The 0x313ce567 value is a function selector for decimals()

$ cast sig 'decimals()'
0x313ce567

This 0x313ce567 value was first moved into memory to perform the staticcall on pc 165. All of this heavily implies that the STATICCALL (and CALL and DELEGATECALL) steps need to invalidate previous memory locations.