Compare commits
1
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
73b7db9d79 |
@@ -3180,15 +3180,16 @@ Currently supported:
|
|||||||
other than the one that sets the input side, whose input or one of whose
|
other than the one that sets the input side, whose input or one of whose
|
||||||
`SETTLE`s or `SETTLE_ALL`s it cannot read, which the router still runs; a V2
|
`SETTLE`s or `SETTLE_ALL`s it cannot read, which the router still runs; a V2
|
||||||
or V3 exact-in or V2 exact-out step or a `PERMIT2_TRANSFER_FROM` whose input
|
or V3 exact-in or V2 exact-out step or a `PERMIT2_TRANSFER_FROM` whose input
|
||||||
it cannot read; every `PERMIT2_TRANSFER_FROM_BATCH`; and, once the input side
|
it cannot read; every `PERMIT2_TRANSFER_FROM_BATCH`; every
|
||||||
is set, every `V3_SWAP_EXACT_OUT`, which the decoder does not read, and every
|
`V3_SWAP_EXACT_OUT`, which the decoder does not read, wherever it stands; and
|
||||||
step it fails on. Each such step gives one `Moved from the sender` line among
|
every step it fails on. Each such step gives one `Moved from the sender` line
|
||||||
those, reading `Unknown (could not be decoded)`. That line, or any line for a
|
among those, reading `Unknown (could not be decoded)`. That line, or any line
|
||||||
token the decoder does not know, leaves no `Amount` line, whose figure might
|
for a token the decoder does not know, leaves no `Amount` line, whose figure
|
||||||
be too low. Then each `PERMIT2_TRANSFER_FROM` but one into the router, in step
|
might be too low, and such a step before a `PERMIT2_PERMIT` keeps the permit's
|
||||||
order, gives three lines: `Moved from the sender`, the amount it moves, for
|
amount from standing. Then each `PERMIT2_TRANSFER_FROM` but one into the
|
||||||
example `1000000.0000 USDT`; `Token moved`, giving the token's address as the
|
router, in step order, gives three lines: `Moved from the sender`, the amount
|
||||||
`Token In` line does; and `Moved to`, which reads
|
it moves, for example `1000000.0000 USDT`; `Token moved`, giving the token's
|
||||||
|
address as the `Token In` line does; and `Moved to`, which reads
|
||||||
`The V2 pair the next swap spends` for a hop and `The sender` for `address(1)`
|
`The V2 pair the next swap spends` for a hop and `The sender` for `address(1)`
|
||||||
on every router but `UniversalRouterV1`, and otherwise gives the address. A
|
on every router but `UniversalRouterV1`, and otherwise gives the address. A
|
||||||
move into the router needs none of them, because its `Paid to` line and
|
move into the router needs none of them, because its `Paid to` line and
|
||||||
|
|||||||
+13
-13
@@ -1234,10 +1234,11 @@ function decode(data, toAddress, chainId, sources, fromAddress) {
|
|||||||
// V4 step, other than the one that sets the input side, whose input
|
// V4 step, other than the one that sets the input side, whose input
|
||||||
// or one of whose SETTLEs or SETTLE_ALLs it cannot read; a V2 or V3
|
// or one of whose SETTLEs or SETTLE_ALLs it cannot read; a V2 or V3
|
||||||
// exact-in or V2 exact-out step or PERMIT2_TRANSFER_FROM whose input
|
// exact-in or V2 exact-out step or PERMIT2_TRANSFER_FROM whose input
|
||||||
// it cannot read; a PERMIT2_TRANSFER_FROM_BATCH; and, once the input
|
// it cannot read; a PERMIT2_TRANSFER_FROM_BATCH; a V3_SWAP_EXACT_OUT;
|
||||||
// side is set, a V3_SWAP_EXACT_OUT or a step it fails on. It is
|
// and a step it fails on. It is recorded with a null token and
|
||||||
// recorded with a null token and amount: one line says so, and there
|
// amount: one line says so, there is no Amount line, whose figure may
|
||||||
// is no Amount line, whose figure may then be too low.
|
// then be too low, and the amount of a permit after it does not stand
|
||||||
|
// (see permitStands).
|
||||||
const spentUnread = () => {
|
const spentUnread = () => {
|
||||||
userPaid.push({ token: null, amount: null });
|
userPaid.push({ token: null, amount: null });
|
||||||
};
|
};
|
||||||
@@ -1489,11 +1490,11 @@ function decode(data, toAddress, chainId, sources, fromAddress) {
|
|||||||
} else if (command === "V3_SWAP_EXACT_OUT") {
|
} else if (command === "V3_SWAP_EXACT_OUT") {
|
||||||
// This decoder does not read it
|
// This decoder does not read it
|
||||||
// (https://git.eeqj.de/sneak/AutistMask/issues/601). It
|
// (https://git.eeqj.de/sneak/AutistMask/issues/601). It
|
||||||
// may pay any address and take from the sender, so once
|
// may pay any address and take from the sender, so
|
||||||
// the input side is set it leaves no Amount figure.
|
// wherever it stands it leaves no Amount figure.
|
||||||
payeeUnread = true;
|
payeeUnread = true;
|
||||||
stepsUnread.push(i);
|
stepsUnread.push(i);
|
||||||
if (inputEstablished) spentUnread();
|
spentUnread();
|
||||||
} else if (command === "V2_SWAP_EXACT_IN") {
|
} else if (command === "V2_SWAP_EXACT_IN") {
|
||||||
const s = decodeV2SwapExactIn(inputs[i]);
|
const s = decodeV2SwapExactIn(inputs[i]);
|
||||||
if (s) {
|
if (s) {
|
||||||
@@ -1749,7 +1750,7 @@ function decode(data, toAddress, chainId, sources, fromAddress) {
|
|||||||
// take from the sender.
|
// take from the sender.
|
||||||
payeeUnread = true;
|
payeeUnread = true;
|
||||||
stepsUnread.push(i);
|
stepsUnread.push(i);
|
||||||
if (inputEstablished) spentUnread();
|
spentUnread();
|
||||||
}
|
}
|
||||||
if (allowedToFail) {
|
if (allowedToFail) {
|
||||||
commandNames[i] += " (allowed to fail)";
|
commandNames[i] += " (allowed to fail)";
|
||||||
@@ -1774,11 +1775,10 @@ function decode(data, toAddress, chainId, sources, fromAddress) {
|
|||||||
// it in full (see stepsUnread). Permit2 then lets the router take no
|
// it in full (see stepsUnread). Permit2 then lets the router take no
|
||||||
// more of the token than that amount, so the permit covers every take
|
// more of the token than that amount, so the permit covers every take
|
||||||
// of it. A later step this decoder did not read may raise what Permit2
|
// of it. A later step this decoder did not read may raise what Permit2
|
||||||
// lets the router take, as a PERMIT2_PERMIT_BATCH can. A step this
|
// lets the router take, as a PERMIT2_PERMIT_BATCH can. A step that
|
||||||
// decoder does not read that may take from the sender leaves no
|
// may take from the sender what this decoder did not read leaves no
|
||||||
// figure, permit or not, when it comes after the step that sets the
|
// figure, permit or not (see spentUnread()), and an EXECUTE_SUB_PLAN
|
||||||
// input side (see spentUnread()), and an EXECUTE_SUB_PLAN step leaves
|
// step leaves both sides unknown (below).
|
||||||
// both sides unknown (below).
|
|
||||||
const stepCommands = Array.from(
|
const stepCommands = Array.from(
|
||||||
commandsBytes,
|
commandsBytes,
|
||||||
(b) => commands[b & commandTypeMask],
|
(b) => commands[b & commandTypeMask],
|
||||||
|
|||||||
+62
-16
@@ -1876,23 +1876,69 @@ describe("uniswap decoder", () => {
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
// This decoder does not read a V3_SWAP_EXACT_OUT, so what one takes
|
// A V3_SWAP_EXACT_OUT the user pays for, of at most `amountInMax`
|
||||||
// after the step that sets the input side leaves no Amount figure.
|
// USDT for USDC. Its input is (recipient, amountOut, amountInMax,
|
||||||
test("a V3 exact-in of 600 USDT, then a V3_SWAP_EXACT_OUT the user pays for, shows no Amount figure", () => {
|
// path, payerIsUser), laid out as encodeV3SwapExactIn() writes one;
|
||||||
// Its input is (recipient, amountOut, amountInMax, path,
|
// an exact-out path lists the token bought first.
|
||||||
// payerIsUser), laid out as encodeV3SwapExactIn() writes one; an
|
const v3ExactOut = (amountInMax) =>
|
||||||
// exact-out path lists the token bought first.
|
encodeV3SwapExactIn(USER_ADDR, 390000000n, amountInMax, [
|
||||||
const exactOut = encodeV3SwapExactIn(
|
USDC_ADDR,
|
||||||
USER_ADDR,
|
USDT_ADDR,
|
||||||
390000000n,
|
|
||||||
USDT_400,
|
|
||||||
[USDC_ADDR, USDT_ADDR],
|
|
||||||
);
|
|
||||||
const result = decodeSteps([0x00, 0x01], [V3_600, exactOut]);
|
|
||||||
expect(linesBetweenTokens(result)).toEqual([
|
|
||||||
["Moved from the sender", UNDECODED],
|
|
||||||
]);
|
]);
|
||||||
});
|
// A split exact-out route: a V3_SWAP_EXACT_OUT of at most 6,000 USDT
|
||||||
|
// and a V2_SWAP_EXACT_OUT of at most 4,000 USDT, both paid by the
|
||||||
|
// user, then a SWEEP of USDC to the user.
|
||||||
|
const EXACT_OUT_SPLIT = [
|
||||||
|
v3ExactOut(6000000000n),
|
||||||
|
encodeV2SwapExactOut(USER_ADDR, 390000000n, 4000000000n, [
|
||||||
|
USDT_ADDR,
|
||||||
|
USDC_ADDR,
|
||||||
|
]),
|
||||||
|
coder.encode(
|
||||||
|
["address", "address", "uint256"],
|
||||||
|
[USDC_ADDR, USER_ADDR, 0n],
|
||||||
|
),
|
||||||
|
];
|
||||||
|
// This decoder does not read a V3_SWAP_EXACT_OUT, so what one takes
|
||||||
|
// leaves no Amount figure wherever it stands, and a permit's amount
|
||||||
|
// does not stand.
|
||||||
|
test.each([
|
||||||
|
{
|
||||||
|
kind: "a V3 exact-in of 600 USDT, then a V3_SWAP_EXACT_OUT",
|
||||||
|
commands: [0x00, 0x01],
|
||||||
|
inputs: [V3_600, v3ExactOut(USDT_400)],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
kind: "a PERMIT2_PERMIT of 10,000 USDT, then a V3_SWAP_EXACT_OUT, a V2_SWAP_EXACT_OUT and a SWEEP",
|
||||||
|
commands: [0x0a, 0x01, 0x09, 0x04],
|
||||||
|
inputs: [
|
||||||
|
encodePermit2(USDT_ADDR, 10000000000n, ROUTER_ADDR),
|
||||||
|
...EXACT_OUT_SPLIT,
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
kind: "a V3_SWAP_EXACT_OUT, a V2_SWAP_EXACT_OUT and a SWEEP",
|
||||||
|
commands: [0x01, 0x09, 0x04],
|
||||||
|
inputs: EXACT_OUT_SPLIT,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
kind: "a V3_SWAP_EXACT_OUT of at most 9,400 USDT, then a PERMIT2_PERMIT of 600 USDT and a V3 exact-in of 600 USDT",
|
||||||
|
commands: [0x01, 0x0a, 0x00],
|
||||||
|
inputs: [
|
||||||
|
v3ExactOut(9400000000n),
|
||||||
|
encodePermit2(USDT_ADDR, USDT_600, ROUTER_ADDR),
|
||||||
|
V3_600,
|
||||||
|
],
|
||||||
|
},
|
||||||
|
])(
|
||||||
|
"$kind, all paid by the user, shows no Amount figure",
|
||||||
|
({ commands, inputs }) => {
|
||||||
|
const result = decodeSteps(commands, inputs);
|
||||||
|
expect(linesBetweenTokens(result)).toEqual([
|
||||||
|
["Moved from the sender", UNDECODED],
|
||||||
|
]);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
// A later step's amount that cannot be added to the Amount line,
|
// A later step's amount that cannot be added to the Amount line,
|
||||||
// because the amount of the step that set the input side is not a
|
// because the amount of the step that set the input side is not a
|
||||||
|
|||||||
Reference in New Issue
Block a user