fix: the swap's unknown first take shows only when the user pays that step (closes #634)
decode() now records whether the user pays the V4 step that sets the input side, from who pays its SETTLE of its input token. That step's Unknown (could not be decoded) line is added only then, and also when a PERMIT2_TRANSFER_FROM of its token goes into the router, whose figure is on its Paid to line. Paid from the router, the step takes nothing from the wallet and never gets the line. README Transaction Decoding says so. Model: opus-5-5
This commit is contained in:
+78
-11
@@ -2318,6 +2318,24 @@ describe("uniswap decoder", () => {
|
||||
encodeV4TakeAll(WETH_ADDR, 0n),
|
||||
],
|
||||
);
|
||||
// The same step with its SETTLE of OPEN_DELTA paid from the router.
|
||||
const V4_EXACT_OUT_600_FROM_ROUTER = encodeV4Swap(
|
||||
new Uint8Array([
|
||||
V4_SWAP_EXACT_OUT_SINGLE_ID,
|
||||
V4_SETTLE_ID,
|
||||
V4_TAKE_ALL_ID,
|
||||
]),
|
||||
[
|
||||
encodeV4ExactOutSingle(
|
||||
USDT_ADDR,
|
||||
WETH_ADDR,
|
||||
ONE_WETH,
|
||||
USDT_600,
|
||||
),
|
||||
settle(USDT_ADDR, 0n, false),
|
||||
encodeV4TakeAll(WETH_ADDR, 0n),
|
||||
],
|
||||
);
|
||||
test.each([
|
||||
{
|
||||
kind: "a V4 exact-out step with a SETTLE of OPEN_DELTA by the user",
|
||||
@@ -2325,6 +2343,13 @@ describe("uniswap decoder", () => {
|
||||
first: V4_EXACT_OUT_600,
|
||||
lines: [...UNKNOWN_USDT, ...UP_TO_400_USDT],
|
||||
},
|
||||
// Paid from the router, the step takes nothing from the wallet.
|
||||
{
|
||||
kind: "a V4 exact-out step with a SETTLE of OPEN_DELTA from the router",
|
||||
commands: [0x10, 0x09],
|
||||
first: V4_EXACT_OUT_600_FROM_ROUTER,
|
||||
lines: UP_TO_400_USDT,
|
||||
},
|
||||
// Settled by the user, the step's amount would be what that
|
||||
// SETTLE pays, which the decoder cannot state here.
|
||||
{
|
||||
@@ -2427,11 +2452,12 @@ describe("uniswap decoder", () => {
|
||||
// PERMIT2_TRANSFER_FROM of the token the V4 exact-out step spends,
|
||||
// before or after it, shows its own figure, so the step's amount is
|
||||
// shown as not known beside it, and the 400 USDT cannot read as all
|
||||
// that leaves. On next only the 400 USDT was shown.
|
||||
const transferTo = (token, amount) =>
|
||||
// that leaves. On next only the 400 USDT was shown. Into the router,
|
||||
// the 400 USDT is on its Paid to line.
|
||||
const transfer = (token, recipient, amount) =>
|
||||
coder.encode(
|
||||
["address", "address", "uint160"],
|
||||
[token, OTHER_ADDR, amount],
|
||||
[token, recipient, amount],
|
||||
);
|
||||
const MOVED_400_USDT = [
|
||||
["Moved from the sender", "400.0000 USDT"],
|
||||
@@ -2442,29 +2468,70 @@ describe("uniswap decoder", () => {
|
||||
{
|
||||
kind: "a V4 exact-out step of at most 600 USDT, then a PERMIT2_TRANSFER_FROM of 400 USDT to another address",
|
||||
commands: [0x10, 0x02],
|
||||
inputs: [V4_EXACT_OUT_600, transferTo(USDT_ADDR, USDT_400)],
|
||||
inputs: [
|
||||
V4_EXACT_OUT_600,
|
||||
transfer(USDT_ADDR, OTHER_ADDR, USDT_400),
|
||||
],
|
||||
lines: [...UNKNOWN_USDT, ...MOVED_400_USDT],
|
||||
},
|
||||
{
|
||||
kind: "a PERMIT2_TRANSFER_FROM of 400 USDT to another address, then a V4 exact-out step of at most 600 USDT",
|
||||
commands: [0x02, 0x10],
|
||||
inputs: [transferTo(USDT_ADDR, USDT_400), V4_EXACT_OUT_600],
|
||||
inputs: [
|
||||
transfer(USDT_ADDR, OTHER_ADDR, USDT_400),
|
||||
V4_EXACT_OUT_600,
|
||||
],
|
||||
lines: [...UNKNOWN_USDT, ...MOVED_400_USDT],
|
||||
},
|
||||
{
|
||||
kind: "a V4 exact-out step of at most 600 USDT, then a PERMIT2_TRANSFER_FROM of 400 USDT into the router",
|
||||
commands: [0x10, 0x02],
|
||||
inputs: [
|
||||
V4_EXACT_OUT_600,
|
||||
transfer(USDT_ADDR, ROUTER_ADDR, USDT_400),
|
||||
],
|
||||
lines: UNKNOWN_USDT,
|
||||
},
|
||||
{
|
||||
kind: "a PERMIT2_TRANSFER_FROM of 400 USDT into the router, then a V4 exact-out step of at most 600 USDT",
|
||||
commands: [0x02, 0x10],
|
||||
inputs: [
|
||||
transfer(USDT_ADDR, ROUTER_ADDR, USDT_400),
|
||||
V4_EXACT_OUT_600,
|
||||
],
|
||||
lines: UNKNOWN_USDT,
|
||||
},
|
||||
])(
|
||||
"$kind, paid by the user, shows that the step's amount is not known",
|
||||
({ commands, inputs }) => {
|
||||
({ commands, inputs, lines }) => {
|
||||
const result = decodeSteps(commands, inputs);
|
||||
expect(linesBetweenTokens(result)).toEqual([
|
||||
...UNKNOWN_USDT,
|
||||
...MOVED_400_USDT,
|
||||
]);
|
||||
expect(linesBetweenTokens(result)).toEqual(lines);
|
||||
},
|
||||
);
|
||||
|
||||
// Paid from the router, the V4 exact-out step takes nothing from the
|
||||
// wallet, so the moves give all that leaves.
|
||||
test("a PERMIT2_TRANSFER_FROM of 400 USDT into the router, one of 10 USDT to another address, then a V4 exact-out step paid from the router, shows only the moves", () => {
|
||||
const result = decodeSteps(
|
||||
[0x02, 0x02, 0x10],
|
||||
[
|
||||
transfer(USDT_ADDR, ROUTER_ADDR, USDT_400),
|
||||
transfer(USDT_ADDR, OTHER_ADDR, 10000000n),
|
||||
V4_EXACT_OUT_600_FROM_ROUTER,
|
||||
],
|
||||
);
|
||||
expect(linesBetweenTokens(result)).toEqual([
|
||||
["Moved from the sender", "10.0000 USDT"],
|
||||
["Token moved", "USDT (" + USDT_ADDR + ")"],
|
||||
["Moved to", OTHER_ADDR],
|
||||
]);
|
||||
});
|
||||
|
||||
// A move of another token says nothing of how much USDT leaves.
|
||||
test("a V4 exact-out step of at most 600 USDT, then a PERMIT2_TRANSFER_FROM of 400 DAI, shows only the DAI moved", () => {
|
||||
const result = decodeSteps(
|
||||
[0x10, 0x02],
|
||||
[V4_EXACT_OUT_600, transferTo(DAI_ADDR, DAI_400)],
|
||||
[V4_EXACT_OUT_600, transfer(DAI_ADDR, OTHER_ADDR, DAI_400)],
|
||||
);
|
||||
expect(linesBetweenTokens(result)).toEqual([
|
||||
["Moved from the sender", "400.0000 DAI"],
|
||||
|
||||
Reference in New Issue
Block a user