fix: a zero-minimum balance check never changes the output side (closes #649)
check / check (push) Waiting to run
e2e / e2e-chrome (push) Waiting to run
e2e / e2e-firefox (push) Waiting to run

A BALANCE_CHECK_ERC20 of the sender with a zero minimum guarantees
nothing. It replaced the output side whenever that side held no
minimum, so after an UNWRAP_WETH that drops the minimum, a zero check
of USDC named USDC as Token Out. Such a check now leaves alone an
output side that an earlier step set. It still sets the output side
when no earlier step did. A check with a positive minimum is unchanged.

Model: opus-5-5
This commit is contained in:
2026-10-27 06:57:57 +00:00
parent fc6cffcaba
commit d921bb871b
3 changed files with 44 additions and 15 deletions
+28
View File
@@ -688,6 +688,34 @@ describe("an UNWRAP_WETH makes the output ETH only when the router holds it", ()
]);
});
// The same route, then a balance check of the sender's USDC with a zero
// minimum. The check guarantees nothing, so Token Out stays ETH
// (https://git.eeqj.de/sneak/AutistMask/issues/649).
test("the same route, then a zero balance check of USDC, still reads as ETH with no minimum", () => {
const result = decode(
execute(
v4Swap(
SWAP_USDT_FOR_WETH,
SETTLE_USDT,
take(WETH, MSG_SENDER, (ONE_WETH * 6n) / 10n),
take(WETH, ADDRESS_THIS),
),
unwrapWeth(MSG_SENDER),
balanceCheck(USDC, 0n),
),
);
expect(result.name).toBe("Swap USDT → ETH");
expect(detail(result, "Token Out").value).toBe("ETH");
expect(labels(result)).toEqual([
"Protocol",
"Token In",
"Amount",
"Token Out",
"Steps",
"Deadline",
]);
});
// A TAKE the decoder cannot read may pay part of the WETH to the user.
test("one V4 step paying WETH to the router beside a TAKE that cannot be read, then an UNWRAP_WETH, reads as ETH with no minimum", () => {
const result = decode(