feat: flatten nested redeemDelegations into outer call#29959
feat: flatten nested redeemDelegations into outer call#29959matthewwalsh0 wants to merge 2 commits into
Conversation
When a nested transaction in a delegated transaction is itself a redeemDelegations call, merge its permission contexts, modes, and calldatas into the outer redeemDelegations call as additional slots rather than wrapping it inside another delegation. This avoids the gas cost of an extra delegation layer when the nested call is already self-authorised.
…try point Mirror the extension by introducing a single convertTransactionToRedeemDelegations function in app/util/transactions/delegation.ts that handles caveats, executions, optional EIP-7702 authorization, and unconditional flattening of nested redeemDelegations. - getDelegationTransaction is now a thin wrapper that defaults value to 0x0 - Delegation7702PublishHook uses the central function, removing ~100 lines of duplicated delegation/execution/caveat assembly - Flattening of nested redeemDelegations is automatic for every caller
🔍 Smart E2E Test Selection
click to see 🤖 AI reasoning detailsE2E Test Selection:
These changes directly affect:
The E2E tests covering these paths are all under
The changes don't affect general wallet navigation, account management, network selection, swap/bridge flows, or other areas. The risk is medium because the refactoring is significant but well-tested with unit tests, and the E2E tests for the most critical paths (gas fee tokens) are currently skipped. Performance Test Selection: |
|



Description
Two related changes to mobile's delegation transaction assembly:
1. Central
convertTransactionToRedeemDelegationsMirroring
metamask-extension, this PR introduces a singleconvertTransactionToRedeemDelegationsfunction inapp/util/transactions/delegation.tsthat all delegation flows route through. It accepts optionalcaveats,additionalExecutions,delegatee,delegationSignature, andskipAuthorizationso each caller can keep its own semantics while sharing one assembly path.getDelegationTransactionis now a thin wrapper that defaultsvalueto0x0.Delegation7702PublishHookuses the central function, removing ~100 lines of duplicated delegation/execution/caveat assembly.2. Automatic flattening of nested
redeemDelegationsWhen a delegated transaction has a nested transaction that is itself a
redeemDelegationscall to theDelegationManager, the previous client wrapped it inside another delegation. The resulting on-chain call had the shape:This added an entire delegation layer (signature recovery, caveat enforcement, an extra
CALLinto theDelegationManager) on top of an already self-authorised redemption.convertTransactionToRedeemDelegationsnow detects that case and merges the inner call'spermissionContexts,modes, andcalldatasinto the outer call as additional parallel slots:The outer delegation is rebuilt to authorise only the non-
redeemDelegationsnested transactions, so its caveats (exactExecution/exactExecutionBatch+limitedCalls(1)) remain tight over the slots the outer delegate actually executes.Detection is gated on (a) the nested target equalling the chain's
DelegationManageraddress fromgetDeleGatorEnvironment, (b) the calldata starting with theredeemDelegationsselector (0xcef6d209), and (c) successful ABI decode of the(bytes[], bytes32[], bytes[])payload. Any failure falls back to the existing nested-delegation shape.Because flattening lives inside
convertTransactionToRedeemDelegations, it now applies automatically to every caller, includingDelegation7702PublishHook.Changelog
CHANGELOG entry: null
Related issues
Fixes:
Manual testing steps
```gherkin
Feature: Delegated transaction with a nested redeemDelegations
Scenario: client builds the outer redeemDelegations call
Given a transaction whose nestedTransactions[i] targets the DelegationManager with a redeemDelegations calldata
When getDelegationTransaction runs
Then the returned transaction calls redeemDelegations once
And the bytes[] permissionContexts argument contains the outer delegation plus the inner permissionContext as additional slots
And the bytes32[] modes and bytes[] calldatas arguments are extended in lockstep
And the outer delegation's caveats cover only the remaining (non-redeem) nested transactions
```
Pre-merge author checklist
Pre-merge reviewer checklist