Conversation
…3017-35090655430 sync: main into dev
* feat(paymaster): public Erc7677Paymaster.fetchTokenQuote and shared token cost helper Expose fetchTokenQuote(tokenAddress, entrypoint) on Erc7677Paymaster for the Candide and Pimlico providers, and add calculateUserOperationErc20TokenCost so the token cost math and its min-of-one floor live in one place, used by both paymaster classes. * fix(paymaster): wrap fetchTokenQuote transport and RPC failures as PAYMASTER_ERROR * feat(utils): accept v0.8 and v0.9 UserOperations in calculateUserOperationErc20TokenCost * refactor(utils): keep calculateUserOperationErc20TokenCost internal The shared helper still backs every token cost computation, but it is no longer part of the public API. Co-signers will read a finished operation's cost through a dedicated decoder instead. * fix(paymaster): fetchTokenQuote wraps non-PAYMASTER_ERROR AbstractionKitErrors Only rethrow AbstractionKitErrors already coded PAYMASTER_ERROR; anything else, such as an error from a custom transport, is wrapped so fetchTokenQuote keeps its documented PAYMASTER_ERROR contract. * refactor(paymaster): drop the public fetchTokenQuote createPaymasterUserOperation already returns the tokenQuote before signing, and decodeTokenQuote covers co-signers, so a standalone rate lookup adds public API without a use case. Keeps the shared token cost helper.
* feat(safe): decodeTokenPaymasterApprovals to read the paymaster approval from a UserOperation Returns every ERC-20 approve in a Safe UserOperation's batch whose spender is the operation's own paymaster, so signers who did not build the operation can see the token cap they are signing without the original TokenQuote. * fix(safe): only decode approvals from a delegatecall to the expected MultiSend A delegatecall runs the target's code in the Safe's context, so a MultiSend-shaped payload sent to any other contract could report approvals that never execute. decodeTokenPaymasterApprovals now throws BAD_DATA unless the delegatecall target is the MultiSend contract (overridable via overrides.multisendContractAddress). * refactor(safe): expose decodeTokenPaymasterApprovals as an account hook Mirror the prepend convention: decodeTokenPaymasterApprovalsStatic holds the logic and the instance method decodeTokenPaymasterApprovals implements the new DecodeTokenPaymasterApprovalsAccount interface, so paymaster-side code can read approvals from any account that supports it. * fix(safe): accept every official Safe MultiSend deployment when decoding approvals Operations built by other SDKs delegatecall MultiSendCallOnly (v1.3.0, v1.4.1, v1.5.0) rather than the SDK's default MultiSend, and were rejected. Accept the official deployments listed in safe-global/safe-deployments; the override now adds a custom deployment instead of replacing the default. * docs(safe): state that decoded approvals are matched by selector, not verified ERC-20 * fix(safe): reject batches with inner delegatecalls when decoding approvals An inner delegatecall runs arbitrary code in the Safe's context and could overwrite the paymaster allowance after a reported approve. Also let the DecodeTokenPaymasterApprovalsAccount hook take the MultiSend override. * fix(safe): report malformed approve calldata as BAD_DATA A batch entry with the approve selector but truncated arguments threw a raw ABI decode error. Wrap it in AbstractionKitError BAD_DATA with the original error as cause and the call's target as context. * feat(paymaster): decodeTokenQuote reads a finished operation's token payment offline Co-signers who did not build an operation can recover what it commits to pay: the paymaster's signed exchange rate and validity window from its paymaster data, and the allowance from the ERC-20 approval in callData, with no RPC. Supports Candide's (EntryPoint v0.6 to v0.9) and Pimlico's (v0.6 to v0.8) token paymasters, identified by their deployed addresses. maxTokenCost bounds what each paymaster contract can charge, including its post-operation overhead. Tests run against 24 real token-paid operations from mainnet and Sepolia, each checked against the amount the paymaster actually charged. * docs(paymaster): note that Candide's decoded token comes from the unverified approval * fix(paymaster): reject ambiguous Candide token approvals and pass the MultiSend override Candide's paymaster data names the token by slot, so approvals of more than one token to the paymaster leave the paid token undetermined offline; throw instead of picking the last. Forward overrides.multisendContractAddress to the account's approval decoder. * refactor(safe): keep decodeTokenPaymasterApprovals as the instance hook only Drop decodeTokenPaymasterApprovalsStatic and move its logic into the instance method that decodeTokenQuote calls, documenting it as the low-level account hook behind decodeTokenQuote. * refactor(paymaster): expose decodeTokenQuote as a static on the paymaster classes Erc7677Paymaster.decodeTokenQuote and CandidePaymaster.decodeTokenQuote replace the root-level function, next to createPaymasterUserOperation where developers look for token payment features. Static because decoding needs no paymaster URL or state, and it works on operations built by either class. * docs(paymaster): explain why the multi-token approval check covers both providers
CALIBUR_CANDIDE_V0_1_0_SINGLETON_ADDRESS pointed at an unofficial, unaudited Calibur deployment. Calibur7702Account defaults to Uniswap's official singleton and never used it.
#241) getUserOperationEip712Data_V9 fell back to 0xee8005d7..., and the JSDoc on both V9 helpers named old addresses. Neither has code outside Sepolia, so callers relying on the default hashed against the wrong verifying contract and failed with AA24. Default to 0x22939E83... instead, the address SafeMultiChainSigAccountV1 uses. Fixes #239
…ASH code (#243) The PaymasterMetadataV6/V7/V8 and SupportedERC20TokensAndMetadata* version aliases were never exported from the package entry point and have no internal users. BundlerErrorCode.INVALID_USEROPERATION_HASH has not been produced since #219 remapped -32601 to METHOD_NOT_FOUND. Also fix the Calibur paymasterFields JSDoc link, which named the old ExperimentalAllowAllPaymaster class.
|
Navigate logical layers of code changes, visualize relationships, and explore their blast radius. No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Essentials Run ID: 📒 Files selected for processing (2)
Included review availability: This review used your included allowance. 1 included review remains after this review. Your included PR review attempts over the past 7 days set your current allowance at 5 reviews per hour. 📝 WalkthroughWalkthroughVersion 0.4.3 adds offline token-quote decoding for supported Candide and Pimlico UserOperations. It adds Safe approval extraction, shares token-cost calculation across paymaster classes, changes the v0.9 Safe module default, and removes several API declarations. ChangesToken Quote Decoding
Priority: ⬇️ Low Estimated code review effort: 4 (Complex) | ~45 minutes Change: Feature Sequence Diagram(s)sequenceDiagram
participant Client
participant CandidePaymaster
participant decodeTokenQuote
participant SafeAccount
Client->>CandidePaymaster: Call decodeTokenQuote with account and operation
CandidePaymaster->>decodeTokenQuote: Forward operation and overrides
decodeTokenQuote->>SafeAccount: Decode paymaster-directed approvals
SafeAccount-->>decodeTokenQuote: Return matching approvals
decodeTokenQuote-->>CandidePaymaster: Return quote or null
CandidePaymaster-->>Client: Return quote or null
Suggested reviewers: Merge Risk: ⚪ Minimal · up to The reviewed Safe approval-decoding changes have no identified merge-blocking issue. Normal checks remain appropriate before merging. 🚥 Pre-merge checks | ✅ 3 | ❌ 2❌ Failed checks (2 warnings)
✅ Passed checks (3 passed)
A rabbit reads the quote in flight, Comment |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: abd8b599bf
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
decodeTokenPaymasterApprovals let a raw ABI decode error escape when a known MultiSend was delegatecalled with a truncated or malformed bytes argument. Wrap it in AbstractionKitError BAD_DATA with the original error as cause and the MultiSend target as context, as documented.
Summary by CodeRabbit