# The Graph Rounding Error Bugfix Review

Two rounding errors in The Graph's Curation and L2Staking contracts let attackers dodge curation tax and bypass the unstaking thaw period, risking user funds.

- Payout: $290,497
- Severity: critical
- Program: The Graph
- Credited: GregadETH
- Disclosed: 2024-05-16
- Write-up quality: 7/10
- Original: https://immunefi.com/blog/bug-fix-reviews/the-graph-rounding-error-bugfix-review/
- Library page: https://bugbountylibrary.com/r/blog%3Aimmunefi-com-blog-bug-fix-reviews-the-graph-rounding-error-bugfix-review
- Tags: domain:web3 impact:funds-loss impact:integrity kind:bounty platform:blog platform:immunefi sev:critical tech:evm tech:solidity technique:source-review vuln:business-logic vuln:precision-loss

**Target:** Curation.sol / L2Curation.sol mint and L2Staking.sol unstake/lockTokens
**Root cause:** Integer division rounds down: curationTax = tokensIn*10000/1000000 truncates to 0 for tokensIn<100, and weightedAverage in lockTokens truncates so a tiny new unstake amount leaves the lock time unchanged.
**Steps:**
1. Call `Curation.mint(subgraphID, 99, 0)` repeatedly in batches of 99 GRT; curationTax computes to 0 each time, avoiding the 1% tax.
2. Burn the accumulated signal to recover tokens, netting the un-taxed amount.
3. For staking: call `L2Staking.unstake(smallAmount)` where smallAmount is tiny relative to currently locked tokens so weightedAverage rounds to the existing lockedUntil.
4. Repeat small unstakes to withdraw staked tokens without extending the thawing period.
**How found:** Researcher reviewed the tax and weighted-average math in Curation/L2Staking, noticed integer division truncation for small inputs, and wrote a PoC splitting mints into 99-GRT chunks to confirm zero tax.
**Exploitation:** On Arbitrum (cheap gas) the attacker loops mint() in 99-GRT batches to pay zero curation tax, then burns signal to reclaim GRT; separately, repeated tiny unstake() calls avoid extending the lock, letting tokens be withdrawn immediately without penalty.
**Escalation:** Batching on L2 makes the dust-amount rounding economically viable; multiple indexers could unstake entirely without penalty, degrading network security.
**Insight:** In staking/reward contracts, audit every division for truncation at small inputs and check whether an attacker can split an operation into dust-sized batches on a cheap L2 to make rounding losses free.
