fix: a V4 SETTLE of ETH paid from the router reads as moved from the sender (closes #682)
V4Router pays a SETTLE of ETH from the router's own ETH, whichever payer it names. The router holds the transaction's value. So a SETTLE of ETH that names the router as payer now counts as paid by the user. When an earlier step left ETH in the router, such a SETTLE gets lines of its own. Its line reads "Up to" and its amount, and that amount never joins the Amount total. A SETTLE of CONTRACT_BALANCE reads as an amount the decoder does not know. One existing row in tests/uniswapRecipient.test.js now expects the ETH lines. Its SETTLE spends all the router's ETH, the transaction's value included. Model: opus-5-5
This commit is contained in:
@@ -3439,6 +3439,77 @@ describe("uniswap decoder", () => {
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
// https://git.eeqj.de/sneak/AutistMask/issues/682 — V4 pays a SETTLE
|
||||
// of ETH from the router's own ETH, whichever payer the SETTLE names,
|
||||
// and the router holds the transaction's value. On next at 36b2002 a
|
||||
// SETTLE of 1 ETH that names the router as payer gave no ETH line.
|
||||
describe("a V4 SETTLE of ETH that names the router as payer", () => {
|
||||
const ONE_ETH = 1000000000000000000n;
|
||||
// A V4 swap of `amount` of ETH for USDC. The SETTLE names the
|
||||
// router as payer.
|
||||
const v4EthFromRouter = (amount) =>
|
||||
encodeV4Swap(
|
||||
new Uint8Array([
|
||||
V4_SWAP_EXACT_IN_SINGLE_ID,
|
||||
V4_SETTLE_ID,
|
||||
V4_TAKE_ALL_ID,
|
||||
]),
|
||||
[
|
||||
encodeV4ExactInSingle(ZERO_ADDR, USDC_ADDR, amount, 1n),
|
||||
settle(ZERO_ADDR, amount, false),
|
||||
encodeV4TakeAll(USDC_ADDR, 1n),
|
||||
],
|
||||
);
|
||||
|
||||
test("after a V3 exact-in of 600 USDT, shows the 1 ETH moved from the sender", () => {
|
||||
const result = decodeSteps(
|
||||
[0x00, 0x10],
|
||||
[V3_600, v4EthFromRouter(ONE_ETH)],
|
||||
);
|
||||
expect(linesBetweenTokens(result)).toEqual([
|
||||
["Amount", "600.0000 USDT"],
|
||||
["Moved from the sender", "1.0000 ETH"],
|
||||
["Token moved", "ETH"],
|
||||
["Moved to", "The swap step that spends it"],
|
||||
]);
|
||||
});
|
||||
|
||||
// The UNWRAP_WETH leaves ETH in the router. The SETTLE may spend
|
||||
// that ETH before the transaction's value.
|
||||
test("after an UNWRAP_WETH into the router, shows at most 1 ETH moved from the sender", () => {
|
||||
const result = decodeSteps(
|
||||
[0x00, 0x0c, 0x10],
|
||||
[
|
||||
encodeV3SwapExactIn(ROUTER_ADDR, USDT_600, 1n, [
|
||||
USDT_ADDR,
|
||||
WETH_ADDR,
|
||||
]),
|
||||
encodeWrapEth(ROUTER_ADDR, 0n), // UNWRAP_WETH, same encoding
|
||||
v4EthFromRouter(ONE_ETH),
|
||||
],
|
||||
);
|
||||
expect(linesBetweenTokens(result)).toEqual([
|
||||
["Amount", "600.0000 USDT"],
|
||||
["Moved from the sender", "Up to 1.0000 ETH"],
|
||||
["Token moved", "ETH"],
|
||||
["Moved to", "The swap step that spends it"],
|
||||
]);
|
||||
});
|
||||
|
||||
test("after a WRAP_ETH of 0.5 ETH, adds the SETTLE's 0.5 ETH to the Amount line", () => {
|
||||
const result = decodeSteps(
|
||||
[0x0b, 0x10],
|
||||
[
|
||||
encodeWrapEth(ROUTER_ADDR, ONE_ETH / 2n),
|
||||
v4EthFromRouter(ONE_ETH / 2n),
|
||||
],
|
||||
);
|
||||
expect(linesBetweenTokens(result)).toEqual([
|
||||
["Amount", "1.0000 ETH"],
|
||||
]);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
// https://git.eeqj.de/sneak/AutistMask/issues/359 — the output half, in
|
||||
|
||||
Reference in New Issue
Block a user