fix: a permit on the zero address never reads as ETH (closes #660)
Permit2 has no allowance of ETH, but the swap decoder read the zero address in a PERMIT2_PERMIT or a batch entry as ETH. Its Allowance token line now names the zero address, as for a token nothing knows. Its amount never stands as the Amount figure, and it never counts as an allowance of Token In, so a route that pays ETH after such a permit shows that ETH. Tests cover the single permit, the batch entry and the 1-wei route. Model: opus-5-5
This commit was merged in pull request #683.
This commit is contained in:
@@ -3310,6 +3310,135 @@ describe("uniswap decoder", () => {
|
||||
|
||||
expect(detail(result, "Amount").value).toBe("Up to 1000.0000 USDT");
|
||||
});
|
||||
|
||||
// https://git.eeqj.de/sneak/AutistMask/issues/660 — Permit2 has no
|
||||
// allowance of ETH, so a permit on the zero address reads as one on a
|
||||
// token nothing knows. On next at 53551c6 such a permit's Allowance
|
||||
// token line read ETH. A permit of 1 wei of the zero address before a
|
||||
// V4 step of 5 ETH made the Amount line read 0.000000000000000001 ETH.
|
||||
// With that permit to another spender and a SETTLE the router pays, no
|
||||
// line gave the 5 ETH.
|
||||
describe("a permit on the zero address", () => {
|
||||
const FIVE_ETH = 5000000000000000000n;
|
||||
// The lines of a permit of `amount` base units of the zero
|
||||
// address for `spender`.
|
||||
const zeroAddressLines = (amount, spender) => [
|
||||
[
|
||||
"Permit2 allowance",
|
||||
amount + " base units (decimals unknown)",
|
||||
],
|
||||
["Allowance token", ZERO_ADDR],
|
||||
["Allowance spender", getAddress(spender)],
|
||||
];
|
||||
// A V4 swap of 5 ETH for USDC. The user pays its SETTLE when
|
||||
// `payerIsUser` is true; otherwise the router pays it from the
|
||||
// transaction's value.
|
||||
const v4FiveEth = (payerIsUser) =>
|
||||
encodeV4Swap(
|
||||
new Uint8Array([
|
||||
V4_SWAP_EXACT_IN_SINGLE_ID,
|
||||
V4_SETTLE_ID,
|
||||
V4_TAKE_ALL_ID,
|
||||
]),
|
||||
[
|
||||
encodeV4ExactInSingle(
|
||||
ZERO_ADDR,
|
||||
USDC_ADDR,
|
||||
FIVE_ETH,
|
||||
1n,
|
||||
),
|
||||
settle(ZERO_ADDR, FIVE_ETH, payerIsUser),
|
||||
encodeV4TakeAll(USDC_ADDR, 1n),
|
||||
],
|
||||
);
|
||||
|
||||
test("a PERMIT2_PERMIT on the zero address names the address", () => {
|
||||
const result = decodeSteps(
|
||||
[0x00, 0x0a],
|
||||
[
|
||||
V3_600,
|
||||
encodePermit2(
|
||||
ZERO_ADDR,
|
||||
1000000000000000000n,
|
||||
ROUTER_ADDR,
|
||||
),
|
||||
],
|
||||
);
|
||||
expect(linesBetweenTokens(result)).toEqual([
|
||||
["Amount", "600.0000 USDT"],
|
||||
...zeroAddressLines("1000000000000000000", ROUTER_ADDR),
|
||||
]);
|
||||
expect(detail(result, "Allowance token").address).toBe(
|
||||
ZERO_ADDR,
|
||||
);
|
||||
});
|
||||
|
||||
test("a PERMIT2_PERMIT_BATCH entry on the zero address names the address", () => {
|
||||
const result = decodeSteps(
|
||||
[0x03, 0x00],
|
||||
[
|
||||
encodePermit2Batch(
|
||||
[
|
||||
[USDT_ADDR, USDT_600],
|
||||
[ZERO_ADDR, 1000000000000000000n],
|
||||
],
|
||||
ROUTER_ADDR,
|
||||
),
|
||||
V3_600,
|
||||
],
|
||||
);
|
||||
expect(linesBetweenTokens(result)).toEqual([
|
||||
["Amount", "600.0000 USDT"],
|
||||
...USDT_600_LINES,
|
||||
...zeroAddressLines("1000000000000000000", ROUTER_ADDR),
|
||||
]);
|
||||
});
|
||||
|
||||
test("a PERMIT2_PERMIT of 1 wei of the zero address, then a V4 step of 5 ETH the user settles, shows the 5 ETH", () => {
|
||||
const result = decodeSteps(
|
||||
[0x0a, 0x10],
|
||||
[
|
||||
encodePermit2(ZERO_ADDR, 1n, ROUTER_ADDR),
|
||||
v4FiveEth(true),
|
||||
],
|
||||
);
|
||||
expect(detail(result, "Token In").value).toBe("ETH (native)");
|
||||
expect(linesBetweenTokens(result)).toEqual([
|
||||
["Amount", "5.0000 ETH"],
|
||||
...zeroAddressLines("1", ROUTER_ADDR),
|
||||
]);
|
||||
});
|
||||
|
||||
test("a PERMIT2_PERMIT of 1 wei of the zero address to another spender, then a V4 step of 5 ETH the router settles, shows the 5 ETH", () => {
|
||||
const result = decodeSteps(
|
||||
[0x0a, 0x10],
|
||||
[
|
||||
encodePermit2(ZERO_ADDR, 1n, OTHER_ADDR),
|
||||
v4FiveEth(false),
|
||||
],
|
||||
);
|
||||
expect(detail(result, "Token In").value).toBe("ETH (native)");
|
||||
expect(linesBetweenTokens(result)).toEqual([
|
||||
["Amount", "5.0000 ETH"],
|
||||
...zeroAddressLines("1", OTHER_ADDR),
|
||||
]);
|
||||
});
|
||||
|
||||
test("a PERMIT2_PERMIT_BATCH entry of 1 wei of the zero address to another spender, then a V4 step of 5 ETH the router settles, shows the 5 ETH", () => {
|
||||
const result = decodeSteps(
|
||||
[0x03, 0x10],
|
||||
[
|
||||
encodePermit2Batch([[ZERO_ADDR, 1n]], OTHER_ADDR),
|
||||
v4FiveEth(false),
|
||||
],
|
||||
);
|
||||
expect(detail(result, "Token In").value).toBe("ETH (native)");
|
||||
expect(linesBetweenTokens(result)).toEqual([
|
||||
["Amount", "5.0000 ETH"],
|
||||
...zeroAddressLines("1", OTHER_ADDR),
|
||||
]);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
// https://git.eeqj.de/sneak/AutistMask/issues/359 — the output half, in
|
||||
|
||||
Reference in New Issue
Block a user