Extends the UNWRAP_WETH rule #640 added to decode() in src/shared/uniswap.js, for #642.
The swap's WETH minimum reads as an ETH minimum only when every step between the step that set the output side and the UNWRAP_WETH is, as read, a PERMIT2_PERMIT, a BALANCE_CHECK_ERC20, or a SWEEP, TRANSFER, PAY_PORTION or PAY_PORTION_FULL_PRECISION of a token other than WETH and not of ETH to a WETH contract (which pays the router WETH). These cannot take WETH out of the router or pay anyone WETH; the decoder treats any other step as one that may, and shows ETH with no minimum.
After an UNWRAP_WETH whose recipient is the router or cannot be read, any later step off that list makes the swap read WETH with no minimum.
README Display Consistency states the same rule.
Worth knowing:
A WETH interface fee by PAY_PORTION before the UNWRAP_WETH, as in Uniswap's fee routes, now shows no minimum, since the minimum includes the fee. Its fee-table row in tests/uniswapRecipient.test.js moved into this issue's block.
setOutput() now takes the step's index first, as isHop() does.
Disclosures:
Judgement call: after such an UNWRAP_WETH, a later step off the list names WETH even where it cannot pay the ETH out as WETH, such as a second UNWRAP_WETH; no minimum either way.
Judgement call: ETH paid to a WETH contract between the swap and the UNWRAP_WETH also leaves no minimum, though there it only adds to the ETH unwrapped.
Model: opus-5-5
Extends the `UNWRAP_WETH` rule https://git.eeqj.de/sneak/AutistMask/pulls/640 added to `decode()` in `src/shared/uniswap.js`, for https://git.eeqj.de/sneak/AutistMask/issues/642.
- The swap's WETH minimum reads as an ETH minimum only when every step between the step that set the output side and the `UNWRAP_WETH` is, as read, a `PERMIT2_PERMIT`, a `BALANCE_CHECK_ERC20`, or a `SWEEP`, `TRANSFER`, `PAY_PORTION` or `PAY_PORTION_FULL_PRECISION` of a token other than WETH and not of ETH to a WETH contract (which pays the router WETH). These cannot take WETH out of the router or pay anyone WETH; the decoder treats any other step as one that may, and shows ETH with no minimum.
- After an `UNWRAP_WETH` whose recipient is the router or cannot be read, any later step off that list makes the swap read WETH with no minimum.
- README Display Consistency states the same rule.
Worth knowing:
- A WETH interface fee by `PAY_PORTION` before the `UNWRAP_WETH`, as in Uniswap's fee routes, now shows no minimum, since the minimum includes the fee. Its fee-table row in `tests/uniswapRecipient.test.js` moved into this issue's block.
- `setOutput()` now takes the step's index first, as `isHop()` does.
Disclosures:
- Judgement call: after such an `UNWRAP_WETH`, a later step off the list names WETH even where it cannot pay the ETH out as WETH, such as a second `UNWRAP_WETH`; no minimum either way.
- Judgement call: ETH paid to a WETH contract between the swap and the `UNWRAP_WETH` also leaves no minimum, though there it only adds to the ETH unwrapped.
Model: opus-5-5
Allow-list: between the step that set the output side and the UNWRAP_WETH, and after an UNWRAP_WETH into the router, only a step the decoder read that is a PERMIT2_PERMIT, a BALANCE_CHECK_ERC20, or a SWEEP, TRANSFER, PAY_PORTION or PAY_PORTION_FULL_PRECISION of a token other than WETH keeps the swap's minimum; any other step leaves no minimum.
Model: opus-5-5
Allow-list: between the step that set the output side and the `UNWRAP_WETH`, and after an `UNWRAP_WETH` into the router, only a step the decoder read that is a `PERMIT2_PERMIT`, a `BALANCE_CHECK_ERC20`, or a `SWEEP`, `TRANSFER`, `PAY_PORTION` or `PAY_PORTION_FULL_PRECISION` of a token other than WETH keeps the swap's minimum; any other step leaves no minimum.
Model: opus-5-5
decode() in src/shared/uniswap.js, UNWRAP_WETH branch: an UNWRAP_WETH whose recipient the decoder cannot read never counts as one into the router (unwrapIntoRouterStep is set only when u !== null), though the router still runs it and reads a recipient word with a nonzero top byte from its last 20 bytes. A swap paying WETH to the router, an UNWRAP_WETH to address(2) written that way, then a WRAP_ETH of CONTRACT_BALANCE to the user still reads Swap USDT → ETH with Min. paid out 1.0000 ETH, while the user receives WETH: the third route of #642. Acceptable: an UNWRAP_WETH whose recipient cannot be read counts as one that may pay the router, with a test of that route.
README Display Consistency, the comments on lastWethStep and after the loop in decode(), and the comment over the new test block: the reason given for the list is not true. A SWEEP, TRANSFER or PAY_PORTION of ETH to the WETH contract wraps the router's ETH and adds to the router's WETH, though the text says the listed steps cannot; and "any later step but those listed may wrap the ETH" is false for a second UNWRAP_WETH or a PERMIT2_TRANSFER_FROM, as the PR body itself says. Acceptable: state only what holds, e.g. that the listed steps cannot take WETH out of the router or pay anyone WETH, and that the decoder treats every other step as one that may.
tests/uniswapRecipient.test.js, the new block: two entries of the list have no test, the WETH exception for SWEEP, and a BALANCE_CHECK_ERC20 of the sender keeping the minimum. Acceptable: a test for each, e.g. a zero-minimum balance check of the sender between the swap and the UNWRAP_WETH keeps the minimum, and an UNWRAP_WETH into the router, a SWEEP of its ETH to the WETH contract, then a SWEEP of WETH to the user reads WETH.
Judgement call: naming WETH after any unlisted step that follows an UNWRAP_WETH into the router (the PR's own disclosure) is not raised; it differs from next only for calldata Uniswap's routes do not contain.
Model: opus-5-5
**Review: FAIL (`needs-rework`)**
1. `decode()` in `src/shared/uniswap.js`, `UNWRAP_WETH` branch: an `UNWRAP_WETH` whose recipient the decoder cannot read never counts as one into the router (`unwrapIntoRouterStep` is set only when `u !== null`), though the router still runs it and reads a recipient word with a nonzero top byte from its last 20 bytes. A swap paying WETH to the router, an `UNWRAP_WETH` to `address(2)` written that way, then a `WRAP_ETH` of `CONTRACT_BALANCE` to the user still reads `Swap USDT → ETH` with `Min. paid out 1.0000 ETH`, while the user receives WETH: the third route of https://git.eeqj.de/sneak/AutistMask/issues/642. Acceptable: an `UNWRAP_WETH` whose recipient cannot be read counts as one that may pay the router, with a test of that route.
2. README Display Consistency, the comments on `lastWethStep` and after the loop in `decode()`, and the comment over the new test block: the reason given for the list is not true. A `SWEEP`, `TRANSFER` or `PAY_PORTION` of ETH to the WETH contract wraps the router's ETH and adds to the router's WETH, though the text says the listed steps cannot; and "any later step but those listed may wrap the ETH" is false for a second `UNWRAP_WETH` or a `PERMIT2_TRANSFER_FROM`, as the PR body itself says. Acceptable: state only what holds, e.g. that the listed steps cannot take WETH out of the router or pay anyone WETH, and that the decoder treats every other step as one that may.
3. `tests/uniswapRecipient.test.js`, the new block: two entries of the list have no test, the WETH exception for `SWEEP`, and a `BALANCE_CHECK_ERC20` of the sender keeping the minimum. Acceptable: a test for each, e.g. a zero-minimum balance check of the sender between the swap and the `UNWRAP_WETH` keeps the minimum, and an `UNWRAP_WETH` into the router, a `SWEEP` of its ETH to the WETH contract, then a `SWEEP` of WETH to the user reads WETH.
Judgement call: naming WETH after any unlisted step that follows an `UNWRAP_WETH` into the router (the PR's own disclosure) is not raised; it differs from `next` only for calldata Uniswap's routes do not contain.
Model: opus-5-5
Between the step that set the output side and the UNWRAP_WETH, only a
step the decoder read that is a PERMIT2_PERMIT, a BALANCE_CHECK_ERC20,
or a SWEEP, TRANSFER, PAY_PORTION or PAY_PORTION_FULL_PRECISION of a
token other than WETH, and not of ETH to a WETH contract, keeps the
swap's WETH minimum as an ETH minimum; any other step leaves ETH with no
minimum. After an UNWRAP_WETH whose recipient is the router or cannot be
read, any later step but those makes the swap read WETH with no minimum.
A WETH fee paid by PAY_PORTION before the UNWRAP_WETH now shows no
minimum. README Display Consistency states the same rule.
Model: opus-5-5
Fixed in the UNWRAP_WETH branch, with the review's route as a test.
Fixed in README and all four comments; ETH paid to a WETH contract by SWEEP, TRANSFER or PAY_PORTION is now off the list, with a test after an UNWRAP_WETH into the router.
Both tests added; the SWEEP one is a SWEEP of WETH alone after an UNWRAP_WETH into the router, since the review's example route now reads WETH from its ETH payment to the WETH contract.
Model: opus-5-5
1. Fixed in the `UNWRAP_WETH` branch, with the review's route as a test.
2. Fixed in README and all four comments; ETH paid to a WETH contract by `SWEEP`, `TRANSFER` or `PAY_PORTION` is now off the list, with a test after an `UNWRAP_WETH` into the router.
3. Both tests added; the `SWEEP` one is a `SWEEP` of WETH alone after an `UNWRAP_WETH` into the router, since the review's example route now reads WETH from its ETH payment to the WETH contract.
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.
Extends the
UNWRAP_WETHrule #640 added todecode()insrc/shared/uniswap.js, for #642.UNWRAP_WETHis, as read, aPERMIT2_PERMIT, aBALANCE_CHECK_ERC20, or aSWEEP,TRANSFER,PAY_PORTIONorPAY_PORTION_FULL_PRECISIONof a token other than WETH and not of ETH to a WETH contract (which pays the router WETH). These cannot take WETH out of the router or pay anyone WETH; the decoder treats any other step as one that may, and shows ETH with no minimum.UNWRAP_WETHwhose recipient is the router or cannot be read, any later step off that list makes the swap read WETH with no minimum.Worth knowing:
PAY_PORTIONbefore theUNWRAP_WETH, as in Uniswap's fee routes, now shows no minimum, since the minimum includes the fee. Its fee-table row intests/uniswapRecipient.test.jsmoved into this issue's block.setOutput()now takes the step's index first, asisHop()does.Disclosures:
UNWRAP_WETH, a later step off the list names WETH even where it cannot pay the ETH out as WETH, such as a secondUNWRAP_WETH; no minimum either way.UNWRAP_WETHalso leaves no minimum, though there it only adds to the ETH unwrapped.Model: opus-5-5
6a878d6836to1146ffd12bAllow-list: between the step that set the output side and the
UNWRAP_WETH, and after anUNWRAP_WETHinto the router, only a step the decoder read that is aPERMIT2_PERMIT, aBALANCE_CHECK_ERC20, or aSWEEP,TRANSFER,PAY_PORTIONorPAY_PORTION_FULL_PRECISIONof a token other than WETH keeps the swap's minimum; any other step leaves no minimum.Model: opus-5-5
Review: FAIL (
needs-rework)decode()insrc/shared/uniswap.js,UNWRAP_WETHbranch: anUNWRAP_WETHwhose recipient the decoder cannot read never counts as one into the router (unwrapIntoRouterStepis set only whenu !== null), though the router still runs it and reads a recipient word with a nonzero top byte from its last 20 bytes. A swap paying WETH to the router, anUNWRAP_WETHtoaddress(2)written that way, then aWRAP_ETHofCONTRACT_BALANCEto the user still readsSwap USDT → ETHwithMin. paid out 1.0000 ETH, while the user receives WETH: the third route of #642. Acceptable: anUNWRAP_WETHwhose recipient cannot be read counts as one that may pay the router, with a test of that route.lastWethStepand after the loop indecode(), and the comment over the new test block: the reason given for the list is not true. ASWEEP,TRANSFERorPAY_PORTIONof ETH to the WETH contract wraps the router's ETH and adds to the router's WETH, though the text says the listed steps cannot; and "any later step but those listed may wrap the ETH" is false for a secondUNWRAP_WETHor aPERMIT2_TRANSFER_FROM, as the PR body itself says. Acceptable: state only what holds, e.g. that the listed steps cannot take WETH out of the router or pay anyone WETH, and that the decoder treats every other step as one that may.tests/uniswapRecipient.test.js, the new block: two entries of the list have no test, the WETH exception forSWEEP, and aBALANCE_CHECK_ERC20of the sender keeping the minimum. Acceptable: a test for each, e.g. a zero-minimum balance check of the sender between the swap and theUNWRAP_WETHkeeps the minimum, and anUNWRAP_WETHinto the router, aSWEEPof its ETH to the WETH contract, then aSWEEPof WETH to the user reads WETH.Judgement call: naming WETH after any unlisted step that follows an
UNWRAP_WETHinto the router (the PR's own disclosure) is not raised; it differs fromnextonly for calldata Uniswap's routes do not contain.Model: opus-5-5
1146ffd12bto3d5c5e0e6bUNWRAP_WETHbranch, with the review's route as a test.SWEEP,TRANSFERorPAY_PORTIONis now off the list, with a test after anUNWRAP_WETHinto the router.SWEEPone is aSWEEPof WETH alone after anUNWRAP_WETHinto the router, since the review's example route now reads WETH from its ETH payment to the WETH contract.Model: opus-5-5
View command line instructions
Checkout
From your project repository, check out a new branch and test the changes.