# Approved spender exceed nominal allowance by splitting aToken transfers into dust chunks

K2 aToken transfer_from charges nominal allowance but rounds scaled shares up, letting an approved spender drain more redeemable value than approved via dust transfers.

- Payout: Contest reward
- Severity: medium
- Program: K2
- Credited: johnyfwesh
- Disclosed: 2026-08-20
- Write-up quality: 6/10
- Original: https://code4rena.com/reports/2026-04-k2#m-42
- Library page: https://bugbountylibrary.com/r/c4%3A2026-04-k2%3AM-42
- Tags: domain:web3 impact:funds-loss kind:contest platform:code4rena sev:medium tech:solidity technique:source-review vuln:accounting-error vuln:business-logic

**Target:** Soroban aToken contract transfer_from/transfer_internal
**Root cause:** transfer_from decrements allowance by nominal amount while transfer_internal converts to scaled shares with ray_div_up ceiling division, so each dust call moves a full rounded-up share.
**Steps:**
1. Victim approves spender for N nominal aToken units.
2. Ensure liquidity_index > RAY (e.g. 2*RAY).
3. Spender calls `transfer_from(victim, attacker, 1)` N times.
4. Each call consumes 1 nominal allowance but credits ray_div_up(1, index)=1 scaled share.
5. Attacker redeems scaled shares worth ~2N nominal underlying.
**How found:** Code review noting allowance accounting uses nominal units while balance movement uses ceiling-rounded scaled shares, creating a unit mismatch exploitable when index > RAY.
**Exploitation:** Approved spender splits allowance into N one-unit transfer_from calls; each consumes minimal nominal allowance but credits a rounded-up scaled share, debited from victim's scaled balance, yielding more redeemable value than approved.
**Insight:** When allowance is tracked in nominal units but balances in scaled/index units, check rounding direction of the conversion: ceiling division on tiny amounts lets each call mint a full share while charging only dust allowance.
