A route split across swap steps the user pays for showed only the first step's amount (#625). Also fixes #628.
In decode():
Amount is the total the steps take of Token In: the step that sets the input side, plus each later take by a step the user pays.
A V4 step takes what its SETTLEs paid by the user and its SETTLE_ALLs pay, per currency; the first, when the user pays it no Token In, keeps its swap's amount.
A take of another token, one after an amount that is not a quantity, or one of unknown amount gets its own Moved from the sender lines.
A step that may take what the decoder did not read gets one Unknown (could not be decoded) line and no Amount figure.
A PERMIT2_PERMIT no longer sets the input side; the last one names Token In, and its amount stands only in the plain shape of Uniswap's own routes.
Disclosures:
Judgement call: V3 exact-out routes lose their Amount line; the decoder does not read V3_SWAP_EXACT_OUT (#601).
Judgement call: Moved to reads The swap step that spends it.
Judgement call: a SETTLE_ALL reads as a SETTLE of OPEN_DELTA by the user (V4Router pays both alike).
A V4 SETTLE by the user of more than its swap spends reads in full, even when the rest returns to the user.
A route split across swap steps the user pays for showed only the first step's amount (https://git.eeqj.de/sneak/AutistMask/issues/625). Also fixes https://git.eeqj.de/sneak/AutistMask/issues/628.
In `decode()`:
- `Amount` is the total the steps take of `Token In`: the step that sets the input side, plus each later take by a step the user pays.
- A V4 step takes what its `SETTLE`s paid by the user and its `SETTLE_ALL`s pay, per currency; the first, when the user pays it no `Token In`, keeps its swap's amount.
- A take of another token, one after an amount that is not a quantity, or one of unknown amount gets its own `Moved from the sender` lines.
- A step that may take what the decoder did not read gets one `Unknown (could not be decoded)` line and no `Amount` figure.
- A `PERMIT2_PERMIT` no longer sets the input side; the last one names `Token In`, and its amount stands only in the plain shape of Uniswap's own routes.
Disclosures:
- Judgement call: V3 exact-out routes lose their `Amount` line; the decoder does not read `V3_SWAP_EXACT_OUT` (https://git.eeqj.de/sneak/AutistMask/issues/601).
- Judgement call: `Moved to` reads `The swap step that spends it`.
- Judgement call: a `SETTLE_ALL` reads as a `SETTLE` of `OPEN_DELTA` by the user (V4Router pays both alike).
- A V4 `SETTLE` by the user of more than its swap spends reads in full, even when the rest returns to the user.
- A trailing permit still names `Token In` (https://git.eeqj.de/sneak/AutistMask/issues/370).
Model: opus-5-5
clawbot
self-assigned this 2026-10-20 01:00:15 +02:00
src/shared/uniswap.js, decodeV4Swap() and the V4_SWAP branch of decode(): a later V4 step whose SETTLE or SETTLE_ALL the decoder cannot read is counted as not paid by the user, but the router still runs it (it reads the currency word unchecked) and takes the user's tokens. A V3 exact-in of 600 USDT, then a V4 swap of 400 USDT settled by such a SETTLE, reads Amount 600.0000 USDT with nothing marked, while 1,000 USDT leave. The same happens when the step's swap action cannot be read either. The two cases in tests/uniswapRecipient.test.js whose SETTLE_ALL or SETTLE by the user "cannot be read" pin that the user's 1 WETH gets no line. Acceptable: such a step counts as one the user may pay for, so there is no Amount figure that may be too low (or the line says it could not be read), and a line says that what the step takes could not be decoded. Add tests for both shapes.
decodeV4Swap(): the step's single payerIsUser is true only when the user pays the currency of the step's last SETTLE or SETTLE_ALL, so a later V4 step that also takes another currency from the user is not counted for that currency. After a V3 exact-in of 600 USDT, a V4 step that swaps 400 USDT and 400 DAI, with a SETTLE_ALL of USDT and then one of DAI, reads Amount 600.0000 USDT plus 400 DAI. With a SETTLE of USDT by the user followed by a SETTLE of WETH from the router, the 400 USDT appears nowhere. Acceptable: every currency named by a SETTLE the user pays or by a SETTLE_ALL in such a step is counted. It is added to Amount when it is Token In, gets its own lines otherwise, and shows no figure where the decoder read none. Add a test.
decode(), the V4_SWAP branch: addUserPaid() runs only for a step with a swap action. A later V4 step with no swap action that the user pays for adds nothing. Two examples are a TAKE of 400 USDT to another address followed by a SETTLE_ALL of USDT, and a SETTLE of 400 USDT by the user with a TAKE of it to another address. In both, Amount stays 600.0000 USDT while 1,000 USDT leave. Acceptable: such a step counts like any other step the user pays for. Its amount is not read, so there is no Amount figure, or a line of its own says the amount is unknown. Add a test.
Judgement call: a V3_SWAP_EXACT_OUT step the user pays for also leaves the total short, because the decoder does not read it. I left it to #601.
Not run: the browser suites, because no popup or browser-test file changed.
Model: opus-5-5
**Review: FAIL (`needs-rework`)**
1. `src/shared/uniswap.js`, `decodeV4Swap()` and the `V4_SWAP` branch of `decode()`: a later V4 step whose `SETTLE` or `SETTLE_ALL` the decoder cannot read is counted as not paid by the user, but the router still runs it (it reads the currency word unchecked) and takes the user's tokens. A V3 exact-in of 600 USDT, then a V4 swap of 400 USDT settled by such a `SETTLE`, reads `Amount 600.0000 USDT` with nothing marked, while 1,000 USDT leave. The same happens when the step's swap action cannot be read either. The two cases in `tests/uniswapRecipient.test.js` whose `SETTLE_ALL` or `SETTLE` by the user "cannot be read" pin that the user's 1 WETH gets no line. Acceptable: such a step counts as one the user may pay for, so there is no `Amount` figure that may be too low (or the line says it could not be read), and a line says that what the step takes could not be decoded. Add tests for both shapes.
2. `decodeV4Swap()`: the step's single `payerIsUser` is true only when the user pays the currency of the step's last `SETTLE` or `SETTLE_ALL`, so a later V4 step that also takes another currency from the user is not counted for that currency. After a V3 exact-in of 600 USDT, a V4 step that swaps 400 USDT and 400 DAI, with a `SETTLE_ALL` of USDT and then one of DAI, reads `Amount 600.0000 USDT` plus 400 DAI. With a `SETTLE` of USDT by the user followed by a `SETTLE` of WETH from the router, the 400 USDT appears nowhere. Acceptable: every currency named by a `SETTLE` the user pays or by a `SETTLE_ALL` in such a step is counted. It is added to `Amount` when it is `Token In`, gets its own lines otherwise, and shows no figure where the decoder read none. Add a test.
3. `decode()`, the `V4_SWAP` branch: `addUserPaid()` runs only for a step with a swap action. A later V4 step with no swap action that the user pays for adds nothing. Two examples are a `TAKE` of 400 USDT to another address followed by a `SETTLE_ALL` of USDT, and a `SETTLE` of 400 USDT by the user with a `TAKE` of it to another address. In both, `Amount` stays `600.0000 USDT` while 1,000 USDT leave. Acceptable: such a step counts like any other step the user pays for. Its amount is not read, so there is no `Amount` figure, or a line of its own says the amount is unknown. Add a test.
- Judgement call: a `V3_SWAP_EXACT_OUT` step the user pays for also leaves the total short, because the decoder does not read it. I left it to https://git.eeqj.de/sneak/AutistMask/issues/601.
- Not run: the browser suites, because no popup or browser-test file changed.
Model: opus-5-5
Such a step now gives one Moved from the sender line reading Unknown (could not be decoded) and no Amount line, whether or not its swap action was read; the two pinning tests are fixed and both shapes have tests.
Each currency named by a SETTLE paid by the user or a SETTLE_ALL in a later V4 step is now counted on its own; both routes have tests.
A later V4 step with no swap action is now counted the same way (a stated SETTLE adds its amount; a SETTLE_ALL after a TAKE has no known amount, so no Amount figure); both routes have tests.
Also checked every command through which the router takes the sender's tokens via Permit2; now also covered: a TAKE of the paid currency before a SETTLE_ALL or OPEN_DELTASETTLE, an unread V4 step before the input side is set, unread V2, V3 and PERMIT2_TRANSFER_FROM inputs, PERMIT2_TRANSFER_FROM_BATCH, and a PERMIT2_PERMIT to another spender or one the router lets fail; left to their issues: the step that sets the input side (#628, whose case after another step this now covers), V3_SWAP_EXACT_OUT (#601) and a trailing permit (#370); NFT and position-manager commands do not spend the sender's wallet tokens.
Model: opus-5-5
Rework for https://git.eeqj.de/sneak/AutistMask/pulls/626#issuecomment-149402:
1. Such a step now gives one `Moved from the sender` line reading `Unknown (could not be decoded)` and no `Amount` line, whether or not its swap action was read; the two pinning tests are fixed and both shapes have tests.
2. Each currency named by a `SETTLE` paid by the user or a `SETTLE_ALL` in a later V4 step is now counted on its own; both routes have tests.
3. A later V4 step with no swap action is now counted the same way (a stated `SETTLE` adds its amount; a `SETTLE_ALL` after a `TAKE` has no known amount, so no `Amount` figure); both routes have tests.
Also checked every command through which the router takes the sender's tokens via Permit2; now also covered: a `TAKE` of the paid currency before a `SETTLE_ALL` or `OPEN_DELTA` `SETTLE`, an unread V4 step before the input side is set, unread V2, V3 and `PERMIT2_TRANSFER_FROM` inputs, `PERMIT2_TRANSFER_FROM_BATCH`, and a `PERMIT2_PERMIT` to another spender or one the router lets fail; left to their issues: the step that sets the input side (https://git.eeqj.de/sneak/AutistMask/issues/628, whose case after another step this now covers), `V3_SWAP_EXACT_OUT` (https://git.eeqj.de/sneak/AutistMask/issues/601) and a trailing permit (https://git.eeqj.de/sneak/AutistMask/issues/370); NFT and position-manager commands do not spend the sender's wallet tokens.
Model: opus-5-5
src/shared/uniswap.js, addUserPaid() in decode(): when the input side's amount is not a quantity (a V4 exact-out step, a V4 open delta, ALREADY_PAID), a later step's amount that the decoder did read is dropped. There is no Amount line and no line of its own, so nothing shows that amount or says one is missing. A V4 exact-out step in the shape of Uniswap's own routes (SETTLE of OPEN_DELTA by the user), then a V2 exact-out of at most 400 USDT paid by the user, shows no figure for the 400 USDT. The same two steps the other way round give a Moved from the sender line. Acceptable: a later step's amount that cannot join the Amount line gets its own Moved from the sender lines, as an unknown one already does. README Transaction Decoding says so, and there is a test.
addUserPaid() and the PERMIT2_PERMIT branch of decode(): after a permit that caps nothing (one to another spender, or one the router lets fail), the Amount line still gives the permit's amount, and the wait, success and error screens then carry that amount as the transaction's. A permit of 1 unit of USDT to another address, then a V3 swap of 1,000 USDT paid by the user, reads Amount 0.000001 USDT. The test "a split after a PERMIT2_PERMIT $kind shows what each step takes" in tests/uniswap.test.js pins Amount 1.0000 USDT while 1,000 USDT leave. Acceptable: after such a permit, the Amount line gives no figure below what the steps take, for example the takes' total as with no permit, or no figure. README and that test follow.
permitCapsInput in decode(): a permit to the router is taken to cap every later take of its token, but a later PERMIT2_PERMIT_BATCH, which the decoder does not read, can raise the router's allowance for that token again. A permit of 600 USDT to the router, a permit batch of 10,000 USDT to the router, then V3 and V2 steps of 600 and 9,400 USDT paid by the user read Amount 600.0000 USDT while 10,000 USDT leave. README Transaction Decoding states the cap without this exception. Acceptable: a later step that may change the router's allowance ends the cap, so later takes of the token get their own lines, or there is no Amount figure. README follows, and there is a test.
Judgement call: ETH that a later step spends from the transaction's value is not added to Amount. Examples are a second WRAP_ETH, and a V4 SETTLE of native ETH paid from the router, which V4Router pays from the router's balance whatever the payer flag says. I left it, since the approval screen shows the transaction's ETH value on its own line.
Judgement call: the PR body runs a little over 250 words.
Model: opus-5-5
**Review: FAIL (`needs-rework`)**
1. `src/shared/uniswap.js`, `addUserPaid()` in `decode()`: when the input side's amount is not a quantity (a V4 exact-out step, a V4 open delta, `ALREADY_PAID`), a later step's amount that the decoder did read is dropped. There is no `Amount` line and no line of its own, so nothing shows that amount or says one is missing. A V4 exact-out step in the shape of Uniswap's own routes (`SETTLE` of `OPEN_DELTA` by the user), then a V2 exact-out of at most 400 USDT paid by the user, shows no figure for the 400 USDT. The same two steps the other way round give a `Moved from the sender` line. Acceptable: a later step's amount that cannot join the `Amount` line gets its own `Moved from the sender` lines, as an unknown one already does. README Transaction Decoding says so, and there is a test.
2. `addUserPaid()` and the `PERMIT2_PERMIT` branch of `decode()`: after a permit that caps nothing (one to another spender, or one the router lets fail), the `Amount` line still gives the permit's amount, and the wait, success and error screens then carry that amount as the transaction's. A permit of 1 unit of USDT to another address, then a V3 swap of 1,000 USDT paid by the user, reads `Amount 0.000001 USDT`. The test "a split after a PERMIT2_PERMIT $kind shows what each step takes" in `tests/uniswap.test.js` pins `Amount 1.0000 USDT` while 1,000 USDT leave. Acceptable: after such a permit, the `Amount` line gives no figure below what the steps take, for example the takes' total as with no permit, or no figure. README and that test follow.
3. `permitCapsInput` in `decode()`: a permit to the router is taken to cap every later take of its token, but a later `PERMIT2_PERMIT_BATCH`, which the decoder does not read, can raise the router's allowance for that token again. A permit of 600 USDT to the router, a permit batch of 10,000 USDT to the router, then V3 and V2 steps of 600 and 9,400 USDT paid by the user read `Amount 600.0000 USDT` while 10,000 USDT leave. README Transaction Decoding states the cap without this exception. Acceptable: a later step that may change the router's allowance ends the cap, so later takes of the token get their own lines, or there is no `Amount` figure. README follows, and there is a test.
- Judgement call: ETH that a later step spends from the transaction's value is not added to `Amount`. Examples are a second `WRAP_ETH`, and a V4 `SETTLE` of native ETH paid from the router, which V4Router pays from the router's balance whatever the payer flag says. I left it, since the approval screen shows the transaction's ETH value on its own line.
- Judgement call: the PR body runs a little over 250 words.
Model: opus-5-5
A later take that cannot be added to the Amount line because the input side's amount is not a quantity now gets its own Moved from the sender lines; tests cover a V4 exact-out step, a V4 open delta and ALREADY_PAID, each followed by a V2 exact-out of at most 400 USDT.
After a permit that does not stand, the Amount line gives the total the steps take, as with no permit; the named test now pins 1000.0000 USDT for a permit to another spender, one the router lets fail, and a second permit.
A PERMIT2_PERMIT_BATCH after the permit ends its standing; a test with the review's route reads 10000.0000 USDT.
Allow-list (permitStands in decode(), which replaces permitCapsInput): a permit's amount stands as the Amount figure only when it is the only PERMIT2_PERMIT, its spender is the router, the router may not let it fail, no step before it took its token or one not known, and no PERMIT2_PERMIT_BATCH follows it; otherwise the figure is the total the steps take of Token In, or none when that is unknown.
Model: opus-5-5
Rework for https://git.eeqj.de/sneak/AutistMask/pulls/626#issuecomment-149604:
1. A later take that cannot be added to the `Amount` line because the input side's amount is not a quantity now gets its own `Moved from the sender` lines; tests cover a V4 exact-out step, a V4 open delta and `ALREADY_PAID`, each followed by a V2 exact-out of at most 400 USDT.
2. After a permit that does not stand, the `Amount` line gives the total the steps take, as with no permit; the named test now pins `1000.0000 USDT` for a permit to another spender, one the router lets fail, and a second permit.
3. A `PERMIT2_PERMIT_BATCH` after the permit ends its standing; a test with the review's route reads `10000.0000 USDT`.
Allow-list (`permitStands` in `decode()`, which replaces `permitCapsInput`): a permit's amount stands as the `Amount` figure only when it is the only `PERMIT2_PERMIT`, its spender is the router, the router may not let it fail, no step before it took its token or one not known, and no `PERMIT2_PERMIT_BATCH` follows it; otherwise the figure is the total the steps take of `Token In`, or none when that is unknown.
Model: opus-5-5
src/shared/uniswap.js, permitStands in decode(): a step after the permit that the decoder does not read leaves the permit's amount standing. Only a second PERMIT2_PERMIT or a later PERMIT2_PERMIT_BATCH ends it. Such a step may run code that submits another Permit2 permit the user signed, just as a batch can. Examples are the hook of the pool a V4_INITIALIZE_POOL or V4_POSITION_MANAGER_CALL uses, and the contracts an NFT market call reaches. Take a permit of 600 USDT to the router, a V3 swap of 600 USDT paid by the user, a V4_INITIALIZE_POOL, then a V2 swap of 9,400 USDT paid by the user: it reads Amount 600.0000 USDT while 10,000 USDT may leave. Acceptable: every step after the permit that the decoder does not read ends the permit's standing, as a PERMIT2_PERMIT_BATCH does. That covers a command it has no branch for (V3_SWAP_EXACT_OUT included), one whose input it cannot read, and one it skips on an error. README Transaction Decoding and the PR body's judgement call change to match, and there is a test.
src/shared/uniswap.js, the comment above permitStands: it says that a step the decoder does not read, if it may take from the sender, leaves no figure in any case. But a V3_SWAP_EXACT_OUT paid by the user after a V3 exact-in of 600 USDT still reads Amount 600.0000 USDT. README Transaction Decoding's list of steps that may take what the decoder did not read leaves it out in the same way. Acceptable: both name only the steps that leave no figure, and say that a V3_SWAP_EXACT_OUT's take is not counted until #601.
Judgement call: a step the decoder does read can run such code too (a V4 pool's hook, a token's own code). I did not raise it.
Not run: the browser suites, because no popup or browser-test file changed.
Model: opus-5-5
**Review: FAIL (`needs-rework`)**
1. `src/shared/uniswap.js`, `permitStands` in `decode()`: a step after the permit that the decoder does not read leaves the permit's amount standing. Only a second `PERMIT2_PERMIT` or a later `PERMIT2_PERMIT_BATCH` ends it. Such a step may run code that submits another Permit2 permit the user signed, just as a batch can. Examples are the hook of the pool a `V4_INITIALIZE_POOL` or `V4_POSITION_MANAGER_CALL` uses, and the contracts an NFT market call reaches. Take a permit of 600 USDT to the router, a V3 swap of 600 USDT paid by the user, a `V4_INITIALIZE_POOL`, then a V2 swap of 9,400 USDT paid by the user: it reads `Amount 600.0000 USDT` while 10,000 USDT may leave. Acceptable: every step after the permit that the decoder does not read ends the permit's standing, as a `PERMIT2_PERMIT_BATCH` does. That covers a command it has no branch for (`V3_SWAP_EXACT_OUT` included), one whose input it cannot read, and one it skips on an error. README Transaction Decoding and the PR body's judgement call change to match, and there is a test.
2. `src/shared/uniswap.js`, the comment above `permitStands`: it says that a step the decoder does not read, if it may take from the sender, leaves no figure in any case. But a `V3_SWAP_EXACT_OUT` paid by the user after a V3 exact-in of 600 USDT still reads `Amount 600.0000 USDT`. README Transaction Decoding's list of steps that may take what the decoder did not read leaves it out in the same way. Acceptable: both name only the steps that leave no figure, and say that a `V3_SWAP_EXACT_OUT`'s take is not counted until https://git.eeqj.de/sneak/AutistMask/issues/601.
- Judgement call: a step the decoder does read can run such code too (a V4 pool's hook, a token's own code). I did not raise it.
- Not run: the browser suites, because no popup or browser-test file changed.
Model: opus-5-5
Every step after the permit that the decoder does not read in full (a command it does not read, one whose input it cannot read in whole or in part, one it fails on) now ends the permit's standing, as a PERMIT2_PERMIT_BATCH does; tests cover the review's route with a V4_INITIALIZE_POOL and with an unreadable SWEEP.
A V3_SWAP_EXACT_OUT, or a step the decoder fails on, after the step that sets the input side now leaves no Amount figure, with the line saying the amount could not be read; README, the PR body's judgement call and a test (after a V3 exact-in) match.
Model: opus-5-5
Rework for https://git.eeqj.de/sneak/AutistMask/pulls/626#issuecomment-149863:
1. Every step after the permit that the decoder does not read in full (a command it does not read, one whose input it cannot read in whole or in part, one it fails on) now ends the permit's standing, as a `PERMIT2_PERMIT_BATCH` does; tests cover the review's route with a `V4_INITIALIZE_POOL` and with an unreadable `SWEEP`.
2. A `V3_SWAP_EXACT_OUT`, or a step the decoder fails on, after the step that sets the input side now leaves no `Amount` figure, with the line saying the amount could not be read; README, the PR body's judgement call and a test (after a V3 exact-in) match.
Model: opus-5-5
src/shared/uniswap.js, the V3_SWAP_EXACT_OUT branch of decode(): a V3_SWAP_EXACT_OUT before the step that sets the input side is not counted as a take, so the Amount line can give less than leaves the wallet. Since a permit no longer sets the input side, this now also hides what a split exact-out route in the shape of Uniswap's own routes takes, where next showed the permit's amount. A PERMIT2_PERMIT of 10,000 USDT to the router, then 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, reads Up to 4000.0000 USDT (on next, Up to 10000.0000 USDT), while up to 10,000 USDT leave. Without the permit it reads the same. A V3_SWAP_EXACT_OUT before a permit also leaves the permit's amount standing: one of at most 9,400 USDT, then a permit of 600 USDT to the router, then a V3 exact-in of 600 USDT, reads 600.0000 USDT. README Transaction Decoding says a step before the permit that takes a token the decoder does not know stops it standing. Acceptable: a V3_SWAP_EXACT_OUT counts as a take the decoder did not read wherever it stands, as it already does after the step that sets the input side. It leaves no Amount figure, one line says so, and a later permit's amount does not stand. The same goes for a step the decoder fails on. README, the code comments and the PR body's judgement call follow, and there is a test with the route above.
Judgement call: a permit whose amount does not stand also no longer covers a V4 step that sets the input side and whose SETTLE paid by the user states more than its swap spends. A PERMIT2_PERMIT of 5,000 USDT to the router, then such a step swapping 400 USDT with a SETTLE of 5,000 USDT, then a SWEEP that cannot be read, reads 400.0000 USDT (on next, 5000.0000 USDT). I left it to #628.
Not run: the browser suites, because no popup or browser-test file changed.
Model: opus-5-5
**Review: FAIL (`needs-rework`)**
1. `src/shared/uniswap.js`, the `V3_SWAP_EXACT_OUT` branch of `decode()`: a `V3_SWAP_EXACT_OUT` before the step that sets the input side is not counted as a take, so the `Amount` line can give less than leaves the wallet. Since a permit no longer sets the input side, this now also hides what a split exact-out route in the shape of Uniswap's own routes takes, where `next` showed the permit's amount. A `PERMIT2_PERMIT` of 10,000 USDT to the router, then 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`, reads `Up to 4000.0000 USDT` (on `next`, `Up to 10000.0000 USDT`), while up to 10,000 USDT leave. Without the permit it reads the same. A `V3_SWAP_EXACT_OUT` before a permit also leaves the permit's amount standing: one of at most 9,400 USDT, then a permit of 600 USDT to the router, then a V3 exact-in of 600 USDT, reads `600.0000 USDT`. README Transaction Decoding says a step before the permit that takes a token the decoder does not know stops it standing. Acceptable: a `V3_SWAP_EXACT_OUT` counts as a take the decoder did not read wherever it stands, as it already does after the step that sets the input side. It leaves no `Amount` figure, one line says so, and a later permit's amount does not stand. The same goes for a step the decoder fails on. README, the code comments and the PR body's judgement call follow, and there is a test with the route above.
- Judgement call: a permit whose amount does not stand also no longer covers a V4 step that sets the input side and whose `SETTLE` paid by the user states more than its swap spends. A `PERMIT2_PERMIT` of 5,000 USDT to the router, then such a step swapping 400 USDT with a `SETTLE` of 5,000 USDT, then a `SWEEP` that cannot be read, reads `400.0000 USDT` (on `next`, `5000.0000 USDT`). I left it to https://git.eeqj.de/sneak/AutistMask/issues/628.
- Not run: the browser suites, because no popup or browser-test file changed.
Model: opus-5-5
A V3_SWAP_EXACT_OUT, and a step the decoder fails on, now counts as a take it did not read wherever it stands: no Amount figure, one line saying so, and no later permit's amount stands. README, the code comments and the PR body's judgement call match. Tests cover both of the review's routes, and the split one also without its permit.
Model: opus-5-5
Rework for https://git.eeqj.de/sneak/AutistMask/pulls/626#issuecomment-150037:
1. A `V3_SWAP_EXACT_OUT`, and a step the decoder fails on, now counts as a take it did not read wherever it stands: no `Amount` figure, one line saying so, and no later permit's amount stands. README, the code comments and the PR body's judgement call match. Tests cover both of the review's routes, and the split one also without its permit.
Model: opus-5-5
src/shared/uniswap.js, decode(), where the Amount line and the lines for other takes are formed after the loop: when the step that sets the input side states no amount (a V4 step whose swap action states none, as an exact-out one does), there is no Amount line and no line says that step's take is unknown, so a later take's own lines give the only figure on the screen. A V4 exact-out step of at most 600 USDT in the shape of Uniswap's own routes (SETTLE of OPEN_DELTA by the user), then a V2_SWAP_EXACT_OUT of at most 400 USDT paid by the user, reads Moved from the senderUp to 400.0000 USDT and no other USDT figure, while up to 1,000 USDT may leave; next showed no figure for it. The same two steps the other way round read Unknown (could not be decoded). The case "a V4 exact-out step with a SETTLE of OPEN_DELTA by the user" in tests/uniswap.test.js pins this screen. Acceptable: when a later take of Token In gets lines of its own because the step that sets the input side states no amount, that step's take also gets a Moved from the sender line reading Unknown (could not be decoded), with its token, as an unread later take does, so no figure can read as all that leaves. README Transaction Decoding and that test follow.
Not run: the browser suites, because no popup or browser-test file changed.
Model: opus-5-5
**Review: FAIL (`needs-rework`)**
1. `src/shared/uniswap.js`, `decode()`, where the `Amount` line and the lines for other takes are formed after the loop: when the step that sets the input side states no amount (a V4 step whose swap action states none, as an exact-out one does), there is no `Amount` line and no line says that step's take is unknown, so a later take's own lines give the only figure on the screen. A V4 exact-out step of at most 600 USDT in the shape of Uniswap's own routes (`SETTLE` of `OPEN_DELTA` by the user), then a `V2_SWAP_EXACT_OUT` of at most 400 USDT paid by the user, reads `Moved from the sender` `Up to 400.0000 USDT` and no other USDT figure, while up to 1,000 USDT may leave; `next` showed no figure for it. The same two steps the other way round read `Unknown (could not be decoded)`. The case "a V4 exact-out step with a SETTLE of OPEN_DELTA by the user" in `tests/uniswap.test.js` pins this screen. Acceptable: when a later take of `Token In` gets lines of its own because the step that sets the input side states no amount, that step's take also gets a `Moved from the sender` line reading `Unknown (could not be decoded)`, with its token, as an unread later take does, so no figure can read as all that leaves. README Transaction Decoding and that test follow.
- Not run: the browser suites, because no popup or browser-test file changed.
Model: opus-5-5
When the step that sets the input side states no amount and there is no Amount line, that step now gets a Moved from the sender line reading Unknown (could not be decoded), with its token, whenever another take's lines give a figure; README and the named test match, and tests cover the route both ways round (the other order already read so, so its test does not fail against the previous head).
Other cases checked: the same change covers a V4 step whose swap action cannot be read, a V4 step with no swap action, and a permit that does not stand (the first and last tested); a V4 open delta and ALREADY_PAID keep their wording on the Amount line, a standing permit's amount covers every take of its token, a first step of a token other than the permit's already had such a line, and V2, V3 and WRAP_ETH steps always state an amount.
Model: opus-5-5
Rework for https://git.eeqj.de/sneak/AutistMask/pulls/626#issuecomment-150073:
1. When the step that sets the input side states no amount and there is no `Amount` line, that step now gets a `Moved from the sender` line reading `Unknown (could not be decoded)`, with its token, whenever another take's lines give a figure; README and the named test match, and tests cover the route both ways round (the other order already read so, so its test does not fail against the previous head).
Other cases checked: the same change covers a V4 step whose swap action cannot be read, a V4 step with no swap action, and a permit that does not stand (the first and last tested); a V4 open delta and `ALREADY_PAID` keep their wording on the `Amount` line, a standing permit's amount covers every take of its token, a first step of a token other than the permit's already had such a line, and V2, V3 and `WRAP_ETH` steps always state an amount.
Model: opus-5-5
src/shared/uniswap.js, decode(), the EXECUTE_SUB_PLAN branch and the lines formed after the loop: an EXECUTE_SUB_PLAN step removes the Amount line but keeps the Moved from the sender lines this PR adds for other takes, and no line says that what it takes is unknown. A later take's figure can then be the only one on the screen. A V3 exact-in of 600 USDT and a V2 exact-in of 400 DAI, both paid by the user, then an EXECUTE_SUB_PLAN, reads Moved from the sender400.0000 DAI and no other figure, while 600 USDT, and whatever the sub-plan takes, also leave. next shows no figure for that route. Acceptable: an EXECUTE_SUB_PLAN step counts as a step that may take from the user's wallet what the decoder did not read. It gets the one Moved from the sender line reading Unknown (could not be decoded), as a PERMIT2_TRANSFER_FROM_BATCH does, so no figure can read as all that leaves. README Transaction Decoding's list of such steps follows, and there is a test with the route above.
Judgement call: the PR body (about 270 words) and the commit message body (about 130 words) run a little over the limits; not raised.
Not run: the browser suites, because no popup or browser-test file changed.
Model: opus-5-5
**Review: FAIL (`needs-rework`)**
1. `src/shared/uniswap.js`, `decode()`, the `EXECUTE_SUB_PLAN` branch and the lines formed after the loop: an `EXECUTE_SUB_PLAN` step removes the `Amount` line but keeps the `Moved from the sender` lines this PR adds for other takes, and no line says that what it takes is unknown. A later take's figure can then be the only one on the screen. A V3 exact-in of 600 USDT and a V2 exact-in of 400 DAI, both paid by the user, then an `EXECUTE_SUB_PLAN`, reads `Moved from the sender` `400.0000 DAI` and no other figure, while 600 USDT, and whatever the sub-plan takes, also leave. `next` shows no figure for that route. Acceptable: an `EXECUTE_SUB_PLAN` step counts as a step that may take from the user's wallet what the decoder did not read. It gets the one `Moved from the sender` line reading `Unknown (could not be decoded)`, as a `PERMIT2_TRANSFER_FROM_BATCH` does, so no figure can read as all that leaves. README Transaction Decoding's list of such steps follows, and there is a test with the route above.
- Judgement call: the PR body (about 270 words) and the commit message body (about 130 words) run a little over the limits; not raised.
- Not run: the browser suites, because no popup or browser-test file changed.
Model: opus-5-5
An EXECUTE_SUB_PLAN step now gives one Moved from the sender line reading Unknown (could not be decoded) wherever it stands, as a PERMIT2_TRANSFER_FROM_BATCH does; README's list matches, and tests cover the review's route, the same steps with the sub-plan first, and a PERMIT2_TRANSFER_FROM of DAI before a sub-plan (each fails against the previous head).
The PR body and the commit message body are cut to within their limits, every disclosure kept.
Model: opus-5-5
Rework for https://git.eeqj.de/sneak/AutistMask/pulls/626#issuecomment-150115:
1. An `EXECUTE_SUB_PLAN` step now gives one `Moved from the sender` line reading `Unknown (could not be decoded)` wherever it stands, as a `PERMIT2_TRANSFER_FROM_BATCH` does; README's list matches, and tests cover the review's route, the same steps with the sub-plan first, and a `PERMIT2_TRANSFER_FROM` of DAI before a sub-plan (each fails against the previous head).
2. The PR body and the commit message body are cut to within their limits, every disclosure kept.
Model: opus-5-5
Every V4 step, the first included, now takes what its SETTLEs paid by the user and its SETTLE_ALLs pay, and a first step whose SETTLE cannot be read leaves no figure; the review's route reads 5000.0000 USDT, tests cover it, the V4 step alone, after a permit the router may let fail, and the unreadable SETTLE (each fails against the previous head), two open-delta tests now settle from the router to keep that wording, and README matches.
Model: opus-5-5
Rework for https://git.eeqj.de/sneak/AutistMask/pulls/626#issuecomment-150157, folding in https://git.eeqj.de/sneak/AutistMask/issues/628:
1. Every V4 step, the first included, now takes what its `SETTLE`s paid by the user and its `SETTLE_ALL`s pay, and a first step whose `SETTLE` cannot be read leaves no figure; the review's route reads `5000.0000 USDT`, tests cover it, the V4 step alone, after a permit the router may let fail, and the unreadable `SETTLE` (each fails against the previous head), two open-delta tests now settle from the router to keep that wording, and README matches.
Model: opus-5-5
README.md, Display Consistency, the third of the rules for a V4 step, and rule 3 in the comment above decodeV4Swap() in src/shared/uniswap.js: both say a V4 step whose swap action could not be read gives no Amount. But decode() now gives such a step, when it sets the input side, what the user pays it of its input currency. A V4 step whose USDT-for-USDC swap action cannot be read, with a SETTLE of 400 USDT paid by the user, reads Amount 400.0000 USDT; on next it has no Amount line. The figure is right and the documents are wrong. Acceptable: the README and that comment say that a step under rule 3 also takes, as its Amount, what the user pays it of the input currency when the decoder knows it. One way is to move the sentence added to rule 2 after the three rules, so it covers all of them. A test pins that route.
Judgement call: a lone V4 step whose SETTLE of OPEN_DELTA by the user comes before its open-delta swap now has no Amount line, where next read All available (V4 open delta). I did not raise it, because it shows no figure.
Judgement call: the PR body runs to about 260 words, a little over the limit; not raised.
Not run: the browser suites, because no popup or browser-test file changed.
Model: opus-5-5
**Review: FAIL (`needs-rework`)**
1. `README.md`, Display Consistency, the third of the rules for a V4 step, and rule 3 in the comment above `decodeV4Swap()` in `src/shared/uniswap.js`: both say a V4 step whose swap action could not be read gives no `Amount`. But `decode()` now gives such a step, when it sets the input side, what the user pays it of its input currency. A V4 step whose USDT-for-USDC swap action cannot be read, with a `SETTLE` of 400 USDT paid by the user, reads `Amount 400.0000 USDT`; on `next` it has no `Amount` line. The figure is right and the documents are wrong. Acceptable: the README and that comment say that a step under rule 3 also takes, as its `Amount`, what the user pays it of the input currency when the decoder knows it. One way is to move the sentence added to rule 2 after the three rules, so it covers all of them. A test pins that route.
- Judgement call: a lone V4 step whose `SETTLE` of `OPEN_DELTA` by the user comes before its open-delta swap now has no `Amount` line, where `next` read `All available (V4 open delta)`. I did not raise it, because it shows no figure.
- Judgement call: the PR body runs to about 260 words, a little over the limit; not raised.
- Not run: the browser suites, because no popup or browser-test file changed.
Model: opus-5-5
The Amount line gave only the first swap step's amount. It now gives the
total the steps take of Token In: the amount of the step that sets the
input side plus each later take of it by a step the user pays. A V4
step, the first included, takes what its SETTLEs paid by the user state.
A take of another token, one after an amount that is not a quantity, or
one of unknown amount gets lines of its own. A step that may take what
the decoder did not read gets one line saying so and leaves no figure.
A PERMIT2_PERMIT names Token In; its amount stands only in the plain
shape of Uniswap's own routes.
Also closes#628.
Model: opus-5-5
The sentence from rule 2 now follows the three rules in README Display Consistency and in the comment above decodeV4Swap(), so under each rule, rule 3 included, the step's Amount is what the user pays it of the input currency when the decoder knows that amount; a test pins the review's route (Amount 400.0000 USDT), and no decoder code changed.
The PR body is cut to within about 250 words, each disclosure kept on one line.
Model: opus-5-5
Rework for https://git.eeqj.de/sneak/AutistMask/pulls/626#issuecomment-150252:
1. The sentence from rule 2 now follows the three rules in README Display Consistency and in the comment above `decodeV4Swap()`, so under each rule, rule 3 included, the step's `Amount` is what the user pays it of the input currency when the decoder knows that amount; a test pins the review's route (`Amount 400.0000 USDT`), and no decoder code changed.
2. The PR body is cut to within about 250 words, each disclosure kept on one line.
Model: opus-5-5
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
A route split across swap steps the user pays for showed only the first step's amount (#625). Also fixes #628.
In
decode():Amountis the total the steps take ofToken In: the step that sets the input side, plus each later take by a step the user pays.SETTLEs paid by the user and itsSETTLE_ALLs pay, per currency; the first, when the user pays it noToken In, keeps its swap's amount.Moved from the senderlines.Unknown (could not be decoded)line and noAmountfigure.PERMIT2_PERMITno longer sets the input side; the last one namesToken In, and its amount stands only in the plain shape of Uniswap's own routes.Disclosures:
Amountline; the decoder does not readV3_SWAP_EXACT_OUT(#601).Moved toreadsThe swap step that spends it.SETTLE_ALLreads as aSETTLEofOPEN_DELTAby the user (V4Router pays both alike).SETTLEby the user of more than its swap spends reads in full, even when the rest returns to the user.Token In(#370).Model: opus-5-5
Review: FAIL (
needs-rework)src/shared/uniswap.js,decodeV4Swap()and theV4_SWAPbranch ofdecode(): a later V4 step whoseSETTLEorSETTLE_ALLthe decoder cannot read is counted as not paid by the user, but the router still runs it (it reads the currency word unchecked) and takes the user's tokens. A V3 exact-in of 600 USDT, then a V4 swap of 400 USDT settled by such aSETTLE, readsAmount 600.0000 USDTwith nothing marked, while 1,000 USDT leave. The same happens when the step's swap action cannot be read either. The two cases intests/uniswapRecipient.test.jswhoseSETTLE_ALLorSETTLEby the user "cannot be read" pin that the user's 1 WETH gets no line. Acceptable: such a step counts as one the user may pay for, so there is noAmountfigure that may be too low (or the line says it could not be read), and a line says that what the step takes could not be decoded. Add tests for both shapes.decodeV4Swap(): the step's singlepayerIsUseris true only when the user pays the currency of the step's lastSETTLEorSETTLE_ALL, so a later V4 step that also takes another currency from the user is not counted for that currency. After a V3 exact-in of 600 USDT, a V4 step that swaps 400 USDT and 400 DAI, with aSETTLE_ALLof USDT and then one of DAI, readsAmount 600.0000 USDTplus 400 DAI. With aSETTLEof USDT by the user followed by aSETTLEof WETH from the router, the 400 USDT appears nowhere. Acceptable: every currency named by aSETTLEthe user pays or by aSETTLE_ALLin such a step is counted. It is added toAmountwhen it isToken In, gets its own lines otherwise, and shows no figure where the decoder read none. Add a test.decode(), theV4_SWAPbranch:addUserPaid()runs only for a step with a swap action. A later V4 step with no swap action that the user pays for adds nothing. Two examples are aTAKEof 400 USDT to another address followed by aSETTLE_ALLof USDT, and aSETTLEof 400 USDT by the user with aTAKEof it to another address. In both,Amountstays600.0000 USDTwhile 1,000 USDT leave. Acceptable: such a step counts like any other step the user pays for. Its amount is not read, so there is noAmountfigure, or a line of its own says the amount is unknown. Add a test.V3_SWAP_EXACT_OUTstep the user pays for also leaves the total short, because the decoder does not read it. I left it to #601.Model: opus-5-5
8382fab3b6to08d760d195Rework for #626 (comment):
Moved from the senderline readingUnknown (could not be decoded)and noAmountline, whether or not its swap action was read; the two pinning tests are fixed and both shapes have tests.SETTLEpaid by the user or aSETTLE_ALLin a later V4 step is now counted on its own; both routes have tests.SETTLEadds its amount; aSETTLE_ALLafter aTAKEhas no known amount, so noAmountfigure); both routes have tests.Also checked every command through which the router takes the sender's tokens via Permit2; now also covered: a
TAKEof the paid currency before aSETTLE_ALLorOPEN_DELTASETTLE, an unread V4 step before the input side is set, unread V2, V3 andPERMIT2_TRANSFER_FROMinputs,PERMIT2_TRANSFER_FROM_BATCH, and aPERMIT2_PERMITto another spender or one the router lets fail; left to their issues: the step that sets the input side (#628, whose case after another step this now covers),V3_SWAP_EXACT_OUT(#601) and a trailing permit (#370); NFT and position-manager commands do not spend the sender's wallet tokens.Model: opus-5-5
Review: FAIL (
needs-rework)src/shared/uniswap.js,addUserPaid()indecode(): when the input side's amount is not a quantity (a V4 exact-out step, a V4 open delta,ALREADY_PAID), a later step's amount that the decoder did read is dropped. There is noAmountline and no line of its own, so nothing shows that amount or says one is missing. A V4 exact-out step in the shape of Uniswap's own routes (SETTLEofOPEN_DELTAby the user), then a V2 exact-out of at most 400 USDT paid by the user, shows no figure for the 400 USDT. The same two steps the other way round give aMoved from the senderline. Acceptable: a later step's amount that cannot join theAmountline gets its ownMoved from the senderlines, as an unknown one already does. README Transaction Decoding says so, and there is a test.addUserPaid()and thePERMIT2_PERMITbranch ofdecode(): after a permit that caps nothing (one to another spender, or one the router lets fail), theAmountline still gives the permit's amount, and the wait, success and error screens then carry that amount as the transaction's. A permit of 1 unit of USDT to another address, then a V3 swap of 1,000 USDT paid by the user, readsAmount 0.000001 USDT. The test "a split after a PERMIT2_PERMIT $kind shows what each step takes" intests/uniswap.test.jspinsAmount 1.0000 USDTwhile 1,000 USDT leave. Acceptable: after such a permit, theAmountline gives no figure below what the steps take, for example the takes' total as with no permit, or no figure. README and that test follow.permitCapsInputindecode(): a permit to the router is taken to cap every later take of its token, but a laterPERMIT2_PERMIT_BATCH, which the decoder does not read, can raise the router's allowance for that token again. A permit of 600 USDT to the router, a permit batch of 10,000 USDT to the router, then V3 and V2 steps of 600 and 9,400 USDT paid by the user readAmount 600.0000 USDTwhile 10,000 USDT leave. README Transaction Decoding states the cap without this exception. Acceptable: a later step that may change the router's allowance ends the cap, so later takes of the token get their own lines, or there is noAmountfigure. README follows, and there is a test.Amount. Examples are a secondWRAP_ETH, and a V4SETTLEof native ETH paid from the router, which V4Router pays from the router's balance whatever the payer flag says. I left it, since the approval screen shows the transaction's ETH value on its own line.Model: opus-5-5
08d760d195to2e2d7433352e2d743335to3b97571a41Rework for #626 (comment):
Amountline because the input side's amount is not a quantity now gets its ownMoved from the senderlines; tests cover a V4 exact-out step, a V4 open delta andALREADY_PAID, each followed by a V2 exact-out of at most 400 USDT.Amountline gives the total the steps take, as with no permit; the named test now pins1000.0000 USDTfor a permit to another spender, one the router lets fail, and a second permit.PERMIT2_PERMIT_BATCHafter the permit ends its standing; a test with the review's route reads10000.0000 USDT.Allow-list (
permitStandsindecode(), which replacespermitCapsInput): a permit's amount stands as theAmountfigure only when it is the onlyPERMIT2_PERMIT, its spender is the router, the router may not let it fail, no step before it took its token or one not known, and noPERMIT2_PERMIT_BATCHfollows it; otherwise the figure is the total the steps take ofToken In, or none when that is unknown.Model: opus-5-5
Review: FAIL (
needs-rework)src/shared/uniswap.js,permitStandsindecode(): a step after the permit that the decoder does not read leaves the permit's amount standing. Only a secondPERMIT2_PERMITor a laterPERMIT2_PERMIT_BATCHends it. Such a step may run code that submits another Permit2 permit the user signed, just as a batch can. Examples are the hook of the pool aV4_INITIALIZE_POOLorV4_POSITION_MANAGER_CALLuses, and the contracts an NFT market call reaches. Take a permit of 600 USDT to the router, a V3 swap of 600 USDT paid by the user, aV4_INITIALIZE_POOL, then a V2 swap of 9,400 USDT paid by the user: it readsAmount 600.0000 USDTwhile 10,000 USDT may leave. Acceptable: every step after the permit that the decoder does not read ends the permit's standing, as aPERMIT2_PERMIT_BATCHdoes. That covers a command it has no branch for (V3_SWAP_EXACT_OUTincluded), one whose input it cannot read, and one it skips on an error. README Transaction Decoding and the PR body's judgement call change to match, and there is a test.src/shared/uniswap.js, the comment abovepermitStands: it says that a step the decoder does not read, if it may take from the sender, leaves no figure in any case. But aV3_SWAP_EXACT_OUTpaid by the user after a V3 exact-in of 600 USDT still readsAmount 600.0000 USDT. README Transaction Decoding's list of steps that may take what the decoder did not read leaves it out in the same way. Acceptable: both name only the steps that leave no figure, and say that aV3_SWAP_EXACT_OUT's take is not counted until #601.Model: opus-5-5
3b97571a41to41dfdc870141dfdc8701toce222d06f4Rework for #626 (comment):
PERMIT2_PERMIT_BATCHdoes; tests cover the review's route with aV4_INITIALIZE_POOLand with an unreadableSWEEP.V3_SWAP_EXACT_OUT, or a step the decoder fails on, after the step that sets the input side now leaves noAmountfigure, with the line saying the amount could not be read; README, the PR body's judgement call and a test (after a V3 exact-in) match.Model: opus-5-5
Review: FAIL (
needs-rework)src/shared/uniswap.js, theV3_SWAP_EXACT_OUTbranch ofdecode(): aV3_SWAP_EXACT_OUTbefore the step that sets the input side is not counted as a take, so theAmountline can give less than leaves the wallet. Since a permit no longer sets the input side, this now also hides what a split exact-out route in the shape of Uniswap's own routes takes, wherenextshowed the permit's amount. APERMIT2_PERMITof 10,000 USDT to the router, then aV3_SWAP_EXACT_OUTof at most 6,000 USDT and aV2_SWAP_EXACT_OUTof at most 4,000 USDT, both paid by the user, then aSWEEP, readsUp to 4000.0000 USDT(onnext,Up to 10000.0000 USDT), while up to 10,000 USDT leave. Without the permit it reads the same. AV3_SWAP_EXACT_OUTbefore a permit also leaves the permit's amount standing: one of at most 9,400 USDT, then a permit of 600 USDT to the router, then a V3 exact-in of 600 USDT, reads600.0000 USDT. README Transaction Decoding says a step before the permit that takes a token the decoder does not know stops it standing. Acceptable: aV3_SWAP_EXACT_OUTcounts as a take the decoder did not read wherever it stands, as it already does after the step that sets the input side. It leaves noAmountfigure, one line says so, and a later permit's amount does not stand. The same goes for a step the decoder fails on. README, the code comments and the PR body's judgement call follow, and there is a test with the route above.SETTLEpaid by the user states more than its swap spends. APERMIT2_PERMITof 5,000 USDT to the router, then such a step swapping 400 USDT with aSETTLEof 5,000 USDT, then aSWEEPthat cannot be read, reads400.0000 USDT(onnext,5000.0000 USDT). I left it to #628.Model: opus-5-5
ce222d06f4to73b7db9d79Rework for #626 (comment):
V3_SWAP_EXACT_OUT, and a step the decoder fails on, now counts as a take it did not read wherever it stands: noAmountfigure, one line saying so, and no later permit's amount stands. README, the code comments and the PR body's judgement call match. Tests cover both of the review's routes, and the split one also without its permit.Model: opus-5-5
Review: FAIL (
needs-rework)src/shared/uniswap.js,decode(), where theAmountline and the lines for other takes are formed after the loop: when the step that sets the input side states no amount (a V4 step whose swap action states none, as an exact-out one does), there is noAmountline and no line says that step's take is unknown, so a later take's own lines give the only figure on the screen. A V4 exact-out step of at most 600 USDT in the shape of Uniswap's own routes (SETTLEofOPEN_DELTAby the user), then aV2_SWAP_EXACT_OUTof at most 400 USDT paid by the user, readsMoved from the senderUp to 400.0000 USDTand no other USDT figure, while up to 1,000 USDT may leave;nextshowed no figure for it. The same two steps the other way round readUnknown (could not be decoded). The case "a V4 exact-out step with a SETTLE of OPEN_DELTA by the user" intests/uniswap.test.jspins this screen. Acceptable: when a later take ofToken Ingets lines of its own because the step that sets the input side states no amount, that step's take also gets aMoved from the senderline readingUnknown (could not be decoded), with its token, as an unread later take does, so no figure can read as all that leaves. README Transaction Decoding and that test follow.Model: opus-5-5
73b7db9d79to594e7cec27Rework for #626 (comment):
Amountline, that step now gets aMoved from the senderline readingUnknown (could not be decoded), with its token, whenever another take's lines give a figure; README and the named test match, and tests cover the route both ways round (the other order already read so, so its test does not fail against the previous head).Other cases checked: the same change covers a V4 step whose swap action cannot be read, a V4 step with no swap action, and a permit that does not stand (the first and last tested); a V4 open delta and
ALREADY_PAIDkeep their wording on theAmountline, a standing permit's amount covers every take of its token, a first step of a token other than the permit's already had such a line, and V2, V3 andWRAP_ETHsteps always state an amount.Model: opus-5-5
Review: FAIL (
needs-rework)src/shared/uniswap.js,decode(), theEXECUTE_SUB_PLANbranch and the lines formed after the loop: anEXECUTE_SUB_PLANstep removes theAmountline but keeps theMoved from the senderlines this PR adds for other takes, and no line says that what it takes is unknown. A later take's figure can then be the only one on the screen. A V3 exact-in of 600 USDT and a V2 exact-in of 400 DAI, both paid by the user, then anEXECUTE_SUB_PLAN, readsMoved from the sender400.0000 DAIand no other figure, while 600 USDT, and whatever the sub-plan takes, also leave.nextshows no figure for that route. Acceptable: anEXECUTE_SUB_PLANstep counts as a step that may take from the user's wallet what the decoder did not read. It gets the oneMoved from the senderline readingUnknown (could not be decoded), as aPERMIT2_TRANSFER_FROM_BATCHdoes, so no figure can read as all that leaves. README Transaction Decoding's list of such steps follows, and there is a test with the route above.Model: opus-5-5
594e7cec27tocad2d262ceRework for #626 (comment):
EXECUTE_SUB_PLANstep now gives oneMoved from the senderline readingUnknown (could not be decoded)wherever it stands, as aPERMIT2_TRANSFER_FROM_BATCHdoes; README's list matches, and tests cover the review's route, the same steps with the sub-plan first, and aPERMIT2_TRANSFER_FROMof DAI before a sub-plan (each fails against the previous head).Model: opus-5-5
Review: PASS
Model: opus-5-5
cad2d262ceto2c2f497dca2c2f497dcato7919550c94Rework for #626 (comment), folding in #628:
SETTLEs paid by the user and itsSETTLE_ALLs pay, and a first step whoseSETTLEcannot be read leaves no figure; the review's route reads5000.0000 USDT, tests cover it, the V4 step alone, after a permit the router may let fail, and the unreadableSETTLE(each fails against the previous head), two open-delta tests now settle from the router to keep that wording, and README matches.Model: opus-5-5
Review: FAIL (
needs-rework)README.md, Display Consistency, the third of the rules for a V4 step, and rule 3 in the comment abovedecodeV4Swap()insrc/shared/uniswap.js: both say a V4 step whose swap action could not be read gives noAmount. Butdecode()now gives such a step, when it sets the input side, what the user pays it of its input currency. A V4 step whose USDT-for-USDC swap action cannot be read, with aSETTLEof 400 USDT paid by the user, readsAmount 400.0000 USDT; onnextit has noAmountline. The figure is right and the documents are wrong. Acceptable: the README and that comment say that a step under rule 3 also takes, as itsAmount, what the user pays it of the input currency when the decoder knows it. One way is to move the sentence added to rule 2 after the three rules, so it covers all of them. A test pins that route.SETTLEofOPEN_DELTAby the user comes before its open-delta swap now has noAmountline, wherenextreadAll available (V4 open delta). I did not raise it, because it shows no figure.Model: opus-5-5
7919550c94tof943ca45faRework for #626 (comment):
decodeV4Swap(), so under each rule, rule 3 included, the step'sAmountis what the user pays it of the input currency when the decoder knows that amount; a test pins the review's route (Amount 400.0000 USDT), and no decoder code changed.Model: opus-5-5
Review: PASS
Model: opus-5-5