fix: a swap split across steps the user pays for shows every amount it spends (closes #625)
check / check (push) Canceled after 0s
e2e / e2e-chrome (push) Canceled after 0s
e2e / e2e-firefox (push) Canceled after 0s

The swap's Amount line took only the first swap step's amount. Each later
V2, V3 or V4 swap step the user pays for now adds what it spends of
Token In to that line, and one that spends another token gets Moved from
the sender, Token moved and Moved to lines of its own. Steps paid from
the router add nothing, and a PERMIT2_PERMIT keeps its own amount.

Model: opus-5-5
This commit is contained in:
2026-10-19 22:53:31 +00:00
committed by sneak
parent 5376723c41
commit 8382fab3b6
4 changed files with 365 additions and 64 deletions
+14 -1
View File
@@ -671,6 +671,7 @@ describe("any token left in the router is not received", () => {
v3SwapExactIn(MSG_SENDER, USDT_2000, USDC_1990, USDT, USDC),
),
left: tokenLine(WETH, "WETH"),
spent: "2000.0000 USDT",
},
{
kind: "a WRAP_ETH of 1 ETH into the router, then a swap of 0.5 WETH from the router",
@@ -697,6 +698,7 @@ describe("any token left in the router is not received", () => {
v2Swap(0x08, MSG_SENDER, ONE_WETH, USDC_1990, [WETH, USDC]),
),
left: tokenLine(WETH, "WETH"),
spent: "1.0000 WETH",
},
{
kind: "a WRAP_ETH of 1 ETH into the router, then a V3 swap of 1 WETH that the user pays for",
@@ -705,6 +707,7 @@ describe("any token left in the router is not received", () => {
v3SwapExactIn(MSG_SENDER, ONE_WETH, USDC_1990, WETH, USDC),
),
left: tokenLine(WETH, "WETH"),
spent: "1.0000 WETH",
},
{
kind: "a WRAP_ETH of 1 ETH into the router, then a V4 swap of 1 WETH with a SETTLE of 1 WETH by the user",
@@ -717,6 +720,7 @@ describe("any token left in the router is not received", () => {
),
),
left: tokenLine(WETH, "WETH"),
spent: "1.0000 WETH",
},
{
kind: "a swap paying WETH to the router, a WRAP_ETH of 1 ETH into the router, then a swap of 1 WETH from the router",
@@ -792,6 +796,7 @@ describe("any token left in the router is not received", () => {
),
),
left: tokenLine(WETH, "WETH"),
spent: "1.0000 WETH",
},
// The user pays for the swap by a SETTLE_ALL or SETTLE whose currency
// the decoder cannot read, so the SETTLE from the router pays nothing.
@@ -873,12 +878,17 @@ describe("any token left in the router is not received", () => {
),
left: { label: "Token moved into the router", value: "ETH" },
},
])("$kind", ({ data, left }) => {
])("$kind", ({ data, left, spent }) => {
const result = decode(data);
expect(labels(result)).toEqual([
"Protocol",
"Token In",
"Amount",
// A later swap step the user pays for spends `spent` of a token
// other than Token In (https://git.eeqj.de/sneak/AutistMask/issues/625).
...(spent
? ["Moved from the sender", "Token moved", "Moved to"]
: []),
"Token Out",
"Paid to",
"Token moved into the router",
@@ -886,6 +896,9 @@ describe("any token left in the router is not received", () => {
"Steps",
"Deadline",
]);
if (spent) {
expect(detail(result, "Moved from the sender").value).toBe(spent);
}
expect(paidTo(result)).toEqual([STAYS_IN_ROUTER]);
expect(detail(result, "Token moved into the router")).toEqual(left);
expect(detail(result, "Min. paid out").value).toBe("1990.0000 USDC");