Skip to content

account/paymaster gas optimization#250

Closed
gonzaotc wants to merge 1 commit into
OpenZeppelin:masterfrom
gonzaotc:gas/paymaster
Closed

account/paymaster gas optimization#250
gonzaotc wants to merge 1 commit into
OpenZeppelin:masterfrom
gonzaotc:gas/paymaster

Conversation

@gonzaotc

@gonzaotc gonzaotc commented Jul 16, 2026

Copy link
Copy Markdown
Contributor

Note

AI-generated with the Solidity Gas Optimizer skill. Findings were measured as positive gains and all tests still pass, but it's encouraged to review before merging to confirm behavior is unaffected.

Run

  • Measurement: Hardhat, solc 0.8.27, runs 200, via-IR false
  • Tests: Target-scoped: 82 passing (paymaster suite). The hot path runs through a predeploy EntryPoint that the gas reporter cannot isolate, so runtime was measured with a deterministic handleOps gasUsed probe over an identical userOp.
  • Scope:
    contracts/account/paymaster/
        PaymasterCore.sol
        PaymasterERC20.sol
        PaymasterERC20Guarantor.sol
        PaymasterERC721Owner.sol
        PaymasterSigner.sol
    

Results

One gas optimization candidate was found and applied, in a single commit keyed by the ID below. It's recommended to review it via the commits view.

ID Change Function Δ runtime /call Δ deploy gas
GAS-M-01 Build validation context in one abi.encodePacked PaymasterERC20._validatePaymasterUserOp −230 −12,343 ($PaymasterERC20Mock) / −5,625 ($PaymasterERC20GuarantorMock)

GAS-M-01 · Build validation context in one abi.encodePacked (PaymasterERC20._validatePaymasterUserOp)

  • What it does: Drops the intermediate context = abi.encodePacked(userOpHash, token, tokenPrice) and builds the returned blob in a single abi.encodePacked(userOpHash, token, tokenPrice, prefundAmount, prefunder, prefundContext) on the success path.
  • Why it's cheaper: abi.encodePacked is plain concatenation, so the old two-step form staged 84 bytes in memory then copied them again into the final blob. Encoding all six pieces once writes those bytes a single time, removing the intermediate allocation and copy on every ERC-20 sponsored operation and shrinking deploy code. The returned bytes are byte-for-byte identical and _postOp's decode offsets (0x00 hash, 0x20 token, 0x34 price, 0x54 prefundAmount, 0x74 prefunder, 0x88 prefundContext) are unchanged.
  • Tradeoff: None (safe idiom). No ABI, storage, or behavior change; the failure path still returns bytes(""). Cherry-picks independently as its own commit.

This optimization was found and measured by the Solidity Gas Optimizer skill; the commit message carries the measured deltas.

…encodePacked (-230/op, -12,343 deploy)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@gonzaotc gonzaotc closed this Jul 16, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant