Conversation
| export const eip7702AuthorizationStep: Step = { | ||
| name: 'eip-7702-authorization', | ||
| async run({ messenger, address, chainId, delegatorImplAddress }) { | ||
| const existing = await messenger.call( |
There was a problem hiding this comment.
I think existing might not be the best check. If can exist but be a wrong one (example lower nonce). Maybe checking if account is actually upgraded might be better. You can check how the existing upgrade account works and how it checks / saves the ones that are already upgraded.
Because if its already upgraded this step can be skipped altogether.
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, have a team admin enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 28b898f. Configure here.
8a1c399 to
0e3e0ab
Compare
| return 'already-done'; | ||
| } | ||
| throw new Error( | ||
| `Account ${address} is already delegated to ${existingDelegation}, which is not the configured delegator impl ${delegatorImplAddress}. Refusing to overwrite an existing EIP-7702 delegation.`, |
There was a problem hiding this comment.
This is not actually a delegation but the account is already upgraded to another smart account not delegation/metamask smart account.

Explanation
Adds 'Step 1' to the money account upgrade controller. This step submits EIP-7702 authorization.
The eip-7702-authorization step submits an EIP-7702 delegation-slot authorization to CHOMP so the Money Account is upgraded to a smart account pointed at the configured delegator impl. It first reads the account's on-chain code via eth_getCode: an empty response ('0x') means a plain EOA and the step proceeds; a 0xef0100 delegation that matches delegatorImplAddress short-circuits with 'already-done'; any other delegation address or unexpected bytecode throws, so the step never overwrites an existing delegation or operates on a regular contract.
For a plain EOA, the step fetches the current on-chain nonce via eth_getTransactionCount, signs the authorization { chainId, contractAddress: delegatorImplAddress, nonce } through KeyringController:signEip7702Authorization, splits the resulting 65-byte signature into { r, s, v, yParity }, and submits it to ChompApiService:createUpgrade (chainId and nonce as decimal strings, since that's the API's wire format).
References
Checklist
Note
Medium Risk
Touches upgrade orchestration and introduces network RPC + signature handling, so failures could block upgrades or cause incorrect CHOMP submissions if edge cases are missed.
Overview
Adds a new
eip-7702-authorizationstep toMoneyAccountUpgradeController’s upgrade sequence that checks on-chain code/nonce viaNetworkController, signs an EIP-7702 authorization viaKeyringController, splits the 65-byte signature, and submits it to CHOMP viaChompApiService:createUpgrade(skipping if already delegated and erroring if delegated elsewhere or the address is a contract).Updates the controller to persist init-time
chainId/delegatorImplAddressand pass them through the step context, expands allowed messenger actions, adds@metamask/network-controlleras a dependency, and extends unit tests (including a new comprehensive test suite for the EIP-7702 step).Reviewed by Cursor Bugbot for commit 82b60d8. Bugbot is set up for automated code reviews on this repo. Configure here.