`tokenInfo(null)` answers `{symbol: "ETH", decimals: 18}`, and the V4 arm of
`decode()` could take a step's `amountOutMin` while leaving `outputToken`
null, because the token assignment was gated on `if (v4.tokenOut)`. The
approval screen then named ETH as the output and formatted `Min. received` at
18 decimals for a swap whose output currency the calldata never stated.
Null is not how V4 spells native ETH. v4-core declares `type Currency is
address` and wraps `address(0)` for native ETH, and a `Currency` is
ABI-encoded as a plain address word, so every decode site here gets back the
truthy string `0x0000000000000000000000000000000000000000` for it — which
`tokenInfo()` already names ETH — and an UNWRAP_WETH output is caught
separately. Nothing that genuinely outputs ETH arrives as null; only a step
whose output currency did not decode does.
So a null output token is now treated as undetermined: `Token Out` reads
`Unknown (not named in the calldata)` and `Min. received` falls to the
base-unit refusal from
#340 instead of being scaled at 18.
A V4 step that supersedes an earlier step's `Min. received` without naming a
currency also clears the earlier step's token, so that figure is never read
against the token a previous hop named.
7.8 KiB
7.8 KiB