|
|
|
@@ -3012,29 +3012,31 @@ Currently supported:
|
|
|
|
|
as the router reads it: a `V3_SWAP_EXACT_IN` path runs from the token it
|
|
|
|
|
spends to the token it buys, and a `V3_SWAP_EXACT_OUT` path from the token it
|
|
|
|
|
buys to the token it spends, so that step's input token is its path's last
|
|
|
|
|
token and its output token the first. A V4 swap action is read only in the
|
|
|
|
|
parameter shape deployed on mainnet and Sepolia, not in the newer one on
|
|
|
|
|
`v4-periphery` `main`, which adds a `minHopPriceX36` field. An action in any
|
|
|
|
|
other shape is not read, and its step is listed as
|
|
|
|
|
`V4 Swap (could not be decoded)`. Each step is named and read as the command
|
|
|
|
|
that the release of the router at that address runs for its command type, as
|
|
|
|
|
that release's `contracts/libraries/Commands.sol` names it. The decoder reads
|
|
|
|
|
the type from the command byte with the mask that router uses: `0x1f` for
|
|
|
|
|
`UniversalRouterV1`, `0x3f` for `UniversalRouterV1_2_V2Support` and
|
|
|
|
|
`UniversalRouterV2`, and `0x7f` for `UniversalRouterV2_1_1` and
|
|
|
|
|
`UniversalRouterV2_1_2`. The allow-revert flag (`0x80`) therefore does not
|
|
|
|
|
change the command a step is read as. Releases run different commands for some
|
|
|
|
|
types: on `UniversalRouterV1` and `UniversalRouterV1_2_V2Support`, `0x10` to
|
|
|
|
|
`0x13` are NFT commands, where the later routers run `V4_SWAP`,
|
|
|
|
|
`V3_POSITION_MANAGER_PERMIT`, `V3_POSITION_MANAGER_CALL` and
|
|
|
|
|
`V4_INITIALIZE_POOL`. The decoder does not read those routers' NFT commands,
|
|
|
|
|
and lists each by its name there, for example `Seaport` for `SEAPORT` (`0x10`
|
|
|
|
|
on `UniversalRouterV1`). A type a release names no command for is listed by
|
|
|
|
|
its number, for example `Command 0x0e` on `UniversalRouterV1`, which has no
|
|
|
|
|
`BALANCE_CHECK_ERC20` and reverts on it. The router reverts the whole
|
|
|
|
|
transaction when a step fails, unless the step's command byte has that flag
|
|
|
|
|
set and its command is one the router lets fail, as each release's
|
|
|
|
|
`contracts/base/Dispatcher.sol` shows: on `UniversalRouterV2`,
|
|
|
|
|
token and its output token the first. The router reads a path as one token
|
|
|
|
|
address followed by whole hops of a 3-byte fee and a token address, and
|
|
|
|
|
ignores any bytes after the last hop, so the decoder does not read a path with
|
|
|
|
|
such bytes. A V4 swap action is read only in the parameter shape deployed on
|
|
|
|
|
mainnet and Sepolia, not in the newer one on `v4-periphery` `main`, which adds
|
|
|
|
|
a `minHopPriceX36` field. An action in any other shape is not read, and its
|
|
|
|
|
step is listed as `V4 Swap (could not be decoded)`. Each step is named and
|
|
|
|
|
read as the command that the release of the router at that address runs for
|
|
|
|
|
its command type, as that release's `contracts/libraries/Commands.sol` names
|
|
|
|
|
it. The decoder reads the type from the command byte with the mask that router
|
|
|
|
|
uses: `0x1f` for `UniversalRouterV1`, `0x3f` for
|
|
|
|
|
`UniversalRouterV1_2_V2Support` and `UniversalRouterV2`, and `0x7f` for
|
|
|
|
|
`UniversalRouterV2_1_1` and `UniversalRouterV2_1_2`. The allow-revert flag
|
|
|
|
|
(`0x80`) therefore does not change the command a step is read as. Releases run
|
|
|
|
|
different commands for some types: on `UniversalRouterV1` and
|
|
|
|
|
`UniversalRouterV1_2_V2Support`, `0x10` to `0x13` are NFT commands, where the
|
|
|
|
|
later routers run `V4_SWAP`, `V3_POSITION_MANAGER_PERMIT`,
|
|
|
|
|
`V3_POSITION_MANAGER_CALL` and `V4_INITIALIZE_POOL`. The decoder does not read
|
|
|
|
|
those routers' NFT commands, and lists each by its name there, for example
|
|
|
|
|
`Seaport` for `SEAPORT` (`0x10` on `UniversalRouterV1`). A type a release
|
|
|
|
|
names no command for is listed by its number, for example `Command 0x0e` on
|
|
|
|
|
`UniversalRouterV1`, which has no `BALANCE_CHECK_ERC20` and reverts on it. The
|
|
|
|
|
router reverts the whole transaction when a step fails, unless the step's
|
|
|
|
|
command byte has that flag set and its command is one the router lets fail, as
|
|
|
|
|
each release's `contracts/base/Dispatcher.sol` shows: on `UniversalRouterV2`,
|
|
|
|
|
`UniversalRouterV2_1_1` and `UniversalRouterV2_1_2`, `PERMIT2_PERMIT`,
|
|
|
|
|
`PERMIT2_PERMIT_BATCH`, `BALANCE_CHECK_ERC20`, `V3_POSITION_MANAGER_PERMIT`,
|
|
|
|
|
`V3_POSITION_MANAGER_CALL`, `V4_INITIALIZE_POOL`, `V4_POSITION_MANAGER_CALL`
|
|
|
|
@@ -3098,9 +3100,9 @@ Currently supported:
|
|
|
|
|
`CONTRACT_BALANCE` and the router held no WETH from an earlier step when the
|
|
|
|
|
`WRAP_ETH` ran: after two `WRAP_ETH`s of 0.5 ETH into the router, a swap of 1
|
|
|
|
|
WETH from it reads as leaving the WETH there. A V2 or V3 exact-out step paid
|
|
|
|
|
from the router spends at most its `amountInMax`, an amount the calldata does
|
|
|
|
|
not state, so the decoder counts it as spending nothing the router holds. A
|
|
|
|
|
`SETTLE` of `OPEN_DELTA` (zero), and a `SETTLE_ALL`, pay only what the step
|
|
|
|
|
from the router spends an amount the calldata does not state, at most its
|
|
|
|
|
`amountInMax`, so the decoder counts it as spending nothing the router holds.
|
|
|
|
|
A `SETTLE` of `OPEN_DELTA` (zero), and a `SETTLE_ALL`, pay only what the step
|
|
|
|
|
still owes of their token when they run. The decoder takes that to be the
|
|
|
|
|
amounts the step's swap actions state they spend of that token only when every
|
|
|
|
|
action in the step could be read, every swap action names the token it spends
|
|
|
|
@@ -3201,16 +3203,16 @@ Currently supported:
|
|
|
|
|
input or one of whose `SETTLE`s or `SETTLE_ALL`s it cannot read, which the
|
|
|
|
|
router still runs; a V2 or V3 exact-in or exact-out step or a
|
|
|
|
|
`PERMIT2_TRANSFER_FROM` whose input it cannot read, such as a V3 step whose
|
|
|
|
|
path is shorter than one token address; every `PERMIT2_TRANSFER_FROM_BATCH`;
|
|
|
|
|
every `EXECUTE_SUB_PLAN`, wherever it stands; and every step it fails on. Each
|
|
|
|
|
such step gives one `Moved from the sender` line among those, reading
|
|
|
|
|
`Unknown (could not be decoded)`. That line, or any line for a token the
|
|
|
|
|
decoder does not know, leaves no `Amount` line, whose figure might be too low,
|
|
|
|
|
and such a step before a `PERMIT2_PERMIT` keeps the permit's amount from
|
|
|
|
|
standing. Then each `PERMIT2_TRANSFER_FROM` but one into the router, in step
|
|
|
|
|
order, gives three lines: `Moved from the sender`, the amount it moves, for
|
|
|
|
|
example `1000000.0000 USDT`; `Token moved`, giving the token's address as the
|
|
|
|
|
`Token In` line does; and `Moved to`, which reads
|
|
|
|
|
path is shorter than one token address or has bytes after its last hop; every
|
|
|
|
|
`PERMIT2_TRANSFER_FROM_BATCH`; every `EXECUTE_SUB_PLAN`, wherever it stands;
|
|
|
|
|
and every step it fails on. Each such step gives one `Moved from the sender`
|
|
|
|
|
line among those, reading `Unknown (could not be decoded)`. That line, or any
|
|
|
|
|
line for a token the decoder does not know, leaves no `Amount` line, whose
|
|
|
|
|
figure might be too low, and such a step before a `PERMIT2_PERMIT` keeps the
|
|
|
|
|
permit's amount from standing. Then each `PERMIT2_TRANSFER_FROM` but one into
|
|
|
|
|
the router, in step order, gives three lines: `Moved from the sender`, the
|
|
|
|
|
amount it moves, for example `1000000.0000 USDT`; `Token moved`, giving the
|
|
|
|
|
token's address as the `Token In` line does; and `Moved to`, which reads
|
|
|
|
|
`The V2 pair the next swap spends` for a hop and `The sender` for `address(1)`
|
|
|
|
|
on every router but `UniversalRouterV1`, and otherwise gives the address. A
|
|
|
|
|
move into the router needs none of them, because its `Paid to` line and
|
|
|
|
@@ -3218,14 +3220,14 @@ Currently supported:
|
|
|
|
|
where it goes, and so its amount is shown once. These lines change neither the
|
|
|
|
|
`Paid to` lines nor the minimum's label. A step goes unread when its recipient
|
|
|
|
|
does not decode as an address, when it is a V3 swap step whose path is shorter
|
|
|
|
|
than one token address, or when it is a command the decoder does not read:
|
|
|
|
|
every command other than `PERMIT2_PERMIT`, `PERMIT2_TRANSFER_FROM`,
|
|
|
|
|
`V2_SWAP_EXACT_IN`, `V2_SWAP_EXACT_OUT`, `V3_SWAP_EXACT_IN`,
|
|
|
|
|
`V3_SWAP_EXACT_OUT`, `V4_SWAP`, `SWEEP`, `TRANSFER`, `PAY_PORTION`,
|
|
|
|
|
`PAY_PORTION_FULL_PRECISION`, `ACROSS_V4_DEPOSIT_V3`, `WRAP_ETH`,
|
|
|
|
|
`UNWRAP_WETH` and `BALANCE_CHECK_ERC20` (`PERMIT2_TRANSFER_FROM_BATCH`,
|
|
|
|
|
`EXECUTE_SUB_PLAN` and the NFT commands among them), or a type its release
|
|
|
|
|
names no command for.
|
|
|
|
|
than one token address or has bytes after its last hop, or when it is a
|
|
|
|
|
command the decoder does not read: every command other than `PERMIT2_PERMIT`,
|
|
|
|
|
`PERMIT2_TRANSFER_FROM`, `V2_SWAP_EXACT_IN`, `V2_SWAP_EXACT_OUT`,
|
|
|
|
|
`V3_SWAP_EXACT_IN`, `V3_SWAP_EXACT_OUT`, `V4_SWAP`, `SWEEP`, `TRANSFER`,
|
|
|
|
|
`PAY_PORTION`, `PAY_PORTION_FULL_PRECISION`, `ACROSS_V4_DEPOSIT_V3`,
|
|
|
|
|
`WRAP_ETH`, `UNWRAP_WETH` and `BALANCE_CHECK_ERC20`
|
|
|
|
|
(`PERMIT2_TRANSFER_FROM_BATCH`, `EXECUTE_SUB_PLAN` and the NFT commands among
|
|
|
|
|
them), or a type its release names no command for.
|
|
|
|
|
|
|
|
|
|
### Non-Goals Forever
|
|
|
|
|
|
|
|
|
|