# SushiToken transfers are broken due to wrong delegates accounting on transfers

SushiToken._beforeTokenTransfer moves votes from `from` instead of `_delegates[from]`, causing underflow reverts that block delegated users from transferring tokens.

- Payout: Audit contest
- Severity: high
- Program: Sushi
- Found by: cmichel
- Disclosed: 2021-11-05
- Write-up quality: 6/10
- Original: https://github.com/code-423n4/2021-09-sushimiso-findings/issues/117
- Library page: https://bugbountylibrary.com/r/c4%3A2021-09-sushimiso%3AH-02
- Tags: area:web3 domain:web3 impact:dos kind:contest platform:code4rena sev:high tech:evm tech:solidity technique:source-review vuln:accounting-error vuln:dos vuln:governance

**Target:** SushiToken ERC20 governance token (_beforeTokenTransfer / _moveDelegates)
**Root cause:** The transfer hook calls `_moveDelegates(from, _delegates[to], amount)` instead of `_moveDelegates(_delegates[from], _delegates[to], amount)`, so it debits the sender's own (empty) checkpoint rather than their delegatee's.
**Steps:**
1. `mint(A, 1000)` → `_moveDelegates(0, delegates[A]=0)` writes no checkpoints
2. A delegates to A' → `_moveDelegates(0, A')` writes `writeCheckpoint(A', 1000)`
3. B delegates to B' → no checkpoint (B balance zero)
4. `transfer(A, B, 1000)` → `_moveDelegates(A, B')` subtracts 1000 from A's default-0 checkpoint → underflow revert
**How found:** Code-reading of the Compound-derived delegation logic: noticed the hook passes `from` rather than `_delegates[from]`, then traced checkpoint writes through mint/delegate/transfer to show the underflow.
**Insight:** When auditing forked governance tokens, diff the delegation hook against Compound's Comp.sol: the `_moveDelegates` args must be the delegatees, not the raw from/to addresses; trace checkpoint state across mint→delegate→transfer to expose underflows.

