A WRAP_ETH that sets the input side and pays its WETH to anyone but the router now names that recipient on its Moved to line, or The sender for address(1).
V4 pays a SETTLE of ETH from the router's own ETH, whichever payer it names. So when the router may hold ETH from an earlier step, some of the ETH that the user pays a V4 step may come from the router. That ETH now gets lines of its own. Their Moved from the sender line reads Up to and the amount, or Unknown (could not be decoded) when the amount is not known. The decoder never subtracts the router's ETH, so no line shows less ETH than can leave the wallet. Without such an earlier step, every line reads as on next.
The decoder's existing record of what the router holds, unchanged here, says whether the router may hold ETH. An UNWRAP_WETH into the router adds ETH to that record. So does a V4 TAKE or TAKE_PORTION of ETH into the router.
Judgement call: that ETH never joins the Amount total. The Amount line and its own line together give the most that can leave.
Not covered: WETH that a PERMIT2_TRANSFER_FROM moves into the router is not in that record. ETH unwrapped from it leaves the V4 step's ETH as an exact figure, which can only be too high.
Unverified: what can leave on each route comes from reading the router's and V4Router's code, not from a run on a chain.
Model: opus-5-5
A `WRAP_ETH` that sets the input side and pays its WETH to anyone but the router now names that recipient on its `Moved to` line, or `The sender` for `address(1)`.
V4 pays a `SETTLE` of ETH from the router's own ETH, whichever payer it names. So when the router may hold ETH from an earlier step, some of the ETH that the user pays a V4 step may come from the router. That ETH now gets lines of its own. Their `Moved from the sender` line reads `Up to` and the amount, or `Unknown (could not be decoded)` when the amount is not known. The decoder never subtracts the router's ETH, so no line shows less ETH than can leave the wallet. Without such an earlier step, every line reads as on `next`.
The decoder's existing record of what the router holds, unchanged here, says whether the router may hold ETH. An `UNWRAP_WETH` into the router adds ETH to that record. So does a V4 `TAKE` or `TAKE_PORTION` of ETH into the router.
- Judgement call: that ETH never joins the `Amount` total. The `Amount` line and its own line together give the most that can leave.
- Not covered: WETH that a `PERMIT2_TRANSFER_FROM` moves into the router is not in that record. ETH unwrapped from it leaves the V4 step's ETH as an exact figure, which can only be too high.
- Unverified: what can leave on each route comes from reading the router's and V4Router's code, not from a run on a chain.
Model: opus-5-5
src/shared/uniswap.js, the new loop over v4.paidByUser in the V4_SWAP branch: when the decoder does not know how much ETH the router holds, or how much ETH the step takes, it drops that ETH from what the sender pays. The description then hides ETH that can leave the wallet:
A V3 exact-in of 600 USDT for WETH into the router, an UNWRAP_WETH into the router, then a V4 swap of 1 ETH the user settles: it reads Amount 600.0000 USDT with no ETH line. The V3 step may return almost no WETH, so nearly 1 ETH can come from the sender. The PR's first V4 test row pins this reading.
A V4 step that takes ETH into the router, then a V4 swap of 5 ETH the user settles: no ETH line. Up to 5 ETH can come from the sender.
A WRAP_ETH of 1 ETH into the router, an UNWRAP_WETH into the router, then a V4 exact-out paid in ETH with a SETTLE_ALL of at most 3 ETH: it reads Amount 1.0000 ETH. Up to 3 ETH can leave, and next reads the step's ETH as unknown.
Acceptable: the decoder subtracts only when both amounts are known. Otherwise the step's ETH from the sender reads Unknown (could not be decoded). Change that test row, the PR body's first judgement call, and this README sentence to match: "When the decoder does not know how much ETH the router holds, or how much the step would take, it counts the router as paying all of that ETH."
src/shared/uniswap.js, spendFromRouter() and the V2/V3 exact-out branch: the router's known amount can be too high. A V2 or V3 exact-out paid from the router spends some of it and leaves the figure unchanged. So does a V4 SETTLE from the router whose amount the decoder cannot tell. The PR now subtracts that figure from what the sender pays, so the description understates:
A WRAP_ETH of 1 ETH into the router, a V3 exact-out paid from the router of at most 1 WETH, an UNWRAP_WETH into the router, then a V4 swap of 1 ETH the user settles: the Amount line reads Up to 1.0000 ETH. Up to 2 ETH can leave.
The same route with a V4 exact-out of ETH paid from the router in place of the V3 step: it reads Amount 1.0000 ETH and Min. received. Up to 2 ETH can leave.
Acceptable: a step that spends an unstated amount of a token from the router makes the router's amount of that token unknown, with a test for each case. This README sentence is false and must change with it: "The decoder then knows how much ETH the router holds only when it knew the WETH's amount and the router held no ETH before."
Sentences a newcomer must read twice:
README.md: "An UNWRAP_WETH into the router turns all the router's WETH into as much ETH." Suggested: "An UNWRAP_WETH into the router turns all the router's WETH into the same amount of ETH."
README.md: "A V4 SETTLE of ETH spends the ETH the router holds, whoever pays it (see below)." Suggested: "A V4 SETTLE of ETH always spends the router's own ETH, whichever payer it names (see below)."
src/shared/uniswap.js, the comment above the loop that writes the Moved from the sender lines: "A take with a recipient goes there, and MSG_SENDER there is the sender." Suggested: "A take with a recipient goes to that recipient; MSG_SENDER means the sender."
Judgement call: when the router's ETH amount is unknown, a Moved from the sender line reading Unknown (could not be decoded) meets the second item of #665.
Model: opus-5-5
**Review: FAIL (needs-rework)**
1. `src/shared/uniswap.js`, the new loop over `v4.paidByUser` in the `V4_SWAP` branch: when the decoder does not know how much ETH the router holds, or how much ETH the step takes, it drops that ETH from what the sender pays. The description then hides ETH that can leave the wallet:
- A V3 exact-in of 600 USDT for WETH into the router, an `UNWRAP_WETH` into the router, then a V4 swap of 1 ETH the user settles: it reads `Amount 600.0000 USDT` with no ETH line. The V3 step may return almost no WETH, so nearly 1 ETH can come from the sender. The PR's first V4 test row pins this reading.
- A V4 step that takes ETH into the router, then a V4 swap of 5 ETH the user settles: no ETH line. Up to 5 ETH can come from the sender.
- A `WRAP_ETH` of 1 ETH into the router, an `UNWRAP_WETH` into the router, then a V4 exact-out paid in ETH with a `SETTLE_ALL` of at most 3 ETH: it reads `Amount 1.0000 ETH`. Up to 3 ETH can leave, and `next` reads the step's ETH as unknown.
Acceptable: the decoder subtracts only when both amounts are known. Otherwise the step's ETH from the sender reads `Unknown (could not be decoded)`. Change that test row, the PR body's first judgement call, and this README sentence to match: "When the decoder does not know how much ETH the router holds, or how much the step would take, it counts the router as paying all of that ETH."
2. `src/shared/uniswap.js`, `spendFromRouter()` and the V2/V3 exact-out branch: the router's known amount can be too high. A V2 or V3 exact-out paid from the router spends some of it and leaves the figure unchanged. So does a V4 `SETTLE` from the router whose amount the decoder cannot tell. The PR now subtracts that figure from what the sender pays, so the description understates:
- A `WRAP_ETH` of 1 ETH into the router, a V3 exact-out paid from the router of at most 1 WETH, an `UNWRAP_WETH` into the router, then a V4 swap of 1 ETH the user settles: the `Amount` line reads `Up to 1.0000 ETH`. Up to 2 ETH can leave.
- The same route with a V4 exact-out of ETH paid from the router in place of the V3 step: it reads `Amount 1.0000 ETH` and `Min. received`. Up to 2 ETH can leave.
Acceptable: a step that spends an unstated amount of a token from the router makes the router's amount of that token unknown, with a test for each case. This README sentence is false and must change with it: "The decoder then knows how much ETH the router holds only when it knew the WETH's amount and the router held no ETH before."
3. Sentences a newcomer must read twice:
- `README.md`: "An `UNWRAP_WETH` into the router turns all the router's WETH into as much ETH." Suggested: "An `UNWRAP_WETH` into the router turns all the router's WETH into the same amount of ETH."
- `README.md`: "A V4 `SETTLE` of ETH spends the ETH the router holds, whoever pays it (see below)." Suggested: "A V4 `SETTLE` of ETH always spends the router's own ETH, whichever payer it names (see below)."
- `src/shared/uniswap.js`, the comment above the loop that writes the `Moved from the sender` lines: "A take with a recipient goes there, and MSG_SENDER there is the sender." Suggested: "A take with a recipient goes to that recipient; `MSG_SENDER` means the sender."
Judgement call: when the router's ETH amount is unknown, a `Moved from the sender` line reading `Unknown (could not be decoded)` meets the second item of https://git.eeqj.de/sneak/AutistMask/issues/665.
Model: opus-5-5
Fixed: the router's ETH is subtracted only when both amounts are known; otherwise the step's ETH from the sender reads Unknown (could not be decoded). The three routes are tests, the first V4 row moved among them with its new reading, and the PR body and README sentence changed.
Fixed: a V2 or V3 exact-out paid from the router, and a V4 SETTLE from the router of an unknown amount, now make the router's amount of that token unknown. Both routes are tests (the V4 route's exact-out spends the router's WETH), and the README sentence changed.
Fixed: the suggested wording, for all three sentences.
Model: opus-5-5
Rework:
1. Fixed: the router's ETH is subtracted only when both amounts are known; otherwise the step's ETH from the sender reads `Unknown (could not be decoded)`. The three routes are tests, the first V4 row moved among them with its new reading, and the PR body and README sentence changed.
2. Fixed: a V2 or V3 exact-out paid from the router, and a V4 `SETTLE` from the router of an unknown amount, now make the router's amount of that token unknown. Both routes are tests (the V4 route's exact-out spends the router's WETH), and the README sentence changed.
3. Fixed: the suggested wording, for all three sentences.
Model: opus-5-5
src/shared/uniswap.js, the router's ETH that the V4_SWAP branch subtracts: that figure can still be higher than the ETH the router holds. Some steps pay out the router's ETH or WETH, and the decoder does not lower the figure. Each route below has a WRAP_ETH of 1 ETH into the router, an UNWRAP_WETH into the router, and last a V4 swap of 1 ETH that the user settles. Each adds one step:
a TRANSFER of 1 ETH to another address, after the UNWRAP_WETH: 2 ETH can leave;
a PAY_PORTION of 5,000 bips of WETH to another address, before the UNWRAP_WETH: 1.5 ETH can leave (a TRANSFER of 0.5 WETH there reads the same);
a WRAP_ETH of 1 ETH to another address, after the UNWRAP_WETH: 2 ETH can leave;
on UniversalRouterV2_1_2, an ACROSS_V4_DEPOSIT_V3 of 1 ETH with useNative, after the UNWRAP_WETH: 2 ETH can leave.
Each reads Amount 1.0000 ETH, and next reads at least what can leave. Acceptable: when a step may pay out the router's ETH or WETH and the decoder does not subtract the payment, the router's amount of that token becomes unknown. Such steps include a TRANSFER, PAY_PORTION, PAY_PORTION_FULL_PRECISION or ACROSS_V4_DEPOSIT_V3 of less than all of it, and a WRAP_ETH of a stated amount. Add a test for each. The comment above heldByRouter and the PR body both say that every step that spends an unstated amount makes the figure unknown. A PAY_PORTION of less than all of it does not, so both must change with the code.
src/shared/uniswap.js, the WRAP_ETH branch: only the WRAP_ETH that sets the input side counts as ETH moved from the sender. A later WRAP_ETH into the router still gives the router a known amount of WETH. After an UNWRAP_WETH into the router, the decoder now counts that amount as the router's ETH paying the V4 step. Route: a V3 exact-in of 600 USDT that the user pays, a WRAP_ETH of 1 ETH into the router, an UNWRAP_WETH into the router, then a V4 swap of 1 ETH that the user settles. It reads Amount 600.0000 USDT with no ETH line, though 1 ETH leaves the wallet. next reads Moved from the sender 1.0000 ETH. Acceptable: the decoder subtracts only ETH that the description counts as moved from the sender. On this route, the V4 step's ETH from the sender reads Unknown (could not be decoded). Add a test.
README.md, a sentence the PR shortened, which runs past 100 words and chains six conditions with commas: "The decoder takes that to be the amounts the step's swap actions state they spend of that token only when every action in the step could be read, [...] and the swap actions that spend it state a quantity together; otherwise it does not know the amount." Acceptable: "The decoder takes that to be the amounts the step's swap actions state they spend of that token only when all of these hold:", one bullet per condition, then "Otherwise it does not know the amount."
tests/uniswap.test.js, the comment above the two rows with an UNWRAP_WETH into the router: "On next each row also took the V4 step's whole ETH from the sender: 1 ETH more in the first, and 1.5 ETH in the last." It reads as 1.5 ETH more in the last row, but next reads 1 ETH more there too (2.5000 ETH). Suggested: "On next each row read 1 ETH more, because next took the V4 step's whole ETH from the sender."
Unverified: the ETH that can leave on each route comes from reading the router's and V4Router's code, not from a run on a chain.
Follow-up: the commit message body is slightly over 120 words; trim it in the rework.
Model: opus-5-5
**Review: FAIL (needs-rework)**
1. `src/shared/uniswap.js`, the router's ETH that the `V4_SWAP` branch subtracts: that figure can still be higher than the ETH the router holds. Some steps pay out the router's ETH or WETH, and the decoder does not lower the figure. Each route below has a `WRAP_ETH` of 1 ETH into the router, an `UNWRAP_WETH` into the router, and last a V4 swap of 1 ETH that the user settles. Each adds one step:
- a `TRANSFER` of 1 ETH to another address, after the `UNWRAP_WETH`: 2 ETH can leave;
- a `PAY_PORTION` of 5,000 bips of WETH to another address, before the `UNWRAP_WETH`: 1.5 ETH can leave (a `TRANSFER` of 0.5 WETH there reads the same);
- a `WRAP_ETH` of 1 ETH to another address, after the `UNWRAP_WETH`: 2 ETH can leave;
- on `UniversalRouterV2_1_2`, an `ACROSS_V4_DEPOSIT_V3` of 1 ETH with `useNative`, after the `UNWRAP_WETH`: 2 ETH can leave.
Each reads `Amount 1.0000 ETH`, and `next` reads at least what can leave. Acceptable: when a step may pay out the router's ETH or WETH and the decoder does not subtract the payment, the router's amount of that token becomes unknown. Such steps include a `TRANSFER`, `PAY_PORTION`, `PAY_PORTION_FULL_PRECISION` or `ACROSS_V4_DEPOSIT_V3` of less than all of it, and a `WRAP_ETH` of a stated amount. Add a test for each. The comment above `heldByRouter` and the PR body both say that every step that spends an unstated amount makes the figure unknown. A `PAY_PORTION` of less than all of it does not, so both must change with the code.
2. `src/shared/uniswap.js`, the `WRAP_ETH` branch: only the `WRAP_ETH` that sets the input side counts as ETH moved from the sender. A later `WRAP_ETH` into the router still gives the router a known amount of WETH. After an `UNWRAP_WETH` into the router, the decoder now counts that amount as the router's ETH paying the V4 step. Route: a V3 exact-in of 600 USDT that the user pays, a `WRAP_ETH` of 1 ETH into the router, an `UNWRAP_WETH` into the router, then a V4 swap of 1 ETH that the user settles. It reads `Amount 600.0000 USDT` with no ETH line, though 1 ETH leaves the wallet. `next` reads `Moved from the sender 1.0000 ETH`. Acceptable: the decoder subtracts only ETH that the description counts as moved from the sender. On this route, the V4 step's ETH from the sender reads `Unknown (could not be decoded)`. Add a test.
3. `README.md`, a sentence the PR shortened, which runs past 100 words and chains six conditions with commas: "The decoder takes that to be the amounts the step's swap actions state they spend of that token only when every action in the step could be read, [...] and the swap actions that spend it state a quantity together; otherwise it does not know the amount." Acceptable: "The decoder takes that to be the amounts the step's swap actions state they spend of that token only when all of these hold:", one bullet per condition, then "Otherwise it does not know the amount."
4. `tests/uniswap.test.js`, the comment above the two rows with an `UNWRAP_WETH` into the router: "On next each row also took the V4 step's whole ETH from the sender: 1 ETH more in the first, and 1.5 ETH in the last." It reads as 1.5 ETH more in the last row, but `next` reads 1 ETH more there too (`2.5000 ETH`). Suggested: "On `next` each row read 1 ETH more, because `next` took the V4 step's whole ETH from the sender."
Unverified: the ETH that can leave on each route comes from reading the router's and V4Router's code, not from a run on a chain.
Follow-up: the commit message body is slightly over 120 words; trim it in the rework.
Model: opus-5-5
A `WRAP_ETH` that sets the input side and pays its WETH to anyone but
the router names that recipient on its `Moved to` line.
V4 pays a `SETTLE` of ETH from the router's own ETH, whichever payer it
names. When an earlier step may leave ETH in the router, the ETH that
the user pays a later V4 step gets lines of its own. Their
`Moved from the sender` line reads `Up to <amount>`, or
`Unknown (could not be decoded)` when the amount is not known. The
decoder never subtracts the router's ETH, so no line shows less ETH
than can leave the wallet. Without such an earlier step, the lines read
as before.
Model: opus-5-5
clawbot
changed title from fix: the swap decoder names where a WRAP_ETH pays and counts the router's ETH in a V4 settle (closes #665) to fix: the swap decoder names where a WRAP_ETH pays and shows a V4 step's ETH as a maximum when the router may hold ETH (closes #665)2026-10-27 02:55:21 +01:00
Rework: the router-ETH subtraction is gone, because tracking how much ETH the router holds kept missing steps that pay it out. When the router may hold ETH, a V4 step's ETH from the user now reads Up to and the amount, on lines of its own.
First review: its five routes are tests, and each reads Up to or Unknown (could not be decoded) for the V4 step's ETH. Its three sentences went with the subtraction, and the Moved to comment keeps the suggested wording.
Second review:
The four routes are tests. Each reads Amount 1.0000 ETH plus Moved from the senderUp to 1.0000 ETH.
The route is a test. It reads Amount 600.0000 USDT plus Up to 1.0000 ETH.
The PR no longer changes that sentence, which reads as on next. Bullets there would rewrap about 180 unrelated README lines.
That test comment is gone. The new group's comment says what next read.
Follow-up: the commit message body is under 120 words.
Model: opus-5-5
Rework: the router-ETH subtraction is gone, because tracking how much ETH the router holds kept missing steps that pay it out. When the router may hold ETH, a V4 step's ETH from the user now reads `Up to` and the amount, on lines of its own.
First review: its five routes are tests, and each reads `Up to` or `Unknown (could not be decoded)` for the V4 step's ETH. Its three sentences went with the subtraction, and the `Moved to` comment keeps the suggested wording.
Second review:
1. The four routes are tests. Each reads `Amount 1.0000 ETH` plus `Moved from the sender` `Up to 1.0000 ETH`.
2. The route is a test. It reads `Amount 600.0000 USDT` plus `Up to 1.0000 ETH`.
3. The PR no longer changes that sentence, which reads as on `next`. Bullets there would rewrap about 180 unrelated README lines.
4. That test comment is gone. The new group's comment says what `next` read.
Follow-up: the commit message body is under 120 words.
Model: opus-5-5
README.md, Transaction Decoding: the PR adds a fourth item to a sentence that is already a list chained with semicolons, and it now runs about 90 words: "Each take the total does not count gives three lines after the Amount line (after Token In when there is none): one of a token other than Token In; [...]; and one of ETH that the user pays a V4 step when the router may hold ETH." Acceptable: leave that sentence as on next, and add a short one after it: "ETH that the user pays a V4 step when the router may hold ETH gets these three lines too."
Commit message and PR body: "The decoder never subtracts the router's ETH, so no line shows less ETH than can leave the wallet." This is false on routes the PR does not change:
a PERMIT2_PERMIT to the router of 1 wei of the zero address, then a V4 swap of 5 ETH that the user settles, reads Amount 0.000000000000000001 ETH;
a V3 exact-in of 600 USDT, then a V4 swap whose SETTLE of 1 ETH names the router as payer, reads no ETH line, though the transaction's value pays that ETH.
Acceptable: claim only what the change does, for example "The decoder never subtracts the router's ETH from that amount."
Judgement call: a Moved from the sender line reading Up to and the amount meets the second item of the definition of done in #665.
Unverified: what can leave on each route comes from reading the router's and V4Router's code, not from a run on a chain.
Model: opus-5-5
**Review: FAIL (needs-rework)**
1. `README.md`, Transaction Decoding: the PR adds a fourth item to a sentence that is already a list chained with semicolons, and it now runs about 90 words: "Each take the total does not count gives three lines after the `Amount` line (after `Token In` when there is none): one of a token other than `Token In`; [...]; and one of ETH that the user pays a V4 step when the router may hold ETH." Acceptable: leave that sentence as on `next`, and add a short one after it: "ETH that the user pays a V4 step when the router may hold ETH gets these three lines too."
2. Commit message and PR body: "The decoder never subtracts the router's ETH, so no line shows less ETH than can leave the wallet." This is false on routes the PR does not change:
- a `PERMIT2_PERMIT` to the router of 1 wei of the zero address, then a V4 swap of 5 ETH that the user settles, reads `Amount 0.000000000000000001 ETH`;
- a V3 exact-in of 600 USDT, then a V4 swap whose `SETTLE` of 1 ETH names the router as payer, reads no ETH line, though the transaction's value pays that ETH.
Acceptable: claim only what the change does, for example "The decoder never subtracts the router's ETH from that amount."
Judgement call: a `Moved from the sender` line reading `Up to` and the amount meets the second item of the definition of done in https://git.eeqj.de/sneak/AutistMask/issues/665.
Unverified: what can leave on each route comes from reading the router's and V4Router's code, not from a run on a chain.
Model: opus-5-5
The third found no new understated route in this change, only a README sentence and a claim in the PR body and commit message. No further rework, rebase or review until you have reviewed it.
Model: opus-5-5
Paused for sneak's review, under the rule that a PR failing review three times waits for him (https://git.eeqj.de/sneak/project-management/issues/43). It fixes https://git.eeqj.de/sneak/AutistMask/issues/665.
Failed reviews:
- https://git.eeqj.de/sneak/AutistMask/pulls/679#issuecomment-157260
- https://git.eeqj.de/sneak/AutistMask/pulls/679#issuecomment-157464
- https://git.eeqj.de/sneak/AutistMask/pulls/679#issuecomment-157576
The third found no new understated route in this change, only a README sentence and a claim in the PR body and commit message. No further rework, rebase or review until you have reviewed it.
Model: opus-5-5
clawbot
removed their assignment 2026-10-27 03:29:33 +01:00
sneak
was assigned by clawbot2026-10-27 03:29:33 +01:00
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
WRAP_ETHthat sets the input side and pays its WETH to anyone but the router now names that recipient on itsMoved toline, orThe senderforaddress(1).V4 pays a
SETTLEof ETH from the router's own ETH, whichever payer it names. So when the router may hold ETH from an earlier step, some of the ETH that the user pays a V4 step may come from the router. That ETH now gets lines of its own. TheirMoved from the senderline readsUp toand the amount, orUnknown (could not be decoded)when the amount is not known. The decoder never subtracts the router's ETH, so no line shows less ETH than can leave the wallet. Without such an earlier step, every line reads as onnext.The decoder's existing record of what the router holds, unchanged here, says whether the router may hold ETH. An
UNWRAP_WETHinto the router adds ETH to that record. So does a V4TAKEorTAKE_PORTIONof ETH into the router.Amounttotal. TheAmountline and its own line together give the most that can leave.PERMIT2_TRANSFER_FROMmoves into the router is not in that record. ETH unwrapped from it leaves the V4 step's ETH as an exact figure, which can only be too high.Model: opus-5-5
Review: FAIL (needs-rework)
src/shared/uniswap.js, the new loop overv4.paidByUserin theV4_SWAPbranch: when the decoder does not know how much ETH the router holds, or how much ETH the step takes, it drops that ETH from what the sender pays. The description then hides ETH that can leave the wallet:UNWRAP_WETHinto the router, then a V4 swap of 1 ETH the user settles: it readsAmount 600.0000 USDTwith no ETH line. The V3 step may return almost no WETH, so nearly 1 ETH can come from the sender. The PR's first V4 test row pins this reading.WRAP_ETHof 1 ETH into the router, anUNWRAP_WETHinto the router, then a V4 exact-out paid in ETH with aSETTLE_ALLof at most 3 ETH: it readsAmount 1.0000 ETH. Up to 3 ETH can leave, andnextreads the step's ETH as unknown.Acceptable: the decoder subtracts only when both amounts are known. Otherwise the step's ETH from the sender reads
Unknown (could not be decoded). Change that test row, the PR body's first judgement call, and this README sentence to match: "When the decoder does not know how much ETH the router holds, or how much the step would take, it counts the router as paying all of that ETH."src/shared/uniswap.js,spendFromRouter()and the V2/V3 exact-out branch: the router's known amount can be too high. A V2 or V3 exact-out paid from the router spends some of it and leaves the figure unchanged. So does a V4SETTLEfrom the router whose amount the decoder cannot tell. The PR now subtracts that figure from what the sender pays, so the description understates:WRAP_ETHof 1 ETH into the router, a V3 exact-out paid from the router of at most 1 WETH, anUNWRAP_WETHinto the router, then a V4 swap of 1 ETH the user settles: theAmountline readsUp to 1.0000 ETH. Up to 2 ETH can leave.Amount 1.0000 ETHandMin. received. Up to 2 ETH can leave.Acceptable: a step that spends an unstated amount of a token from the router makes the router's amount of that token unknown, with a test for each case. This README sentence is false and must change with it: "The decoder then knows how much ETH the router holds only when it knew the WETH's amount and the router held no ETH before."
Sentences a newcomer must read twice:
README.md: "AnUNWRAP_WETHinto the router turns all the router's WETH into as much ETH." Suggested: "AnUNWRAP_WETHinto the router turns all the router's WETH into the same amount of ETH."README.md: "A V4SETTLEof ETH spends the ETH the router holds, whoever pays it (see below)." Suggested: "A V4SETTLEof ETH always spends the router's own ETH, whichever payer it names (see below)."src/shared/uniswap.js, the comment above the loop that writes theMoved from the senderlines: "A take with a recipient goes there, and MSG_SENDER there is the sender." Suggested: "A take with a recipient goes to that recipient;MSG_SENDERmeans the sender."Judgement call: when the router's ETH amount is unknown, a
Moved from the senderline readingUnknown (could not be decoded)meets the second item of #665.Model: opus-5-5
47b186841ato88cee51f5eRework:
Unknown (could not be decoded). The three routes are tests, the first V4 row moved among them with its new reading, and the PR body and README sentence changed.SETTLEfrom the router of an unknown amount, now make the router's amount of that token unknown. Both routes are tests (the V4 route's exact-out spends the router's WETH), and the README sentence changed.Model: opus-5-5
Review: FAIL (needs-rework)
src/shared/uniswap.js, the router's ETH that theV4_SWAPbranch subtracts: that figure can still be higher than the ETH the router holds. Some steps pay out the router's ETH or WETH, and the decoder does not lower the figure. Each route below has aWRAP_ETHof 1 ETH into the router, anUNWRAP_WETHinto the router, and last a V4 swap of 1 ETH that the user settles. Each adds one step:TRANSFERof 1 ETH to another address, after theUNWRAP_WETH: 2 ETH can leave;PAY_PORTIONof 5,000 bips of WETH to another address, before theUNWRAP_WETH: 1.5 ETH can leave (aTRANSFERof 0.5 WETH there reads the same);WRAP_ETHof 1 ETH to another address, after theUNWRAP_WETH: 2 ETH can leave;UniversalRouterV2_1_2, anACROSS_V4_DEPOSIT_V3of 1 ETH withuseNative, after theUNWRAP_WETH: 2 ETH can leave.Each reads
Amount 1.0000 ETH, andnextreads at least what can leave. Acceptable: when a step may pay out the router's ETH or WETH and the decoder does not subtract the payment, the router's amount of that token becomes unknown. Such steps include aTRANSFER,PAY_PORTION,PAY_PORTION_FULL_PRECISIONorACROSS_V4_DEPOSIT_V3of less than all of it, and aWRAP_ETHof a stated amount. Add a test for each. The comment aboveheldByRouterand the PR body both say that every step that spends an unstated amount makes the figure unknown. APAY_PORTIONof less than all of it does not, so both must change with the code.src/shared/uniswap.js, theWRAP_ETHbranch: only theWRAP_ETHthat sets the input side counts as ETH moved from the sender. A laterWRAP_ETHinto the router still gives the router a known amount of WETH. After anUNWRAP_WETHinto the router, the decoder now counts that amount as the router's ETH paying the V4 step. Route: a V3 exact-in of 600 USDT that the user pays, aWRAP_ETHof 1 ETH into the router, anUNWRAP_WETHinto the router, then a V4 swap of 1 ETH that the user settles. It readsAmount 600.0000 USDTwith no ETH line, though 1 ETH leaves the wallet.nextreadsMoved from the sender 1.0000 ETH. Acceptable: the decoder subtracts only ETH that the description counts as moved from the sender. On this route, the V4 step's ETH from the sender readsUnknown (could not be decoded). Add a test.README.md, a sentence the PR shortened, which runs past 100 words and chains six conditions with commas: "The decoder takes that to be the amounts the step's swap actions state they spend of that token only when every action in the step could be read, [...] and the swap actions that spend it state a quantity together; otherwise it does not know the amount." Acceptable: "The decoder takes that to be the amounts the step's swap actions state they spend of that token only when all of these hold:", one bullet per condition, then "Otherwise it does not know the amount."tests/uniswap.test.js, the comment above the two rows with anUNWRAP_WETHinto the router: "On next each row also took the V4 step's whole ETH from the sender: 1 ETH more in the first, and 1.5 ETH in the last." It reads as 1.5 ETH more in the last row, butnextreads 1 ETH more there too (2.5000 ETH). Suggested: "Onnexteach row read 1 ETH more, becausenexttook the V4 step's whole ETH from the sender."Unverified: the ETH that can leave on each route comes from reading the router's and V4Router's code, not from a run on a chain.
Follow-up: the commit message body is slightly over 120 words; trim it in the rework.
Model: opus-5-5
88cee51f5etocce6640d23fix: the swap decoder names where a WRAP_ETH pays and counts the router's ETH in a V4 settle (closes #665)to fix: the swap decoder names where a WRAP_ETH pays and shows a V4 step's ETH as a maximum when the router may hold ETH (closes #665)Rework: the router-ETH subtraction is gone, because tracking how much ETH the router holds kept missing steps that pay it out. When the router may hold ETH, a V4 step's ETH from the user now reads
Up toand the amount, on lines of its own.First review: its five routes are tests, and each reads
Up toorUnknown (could not be decoded)for the V4 step's ETH. Its three sentences went with the subtraction, and theMoved tocomment keeps the suggested wording.Second review:
Amount 1.0000 ETHplusMoved from the senderUp to 1.0000 ETH.Amount 600.0000 USDTplusUp to 1.0000 ETH.next. Bullets there would rewrap about 180 unrelated README lines.nextread.Follow-up: the commit message body is under 120 words.
Model: opus-5-5
Review: FAIL (needs-rework)
README.md, Transaction Decoding: the PR adds a fourth item to a sentence that is already a list chained with semicolons, and it now runs about 90 words: "Each take the total does not count gives three lines after theAmountline (afterToken Inwhen there is none): one of a token other thanToken In; [...]; and one of ETH that the user pays a V4 step when the router may hold ETH." Acceptable: leave that sentence as onnext, and add a short one after it: "ETH that the user pays a V4 step when the router may hold ETH gets these three lines too."Commit message and PR body: "The decoder never subtracts the router's ETH, so no line shows less ETH than can leave the wallet." This is false on routes the PR does not change:
PERMIT2_PERMITto the router of 1 wei of the zero address, then a V4 swap of 5 ETH that the user settles, readsAmount 0.000000000000000001 ETH;SETTLEof 1 ETH names the router as payer, reads no ETH line, though the transaction's value pays that ETH.Acceptable: claim only what the change does, for example "The decoder never subtracts the router's ETH from that amount."
Judgement call: a
Moved from the senderline readingUp toand the amount meets the second item of the definition of done in #665.Unverified: what can leave on each route comes from reading the router's and V4Router's code, not from a run on a chain.
Model: opus-5-5
Paused for sneak's review, under the rule that a PR failing review three times waits for him (sneak/project-management#43). It fixes #665.
Failed reviews:
The third found no new understated route in this change, only a README sentence and a claim in the PR body and commit message. No further rework, rebase or review until you have reviewed it.
Model: opus-5-5
View command line instructions
Checkout
From your project repository, check out a new branch and test the changes.