Add CALL_TARGET command #449
Draft
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Proposal: Add CALL_TARGET Command
TLDR
Add a new
CALL_TARGETCommand that enables users to make a custom call at any time during the execution.Overview
The UniversalRouter provides significant efficiency for interacting across Uniswap versions & Permit2 approvals. Users can in a single transaction do any number of approvals/transfers/swaps across any number of Uniswap Pools (v2/v3/v4). This enables even simple EOAs the power to batch financial transactions.
Problem: Custom Logic with Uniswap
If an EOA wants to interact with a different contract not supported by the UniversalRouter however, they cannot do so and must rely on some other external periphery contract.
Solution: Interoperability via Universal Router
The
CALL_TARGETcommand enables calling a custom contract at any time during the UniversalRouter's execution. Adding aCALL_TARGETcommand enables great interoperability between Uniswap & custom contracts by simply encoding a custom call at any point between the command execution.This unlocks several use cases:
Our team at ETHDenver significantly used this feature in our Veraswap MVP to easily combine Uniswap with post-swap bridging via Hyperlane or Superchain Interop.
Purpose of PR
Purposes for this PR is to get some feedback of the
CALL_TARGETcommand:CALL_TARGETcommand?Implementation
CALL_TARGET Command
We update the Commands.sol with a custom
CALL_TARGETwith the0x22flag.Call Target Decoder
We add the CalldataCallTargetDecoder.sol library to decode the call target params. This library was added to avoid editing the CallDataDecoder.sol in v4-periphery.
We decode the following params
abi.decode(params, (address, uint256, bytes)):address: target addressuint256: call valuebytes: call dataDispatcher Logic
The Dispatcher.sol contract implements the core of the Universal Router and is responsible for decoding and executing the logic of each command. At the bottom of the
executecommand, we add the implementation forCALL_TARGETright before the// placeholder area for commands 0x22-0x3fcomment.The Dispatcher implementation does the following:
Security Considerations
The main reason we can add a custom
CALL_TARGETwith little security changes is because one main assumption is that the UniversalRouter does not hold funds between transactions (anyone canSWEEP) and that approvals are managed via Permit2.For example, an attacker can have the UniversalRouter call
ERC20.approve(<attacker>, MAX_UINT256)to try to steal any balances from the router, but the same can already be achieved by a simpleSWEEPcommand. The main risk is managing user approvals, and since they are exclusively managed via Permit2, banning the Permit2 address makes any attack on 3rd party approvals impossible.Ban Permit2
The only security check is that the target is NOT Permit2. This is critical since token transfers to and from UniversalRouter are managed via Permit2. If Permit2 was allowed, a attacker could call the Permit2 contract and steal a 3rd party's approved funds.
Interactions with Permit2 contract are tightly controlled by the PERMIT2 commands and always use the proper caller.
Banning Other Addresses
Other addresses could also be banned for good measure but do not seem necessary: