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
|
||||
`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
|
||||
it cannot read; every `PERMIT2_TRANSFER_FROM_BATCH`; and, once the input side
|
||||
is set, every `V3_SWAP_EXACT_OUT`, which the decoder does not read, and every
|
||||
step it fails on. Each such step gives one `Moved from the sender` line among
|
||||
those, reading `Unknown (could not be decoded)`. That line, or any line for a
|
||||
token the decoder does not know, leaves no `Amount` line, whose figure might
|
||||
be too low. Then each `PERMIT2_TRANSFER_FROM` but one into the router, in step
|
||||
order, gives three lines: `Moved from the sender`, the amount 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
|
||||
it cannot read; every `PERMIT2_TRANSFER_FROM_BATCH`; every
|
||||
`V3_SWAP_EXACT_OUT`, which the decoder does not read, wherever it stands; and
|
||||
every step it fails on. Each such step gives one `Moved from the sender` line
|
||||
among those, reading `Unknown (could not be decoded)`. That line, or any line
|
||||
for a token the decoder does not know, leaves no `Amount` line, whose figure
|
||||
might be too low, and such a step before a `PERMIT2_PERMIT` keeps the permit's
|
||||
amount from standing. Then each `PERMIT2_TRANSFER_FROM` but one into the
|
||||
router, in step order, gives three lines: `Moved from the sender`, the amount
|
||||
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)`
|
||||
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
|
||||
|
||||
+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
|
||||
// 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
|
||||
// it cannot read; a PERMIT2_TRANSFER_FROM_BATCH; and, once the input
|
||||
// side is set, a V3_SWAP_EXACT_OUT or a step it fails on. It is
|
||||
// recorded with a null token and amount: one line says so, and there
|
||||
// is no Amount line, whose figure may then be too low.
|
||||
// it cannot read; a PERMIT2_TRANSFER_FROM_BATCH; a V3_SWAP_EXACT_OUT;
|
||||
// and a step it fails on. It is recorded with a null token and
|
||||
// amount: one line says so, there is no Amount line, whose figure may
|
||||
// then be too low, and the amount of a permit after it does not stand
|
||||
// (see permitStands).
|
||||
const spentUnread = () => {
|
||||
userPaid.push({ token: null, amount: null });
|
||||
};
|
||||
@@ -1489,11 +1490,11 @@ function decode(data, toAddress, chainId, sources, fromAddress) {
|
||||
} else if (command === "V3_SWAP_EXACT_OUT") {
|
||||
// This decoder does not read it
|
||||
// (https://git.eeqj.de/sneak/AutistMask/issues/601). It
|
||||
// may pay any address and take from the sender, so once
|
||||
// the input side is set it leaves no Amount figure.
|
||||
// may pay any address and take from the sender, so
|
||||
// wherever it stands it leaves no Amount figure.
|
||||
payeeUnread = true;
|
||||
stepsUnread.push(i);
|
||||
if (inputEstablished) spentUnread();
|
||||
spentUnread();
|
||||
} else if (command === "V2_SWAP_EXACT_IN") {
|
||||
const s = decodeV2SwapExactIn(inputs[i]);
|
||||
if (s) {
|
||||
@@ -1749,7 +1750,7 @@ function decode(data, toAddress, chainId, sources, fromAddress) {
|
||||
// take from the sender.
|
||||
payeeUnread = true;
|
||||
stepsUnread.push(i);
|
||||
if (inputEstablished) spentUnread();
|
||||
spentUnread();
|
||||
}
|
||||
if (allowedToFail) {
|
||||
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
|
||||
// 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
|
||||
// lets the router take, as a PERMIT2_PERMIT_BATCH can. A step this
|
||||
// decoder does not read that may take from the sender leaves no
|
||||
// figure, permit or not, when it comes after the step that sets the
|
||||
// input side (see spentUnread()), and an EXECUTE_SUB_PLAN step leaves
|
||||
// both sides unknown (below).
|
||||
// lets the router take, as a PERMIT2_PERMIT_BATCH can. A step that
|
||||
// may take from the sender what this decoder did not read leaves no
|
||||
// figure, permit or not (see spentUnread()), and an EXECUTE_SUB_PLAN
|
||||
// step leaves both sides unknown (below).
|
||||
const stepCommands = Array.from(
|
||||
commandsBytes,
|
||||
(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
|
||||
// after the step that sets the input side leaves no Amount figure.
|
||||
test("a V3 exact-in of 600 USDT, then a V3_SWAP_EXACT_OUT the user pays for, shows no Amount figure", () => {
|
||||
// Its input is (recipient, amountOut, amountInMax, path,
|
||||
// payerIsUser), laid out as encodeV3SwapExactIn() writes one; an
|
||||
// exact-out path lists the token bought first.
|
||||
const exactOut = encodeV3SwapExactIn(
|
||||
USER_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 V3_SWAP_EXACT_OUT the user pays for, of at most `amountInMax`
|
||||
// USDT for USDC. Its input is (recipient, amountOut, amountInMax,
|
||||
// path, payerIsUser), laid out as encodeV3SwapExactIn() writes one;
|
||||
// an exact-out path lists the token bought first.
|
||||
const v3ExactOut = (amountInMax) =>
|
||||
encodeV3SwapExactIn(USER_ADDR, 390000000n, amountInMax, [
|
||||
USDC_ADDR,
|
||||
USDT_ADDR,
|
||||
]);
|
||||
});
|
||||
// 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,
|
||||
// because the amount of the step that set the input side is not a
|
||||
|
||||
Reference in New Issue
Block a user