Skip to content

Glamsterdam (EIP-8037/8038) gas invariants review #6858

Open
4 of 5 issues completed
Open

Description

@Amxx

Tracking issue for reviewing contracts/ (mocks excluded) against the Glamsterdam gas changes, EIP-8037 (state-creation gas, reservoir) and EIP-8038 (state access repricing). The review used the invariants published in ethereum/glamsterdam-gas-invariants.

Unless stated otherwise, findings are inferred from the code and the spec gas table. The paymaster findings were measured on EDR 0.25 with the amsterdam hardfork (#6838).

Findings (sub-issues)

  1. PaymasterERC20Guarantor (PaymasterERC20Guarantor: default postOp gas floor too low after Glamsterdam, can strand guarantor prefund #6863): the guaranteed postOp pulls the cost from the user, whose balance (and finite allowance) are cold first writes in the transaction. EIP-8038 raises those by ~7.1k each. Measured on EDR 0.25 (Test guaranteed refunds at the postOp gas floor #6866): with a finite allowance, postOp uses 41,575 of the 45,000 floor, down from a ~17.6k margin before the fork to ~3.4k. A token with heavier transfer logic would run out of gas and strand the guarantor's prefund (INV-4 / INV-7). Fix in Raise default _guaranteedPostOpCost to cover EIP-8038 repricing #6869: default _guaranteedPostOpCost() raised from 15,000 to 30,000.

Closed:

Notes (no action needed in this repo)

  • INV-3, effect on downstream code: ERC721Utils, ERC1155Utils, ERC1363Utils and Address turn empty revert data into custom errors. Every branch here reverts, so nothing breaks in this repo. But downstream "empty revert data means out of gas" heuristics no longer hold.
  • INV-4, values signed before the fork: ForwardRequest.gas and ERC-4337 gas limits signed before the fork may be too low afterwards. In ERC2771Forwarder.executeBatch that burns the nonce.

Checked, nothing found

  • INV-3, CREATE results: every create/create2 result is checked (Clones, ERC1967Clones, Create2, RelayedCall, SimulateCall).
  • INV-5: no contract bills by subtracting two gasleft() readings.
  • INV-2: ReentrancyGuard rests at 1 and goes 1 → 2 → 1. The transient variants and Initializable don't refill either.
  • INV-7: no transfer or send calls.
  • Execution paths: Governor, GovernorTimelockAccess, TimelockController and AccessManager revert on any failed call.
  • Harmless try/catch:
    • The try/catch in GovernorTimelockAccess._cancel is harmless: only the governor could run the leftover operation.
    • The try/catch in GovernorVotes.clock cannot be exploited: starving a call that cheap leaves too little gas for propose.

Not covered

  • Off-chain components: relayers and bundlers integrating these contracts.
  • Settings of deployed contracts.
  • Rules still under discussion: INV-1, INV-2, INV-3 and INV-5 depend on parts of the spec that may change (e.g. EIPs PR #12581). The fixes proposed should work under either rule.

Metadata

Metadata

Assignees

No one assigned

    Labels

    metasecurityPull requests that address a security vulnerability

    Type

    No type

    Projects

    No projects

      Milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions