Compare commits
1
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5a444781bc |
@@ -3254,30 +3254,26 @@ Currently supported:
|
|||||||
whose amount the decoder does not know. When there is no `Amount` line, each
|
whose amount the decoder does not know. When there is no `Amount` line, each
|
||||||
take the total counts gets them too, so that every amount the decoder reads is
|
take the total counts gets them too, so that every amount the decoder reads is
|
||||||
shown: the amount the step that sets the input side states, when it is a
|
shown: the amount the step that sets the input side states, when it is a
|
||||||
quantity and the user pays that step (a V2 or V3 step whose `payerIsUser` is
|
quantity, and each later take of `Token In` added to it. A `PERMIT2_PERMIT`
|
||||||
true, a V4 step the user pays some of its input token, or a `WRAP_ETH`, whose
|
the decoder cannot read, then V3 exact-ins of 600 USDT and 400 DAI paid by the
|
||||||
ETH comes from the transaction's value), and each later take of `Token In`
|
user, give lines for both amounts. When the step that sets the input side
|
||||||
added to it. A step that sets the input side and is paid from the router takes
|
states no amount, the user pays it some of its input token, and there is no
|
||||||
nothing from the user's wallet and gets none. A `PERMIT2_PERMIT` the decoder
|
`Amount` line, that step gets them too whenever another take's lines give a
|
||||||
cannot read, then V3 exact-ins of 600 USDT and 400 DAI paid by the user, give
|
figure, or a `PERMIT2_TRANSFER_FROM` of its token gives one, on the lines
|
||||||
lines for both amounts. When the step that sets the input side states no
|
below or, into the router, on its `Paid to` line, so that figure cannot read
|
||||||
amount, the user pays it some of its input token, and there is no `Amount`
|
as all that leaves. When it states no amount and the user pays it none of its
|
||||||
line, that step gets them too whenever another take's lines give a figure, or
|
input token, as when the router pays it, that step takes none of that token
|
||||||
a `PERMIT2_TRANSFER_FROM` of its token gives one, on the lines below or, into
|
from the user's wallet and never gets them, with a permit or without. They
|
||||||
the router, on its `Paid to` line, so that figure cannot read as all that
|
come in step order, except that the step that sets the input side comes first
|
||||||
leaves. When it states no amount and the user pays it none of its input token,
|
when it has them, followed, when there is no `Amount` line, by the other takes
|
||||||
as when the router pays it, that step takes none of that token from the user's
|
the total counts: `Moved from the sender`, its amount, worded as the `Amount`
|
||||||
wallet and never gets them, with a permit or without. They come in step order,
|
line words one, or `Unknown (could not be decoded)` when the decoder does not
|
||||||
except that the step that sets the input side comes first when it has them,
|
know it; `Token moved`, giving the token's address as the `Token In` line
|
||||||
followed, when there is no `Amount` line, by the other takes the total counts:
|
does; and `Moved to`, which reads `The swap step that spends it`. A token the
|
||||||
`Moved from the sender`, its amount, worded as the `Amount` line words one, or
|
decoder does not know gives the `Moved from the sender` line alone. A step may
|
||||||
`Unknown (could not be decoded)` when the decoder does not know it;
|
also take from the user's wallet what the decoder did not read: a V4 step
|
||||||
`Token moved`, giving the token's address as the `Token In` line does; and
|
whose input or one of whose `SETTLE`s or `SETTLE_ALL`s it cannot read, which
|
||||||
`Moved to`, which reads `The swap step that spends it`. A token the decoder
|
the router still runs; a V2 or V3 exact-in or exact-out step or a
|
||||||
does not know gives the `Moved from the sender` line alone. A step may also
|
|
||||||
take from the user's wallet what the decoder did not read: a V4 step 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 exact-out step or a
|
|
||||||
`PERMIT2_TRANSFER_FROM` whose input it cannot read, such as a V3 step whose
|
`PERMIT2_TRANSFER_FROM` whose input it cannot read, such as a V3 step whose
|
||||||
path is shorter than one token address or has bytes after its last hop; every
|
path is shorter than one token address or has bytes after its last hop; every
|
||||||
`PERMIT2_TRANSFER_FROM_BATCH`; every `EXECUTE_SUB_PLAN`, wherever it stands;
|
`PERMIT2_TRANSFER_FROM_BATCH`; every `EXECUTE_SUB_PLAN`, wherever it stands;
|
||||||
|
|||||||
+11
-20
@@ -1234,11 +1234,9 @@ function decode(data, toAddress, chainId, sources, fromAddress) {
|
|||||||
let inputToken = null;
|
let inputToken = null;
|
||||||
let inputAmount = null;
|
let inputAmount = null;
|
||||||
let inputEstablished = false;
|
let inputEstablished = false;
|
||||||
// Whether the user pays the step that set the input side: a V2 or V3
|
// Whether the user pays the V4 step that set the input side any of
|
||||||
// swap step with `payerIsUser` true, a V4 step the user pays some of
|
// its input currency (see decodeV4Swap()). Only a V4 step can set the
|
||||||
// its input currency (see decodeV4Swap()), or a WRAP_ETH, whose ETH
|
// input side with no amount, the one case in which this is read.
|
||||||
// comes from the transaction's value. A step paid from the router
|
|
||||||
// takes nothing from the sender.
|
|
||||||
let inputPaidByUser = false;
|
let inputPaidByUser = false;
|
||||||
// The last PERMIT2_PERMIT this decoder read before a step set the
|
// The last PERMIT2_PERMIT this decoder read before a step set the
|
||||||
// input side, or null (see permitStands after the loop).
|
// input side, or null (see permitStands after the loop).
|
||||||
@@ -1624,7 +1622,6 @@ function decode(data, toAddress, chainId, sources, fromAddress) {
|
|||||||
if (s) {
|
if (s) {
|
||||||
if (!inputEstablished) {
|
if (!inputEstablished) {
|
||||||
setInputOnce(s.tokenIn, s.amountIn);
|
setInputOnce(s.tokenIn, s.amountIn);
|
||||||
inputPaidByUser = s.payerIsUser;
|
|
||||||
} else if (s.payerIsUser) {
|
} else if (s.payerIsUser) {
|
||||||
addUserPaid(s.tokenIn, s.amountIn);
|
addUserPaid(s.tokenIn, s.amountIn);
|
||||||
}
|
}
|
||||||
@@ -1648,7 +1645,6 @@ function decode(data, toAddress, chainId, sources, fromAddress) {
|
|||||||
if (s) {
|
if (s) {
|
||||||
if (!inputEstablished) {
|
if (!inputEstablished) {
|
||||||
setInputOnce(s.tokenIn, s.amountIn);
|
setInputOnce(s.tokenIn, s.amountIn);
|
||||||
inputPaidByUser = s.payerIsUser;
|
|
||||||
} else if (s.payerIsUser) {
|
} else if (s.payerIsUser) {
|
||||||
addUserPaid(s.tokenIn, s.amountIn);
|
addUserPaid(s.tokenIn, s.amountIn);
|
||||||
}
|
}
|
||||||
@@ -1680,7 +1676,6 @@ function decode(data, toAddress, chainId, sources, fromAddress) {
|
|||||||
if (s) {
|
if (s) {
|
||||||
if (!inputEstablished) {
|
if (!inputEstablished) {
|
||||||
setInputOnce(s.tokenIn, s.amountInMax);
|
setInputOnce(s.tokenIn, s.amountInMax);
|
||||||
inputPaidByUser = s.payerIsUser;
|
|
||||||
} else if (s.payerIsUser) {
|
} else if (s.payerIsUser) {
|
||||||
addUserPaid(s.tokenIn, s.amountInMax);
|
addUserPaid(s.tokenIn, s.amountInMax);
|
||||||
}
|
}
|
||||||
@@ -1776,13 +1771,10 @@ function decode(data, toAddress, chainId, sources, fromAddress) {
|
|||||||
} else if (command === "WRAP_ETH") {
|
} else if (command === "WRAP_ETH") {
|
||||||
const w = decodeWrapEth(inputs[i]);
|
const w = decodeWrapEth(inputs[i]);
|
||||||
if (w) {
|
if (w) {
|
||||||
if (!inputEstablished) {
|
setInputOnce(
|
||||||
setInputOnce(
|
"0x0000000000000000000000000000000000000000",
|
||||||
"0x0000000000000000000000000000000000000000",
|
w.amount,
|
||||||
w.amount,
|
);
|
||||||
);
|
|
||||||
inputPaidByUser = true;
|
|
||||||
}
|
|
||||||
addPayee(w.recipient);
|
addPayee(w.recipient);
|
||||||
// CONTRACT_BALANCE wraps all the router's ETH.
|
// CONTRACT_BALANCE wraps all the router's ETH.
|
||||||
if (w.amount === CONTRACT_BALANCE) {
|
if (w.amount === CONTRACT_BALANCE) {
|
||||||
@@ -2049,10 +2041,9 @@ function decode(data, toAddress, chainId, sources, fromAddress) {
|
|||||||
// (see spentUnread()), or a token it does not know.
|
// (see spentUnread()), or a token it does not know.
|
||||||
const spentFromSender = [];
|
const spentFromSender = [];
|
||||||
let total = null;
|
let total = null;
|
||||||
// The takes from the sender that `total` adds up, each a quantity, as
|
// The takes `total` adds up, each a quantity, as { token, amount }.
|
||||||
// { token, amount }. When there is no Amount line, each gets lines of
|
// When there is no Amount line, each gets lines of its own (see
|
||||||
// its own (see below). The amount of a step that set the input side
|
// below).
|
||||||
// and is paid from the router counts in `total` but is not among them.
|
|
||||||
const inTotal = [];
|
const inTotal = [];
|
||||||
// Whether the step that set the input side counts as a take from the
|
// Whether the step that set the input side counts as a take from the
|
||||||
// sender, which may get lines of its own. The amount it stated counts
|
// sender, which may get lines of its own. The amount it stated counts
|
||||||
@@ -2066,7 +2057,7 @@ function decode(data, toAddress, chainId, sources, fromAddress) {
|
|||||||
let firstTakeUnstated = null;
|
let firstTakeUnstated = null;
|
||||||
if (!permitStands || sameAddress(inputToken, permit.token)) {
|
if (!permitStands || sameAddress(inputToken, permit.token)) {
|
||||||
total = inputAmount;
|
total = inputAmount;
|
||||||
if (typeof inputAmount === "bigint" && inputPaidByUser) {
|
if (typeof inputAmount === "bigint") {
|
||||||
inTotal.push({ token: inputToken, amount: inputAmount });
|
inTotal.push({ token: inputToken, amount: inputAmount });
|
||||||
}
|
}
|
||||||
if (hasFirstTake && !present(inputAmount)) {
|
if (hasFirstTake && !present(inputAmount)) {
|
||||||
|
|||||||
@@ -2331,103 +2331,6 @@ describe("uniswap decoder", () => {
|
|||||||
expect(linesBetweenTokens(result)).toEqual(lines);
|
expect(linesBetweenTokens(result)).toEqual(lines);
|
||||||
});
|
});
|
||||||
|
|
||||||
// A step that sets the input side and is paid from the router takes
|
|
||||||
// nothing from the sender, so with no Amount line its amount gets no
|
|
||||||
// lines of its own: in each route below the sender's 600 USDT moves
|
|
||||||
// into the router first, and such lines would say it left twice.
|
|
||||||
const INTO_ROUTER_600 = permit2TransferFrom(
|
|
||||||
USDT_ADDR,
|
|
||||||
ROUTER_ADDR,
|
|
||||||
USDT_600,
|
|
||||||
);
|
|
||||||
const V3_600_FROM_ROUTER = coder.encode(
|
|
||||||
["address", "uint256", "uint256", "bytes", "bool"],
|
|
||||||
[
|
|
||||||
USER_ADDR,
|
|
||||||
USDT_600,
|
|
||||||
590000000n,
|
|
||||||
encodeV3Path([USDT_ADDR, USDC_ADDR]),
|
|
||||||
false,
|
|
||||||
],
|
|
||||||
);
|
|
||||||
const TRANSFER_FROM_BATCH = coder.encode(
|
|
||||||
["tuple(address,address,uint160,address)[]"],
|
|
||||||
[[[USER_ADDR, OTHER_ADDR, USDT_400, USDT_ADDR]]],
|
|
||||||
);
|
|
||||||
test.each([
|
|
||||||
{
|
|
||||||
kind: "a PERMIT2_TRANSFER_FROM of 600 USDT into the router, a V3 exact-in of 600 USDT paid from the router, then a PERMIT2_TRANSFER_FROM_BATCH",
|
|
||||||
commands: [0x02, 0x00, 0x0d],
|
|
||||||
inputs: [
|
|
||||||
INTO_ROUTER_600,
|
|
||||||
V3_600_FROM_ROUTER,
|
|
||||||
TRANSFER_FROM_BATCH,
|
|
||||||
],
|
|
||||||
lines: [["Moved from the sender", UNDECODED]],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
kind: "a PERMIT2_PERMIT that cannot be read, a PERMIT2_TRANSFER_FROM of 600 USDT into the router, then a V3 exact-in of 600 USDT paid from the router",
|
|
||||||
commands: [0x0a, 0x02, 0x00],
|
|
||||||
inputs: [
|
|
||||||
dirtyWord(
|
|
||||||
encodePermit2(USDT_ADDR, 5000000000n, ROUTER_ADDR),
|
|
||||||
0,
|
|
||||||
),
|
|
||||||
INTO_ROUTER_600,
|
|
||||||
V3_600_FROM_ROUTER,
|
|
||||||
],
|
|
||||||
lines: [["Permit2 allowance", UNDECODED]],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
kind: "a PERMIT2_TRANSFER_FROM of 600 USDT into the router, a V4 step swapping 600 USDT whose SETTLE the router pays, then a PERMIT2_TRANSFER_FROM_BATCH",
|
|
||||||
commands: [0x02, 0x10, 0x0d],
|
|
||||||
inputs: [
|
|
||||||
INTO_ROUTER_600,
|
|
||||||
encodeV4Swap(
|
|
||||||
new Uint8Array([
|
|
||||||
V4_SWAP_EXACT_IN_SINGLE_ID,
|
|
||||||
V4_SETTLE_ID,
|
|
||||||
V4_TAKE_ALL_ID,
|
|
||||||
]),
|
|
||||||
[
|
|
||||||
encodeV4ExactInSingle(
|
|
||||||
USDT_ADDR,
|
|
||||||
USDC_ADDR,
|
|
||||||
USDT_600,
|
|
||||||
590000000n,
|
|
||||||
),
|
|
||||||
settle(USDT_ADDR, USDT_600, false),
|
|
||||||
encodeV4TakeAll(USDC_ADDR, 0n),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
TRANSFER_FROM_BATCH,
|
|
||||||
],
|
|
||||||
lines: [["Moved from the sender", UNDECODED]],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
kind: "a PERMIT2_TRANSFER_FROM of 600 USDT into the router, a V2 exact-in of CONTRACT_BALANCE paid from the router, then an EXECUTE_SUB_PLAN",
|
|
||||||
commands: [0x02, 0x08, 0x21],
|
|
||||||
inputs: [
|
|
||||||
INTO_ROUTER_600,
|
|
||||||
coder.encode(
|
|
||||||
["address", "uint256", "uint256", "address[]", "bool"],
|
|
||||||
[
|
|
||||||
USER_ADDR,
|
|
||||||
2n ** 255n, // CONTRACT_BALANCE
|
|
||||||
590000000n,
|
|
||||||
[USDT_ADDR, USDC_ADDR],
|
|
||||||
false,
|
|
||||||
],
|
|
||||||
),
|
|
||||||
SUB_PLAN,
|
|
||||||
],
|
|
||||||
lines: [["Moved from the sender", UNDECODED]],
|
|
||||||
},
|
|
||||||
])("$kind", ({ commands, inputs, lines }) => {
|
|
||||||
const result = decodeSteps(commands, inputs);
|
|
||||||
expect(linesBetweenTokens(result)).toEqual(lines);
|
|
||||||
});
|
|
||||||
|
|
||||||
// A V3_SWAP_EXACT_OUT the user pays for, of at most `amountInMax`
|
// A V3_SWAP_EXACT_OUT the user pays for, of at most `amountInMax`
|
||||||
// USDT for USDC.
|
// USDT for USDC.
|
||||||
const v3ExactOut = (amountInMax) =>
|
const v3ExactOut = (amountInMax) =>
|
||||||
|
|||||||
Reference in New Issue
Block a user