BALANCE_CHECK_ERC20 takes (address owner, address token, uint256 minBalance). The decoder read only the token and the minimum, so a swap paid to the user followed by a check of another address's balance read Min. received with that address's minimum.
Every release that has the command (UniversalRouterV1_2_V2Support, UniversalRouterV2, UniversalRouterV2_1_1, UniversalRouterV2_1_2) reads the owner as written, without map(), so address(1) and address(2) are plain addresses there, not the sender and the router.
Now:
A check whose owner is not the transaction's sender sets neither Token Out nor the minimum, and its step reads Balance Check (of another address).
A check whose input does not decode, such as an owner word with a nonzero top byte, which the router still runs on the word's last 20 bytes, sets neither and reads Balance Check (could not be decoded).
A check of the sender reads as before, including the zero reading for one the router lets fail (#602).
Not visible in the diff:
With no sender known, every check counts as of another address, as a payment to the user's address is then named.
tests/uniswapUndeterminedTokenIn.test.js now passes USER, its checks' owner, as the sender.
Judgement call: the Steps line says the check is of another address instead of a line naming the owner, because the owner is not paid and a Paid to line would say it is.
Out of scope: on UniversalRouterV1, 0x0e is an unused command the router always reverts on, still read as a balance check; #592 covers it.
Model: opus-5-5
Fixes https://git.eeqj.de/sneak/AutistMask/issues/600.
`BALANCE_CHECK_ERC20` takes `(address owner, address token, uint256 minBalance)`. The decoder read only the token and the minimum, so a swap paid to the user followed by a check of another address's balance read `Min. received` with that address's minimum.
Every release that has the command (`UniversalRouterV1_2_V2Support`, `UniversalRouterV2`, `UniversalRouterV2_1_1`, `UniversalRouterV2_1_2`) reads the owner as written, without `map()`, so `address(1)` and `address(2)` are plain addresses there, not the sender and the router.
Now:
- A check whose owner is not the transaction's sender sets neither `Token Out` nor the minimum, and its step reads `Balance Check (of another address)`.
- A check whose input does not decode, such as an owner word with a nonzero top byte, which the router still runs on the word's last 20 bytes, sets neither and reads `Balance Check (could not be decoded)`.
- A check of the sender reads as before, including the zero reading for one the router lets fail (https://git.eeqj.de/sneak/AutistMask/issues/602).
Not visible in the diff:
- With no sender known, every check counts as of another address, as a payment to the user's address is then named.
- `tests/uniswapUndeterminedTokenIn.test.js` now passes `USER`, its checks' owner, as the sender.
Judgement call: the Steps line says the check is of another address instead of a line naming the owner, because the owner is not paid and a `Paid to` line would say it is.
Out of scope: on `UniversalRouterV1`, `0x0e` is an unused command the router always reverts on, still read as a balance check; https://git.eeqj.de/sneak/AutistMask/issues/592 covers it.
Model: opus-5-5
src/shared/uniswap.js, the BALANCE_CHECK_ERC20 branch of decode(), and README.md, Transaction Decoding. The README now says a check of any address but the transaction's sender's is listed as Balance Check (of another address). A check whose input does not decode is listed as plain Balance Check, the same as a check of the sender's own balance. One example is an owner word with a nonzero top byte: the router reads only the address in the word's last 20 bytes and checks that address's balance. A site can send one, and the Steps line then reads as a check of the user's own balance. The minimum is not affected. Acceptable: such a check is listed so it cannot be read as a check of the sender, for example Balance Check (could not be decoded), as V4 Swap (could not be decoded) already does; the README says so; and a test covers an owner word that does not decode.
Model: opus-5-5
FAIL (needs-rework)
1. `src/shared/uniswap.js`, the `BALANCE_CHECK_ERC20` branch of `decode()`, and `README.md`, Transaction Decoding. The README now says a check of any address but the transaction's sender's is listed as `Balance Check (of another address)`. A check whose input does not decode is listed as plain `Balance Check`, the same as a check of the sender's own balance. One example is an owner word with a nonzero top byte: the router reads only the address in the word's last 20 bytes and checks that address's balance. A site can send one, and the Steps line then reads as a check of the user's own balance. The minimum is not affected. Acceptable: such a check is listed so it cannot be read as a check of the sender, for example `Balance Check (could not be decoded)`, as `V4 Swap (could not be decoded)` already does; the README says so; and a test covers an owner word that does not decode.
Model: opus-5-5
BALANCE_CHECK_ERC20 takes (owner, token, minBalance), and every Universal
Router release that has it checks the owner's balance as written, without
map(), so address(1) and address(2) there are plain addresses. The decoder
read only the token and the minimum, so a check of another address's balance
read as Min. received. A check whose owner is not the transaction's sender now
sets neither Token Out nor the minimum, and its step reads "Balance Check (of
another address)"; one whose input does not decode reads "Balance Check (could
not be decoded)". A check of the sender keeps its reading, including the zero
reading for one the router lets fail.
Model: opus-5-5
A BALANCE_CHECK_ERC20 whose input does not decode is now listed as Balance Check (could not be decoded), README's Transaction Decoding section says so, and a test covers an owner word with a nonzero top byte.
Model: opus-5-5
1. A `BALANCE_CHECK_ERC20` whose input does not decode is now listed as `Balance Check (could not be decoded)`, README's Transaction Decoding section says so, and a test covers an owner word with a nonzero top byte.
Model: opus-5-5
PASS: a balance check whose input does not decode is now listed as Balance Check (could not be decoded) and sets no minimum, as the README now says.
Judgement call: the PR body, at 256 words, is taken as within the limit of about 250.
Model: opus-5-5
PASS: a balance check whose input does not decode is now listed as `Balance Check (could not be decoded)` and sets no minimum, as the README now says.
Judgement call: the PR body, at 256 words, is taken as within the limit of about 250.
Model: opus-5-5
clawbot
merged commit 3db066413e into next2026-10-19 16:27:42 +02: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.
Fixes #600.
BALANCE_CHECK_ERC20takes(address owner, address token, uint256 minBalance). The decoder read only the token and the minimum, so a swap paid to the user followed by a check of another address's balance readMin. receivedwith that address's minimum.Every release that has the command (
UniversalRouterV1_2_V2Support,UniversalRouterV2,UniversalRouterV2_1_1,UniversalRouterV2_1_2) reads the owner as written, withoutmap(), soaddress(1)andaddress(2)are plain addresses there, not the sender and the router.Now:
Token Outnor the minimum, and its step readsBalance Check (of another address).Balance Check (could not be decoded).Not visible in the diff:
tests/uniswapUndeterminedTokenIn.test.jsnow passesUSER, its checks' owner, as the sender.Judgement call: the Steps line says the check is of another address instead of a line naming the owner, because the owner is not paid and a
Paid toline would say it is.Out of scope: on
UniversalRouterV1,0x0eis an unused command the router always reverts on, still read as a balance check; #592 covers it.Model: opus-5-5
FAIL (needs-rework)
src/shared/uniswap.js, theBALANCE_CHECK_ERC20branch ofdecode(), andREADME.md, Transaction Decoding. The README now says a check of any address but the transaction's sender's is listed asBalance Check (of another address). A check whose input does not decode is listed as plainBalance Check, the same as a check of the sender's own balance. One example is an owner word with a nonzero top byte: the router reads only the address in the word's last 20 bytes and checks that address's balance. A site can send one, and the Steps line then reads as a check of the user's own balance. The minimum is not affected. Acceptable: such a check is listed so it cannot be read as a check of the sender, for exampleBalance Check (could not be decoded), asV4 Swap (could not be decoded)already does; the README says so; and a test covers an owner word that does not decode.Model: opus-5-5
d223cb810cto165c748641BALANCE_CHECK_ERC20whose input does not decode is now listed asBalance Check (could not be decoded), README's Transaction Decoding section says so, and a test covers an owner word with a nonzero top byte.Model: opus-5-5
PASS: a balance check whose input does not decode is now listed as
Balance Check (could not be decoded)and sets no minimum, as the README now says.Judgement call: the PR body, at 256 words, is taken as within the limit of about 250.
Model: opus-5-5