fix: a swap's WETH minimum reads as ETH only when all its WETH reaches the UNWRAP_WETH (closes #642)
check / check (push) Canceled after 0s
e2e / e2e-chrome (push) Canceled after 0s
e2e / e2e-firefox (push) Canceled after 0s

An UNWRAP_WETH unwraps whatever WETH the router holds when it runs. A
TRANSFER, PAY_PORTION or PAY_PORTION_FULL_PRECISION of WETH to anyone but
the router between the swap and the UNWRAP_WETH may pay out part of the
swap's WETH, and a WRAP_ETH into the router may put other WETH in place of
WETH already paid out; after either, the swap now reads as ETH with no
minimum. An UNWRAP_WETH into the router followed by a WRAP_ETH of all the
router's ETH to anyone else pays the output out as WETH again, so the swap
reads as WETH, with no minimum. README Display Consistency says the same.

Model: opus-5-5
This commit is contained in:
2026-10-20 15:34:11 +00:00
parent 4472746b89
commit 6a878d6836
3 changed files with 163 additions and 30 deletions
+20 -11
View File
@@ -1260,17 +1260,26 @@ runs (Transaction Decoding below gives what the router holds). The router
unwraps only the WETH it holds, so WETH that step paid to the user, or to anyone
else, stays WETH: a swap that pays the router WETH, then a swap that pays the
user WETH, then an unwrap, shows WETH with the second swap's minimum. The
minimum reads in ETH when that step paid all its WETH to the router. When it
paid only part of it to the router, as a V4 step does that `TAKE`s some of its
WETH to the user and the rest to the router, or paid the router WETH beside a
payout the decoder cannot read, the swap shows ETH with no minimum: the decoder
does not count how much of that step's minimum reaches the router, nor read the
`UNWRAP_WETH`'s own minimum. A later step that sets the output side sets it
anew. Otherwise `Token Out` and `Min. received` keep the output side's own token
and figure, whether the swap was paid in ETH or in a token: a V2 exact-out swap
that buys USDC and then unwraps the WETH it did not spend shows USDC. The token
permission warning on the signature screen has its own amount wording, including
`Unknown`; the SignApproval section below describes it.
minimum reads in ETH when that step paid all its WETH to the router and no step
between it and the `UNWRAP_WETH` is a `TRANSFER`, `PAY_PORTION` or
`PAY_PORTION_FULL_PRECISION` of WETH to anyone but the router, or a `WRAP_ETH`
into the router. Such a step may pay out WETH the router holds, or put other
WETH in place of WETH an earlier step paid out. With such a step, or when that
step paid only part of its WETH to the router, as a V4 step does that `TAKE`s
some of its WETH to the user and the rest to the router, or paid the router WETH
beside a payout the decoder cannot read, the swap shows ETH with no minimum: the
decoder does not count how much of that step's minimum reaches the
`UNWRAP_WETH`, nor read the `UNWRAP_WETH`'s own minimum. After an `UNWRAP_WETH`
that pays the output side's WETH to the router as ETH, a `WRAP_ETH` of
`CONTRACT_BALANCE` to anyone but the router, while the router still holds ETH,
pays the output out as WETH again: the swap shows WETH with no minimum, as the
decoder does not count what steps between the two pay out of that ETH. A later
step that sets the output side sets it anew. Otherwise `Token Out` and
`Min. received` keep the output side's own token and figure, whether the swap
was paid in ETH or in a token: a V2 exact-out swap that buys USDC and then
unwraps the WETH it did not spend shows USDC. The token permission warning on
the signature screen has its own amount wording, including `Unknown`; the
SignApproval section below describes it.
The swap's `Deadline` line is the router's deadline as a UTC date and time, e.g.
`2026-02-27 08:25:51`. A JavaScript date reaches only to 275760-09-13 00:00:00