The swap decoder, decode() in src/shared/uniswap.js: a PERMIT2_PERMIT or a PERMIT2_PERMIT_BATCH that grants an allowance to a spender other than the router.
What happens
Since #651 and #656 such an allowance is shown on its own lines. But code that a step of the same transaction runs (a V4 pool's hook, a token's own code) can call that spender, which can then take up to the allowance from the user's wallet before the transaction ends. The Amount figure and Min. received take no account of it, so they can read as all that leaves while more may.
What should happen
The approval screen never shows a figure for what leaves the wallet that may be too low: when a transaction grants an allowance to a spender other than the router, there is no Amount figure for that token (the allowance lines stay), and the minimum reads Min. paid out.
Severity: major
Definition of done
A permit or batch to a spender other than the router leaves no Amount figure for its token and no Min. received.
Tests for a permit and a batch to another spender, failing on next; Uniswap's own routes (allowances to the router) read as on next.
Model: opus-5-5
Seen by the review of https://git.eeqj.de/sneak/AutistMask/pulls/656.
## Where
The swap decoder, `decode()` in `src/shared/uniswap.js`: a `PERMIT2_PERMIT` or a `PERMIT2_PERMIT_BATCH` that grants an allowance to a spender other than the router.
## What happens
Since https://git.eeqj.de/sneak/AutistMask/pulls/651 and https://git.eeqj.de/sneak/AutistMask/pulls/656 such an allowance is shown on its own lines. But code that a step of the same transaction runs (a V4 pool's hook, a token's own code) can call that spender, which can then take up to the allowance from the user's wallet before the transaction ends. The `Amount` figure and `Min. received` take no account of it, so they can read as all that leaves while more may.
## What should happen
The approval screen never shows a figure for what leaves the wallet that may be too low: when a transaction grants an allowance to a spender other than the router, there is no `Amount` figure for that token (the allowance lines stay), and the minimum reads `Min. paid out`.
Severity: major
## Definition of done
- [ ] A permit or batch to a spender other than the router leaves no `Amount` figure for its token and no `Min. received`.
- [ ] Tests for a permit and a batch to another spender, failing on `next`; Uniswap's own routes (allowances to the router) read as on `next`.
Model: opus-5-5
clawbot
self-assigned this 2026-10-21 01:41:53 +02:00
Plan: one PR to next, in decode() in src/shared/uniswap.js. A PERMIT2_PERMIT or a batch entry granting an allowance to a spender other than the router marks its token: there is no Amount figure for that token (the existing line saying the amount could not be read stands in its place), and the minimum reads Min. paid out. The allowance lines stay. Allowances to the router are unchanged, so Uniswap's own routes read as on next. Tests for a permit and a batch to another spender, each failing on next.
Model: opus-5-5
Plan: one PR to `next`, in `decode()` in `src/shared/uniswap.js`. A `PERMIT2_PERMIT` or a batch entry granting an allowance to a spender other than the router marks its token: there is no `Amount` figure for that token (the existing line saying the amount could not be read stands in its place), and the minimum reads `Min. paid out`. The allowance lines stay. Allowances to the router are unchanged, so Uniswap's own routes read as on `next`. Tests for a permit and a batch to another spender, each failing on `next`.
Model: opus-5-5
Built in #666 as planned. One judgement call beyond the plan: a permit or batch the decoder cannot read may be to any spender, so it now also makes the minimum read Min. paid out.
Model: opus-5-5
Built in https://git.eeqj.de/sneak/AutistMask/pulls/666 as planned. One judgement call beyond the plan: a permit or batch the decoder cannot read may be to any spender, so it now also makes the minimum read `Min. paid out`.
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.
Seen by the review of #656.
Where
The swap decoder,
decode()insrc/shared/uniswap.js: aPERMIT2_PERMITor aPERMIT2_PERMIT_BATCHthat grants an allowance to a spender other than the router.What happens
Since #651 and #656 such an allowance is shown on its own lines. But code that a step of the same transaction runs (a V4 pool's hook, a token's own code) can call that spender, which can then take up to the allowance from the user's wallet before the transaction ends. The
Amountfigure andMin. receivedtake no account of it, so they can read as all that leaves while more may.What should happen
The approval screen never shows a figure for what leaves the wallet that may be too low: when a transaction grants an allowance to a spender other than the router, there is no
Amountfigure for that token (the allowance lines stay), and the minimum readsMin. paid out.Severity: major
Definition of done
Amountfigure for its token and noMin. received.next; Uniswap's own routes (allowances to the router) read as onnext.Model: opus-5-5
Plan: one PR to
next, indecode()insrc/shared/uniswap.js. APERMIT2_PERMITor a batch entry granting an allowance to a spender other than the router marks its token: there is noAmountfigure for that token (the existing line saying the amount could not be read stands in its place), and the minimum readsMin. paid out. The allowance lines stay. Allowances to the router are unchanged, so Uniswap's own routes read as onnext. Tests for a permit and a batch to another spender, each failing onnext.Model: opus-5-5
Built in #666 as planned. One judgement call beyond the plan: a permit or batch the decoder cannot read may be to any spender, so it now also makes the minimum read
Min. paid out.Model: opus-5-5