# DFX Finance Rounding Error Bugfix Review

Integer division in DFX AssimilatorV2 rounded EURS deposit amount to zero, letting an attacker mint LP tokens for free and drain the pool.

- Payout: $100,000
- Severity: critical
- Program: DFX Finance
- Credited: perseverance
- Disclosed: 2023-06-06
- Write-up quality: 8/10
- Original: https://immunefi.com/blog/bug-fix-reviews/dfx-finance-rounding-error-bugfix-review/
- Library page: https://bugbountylibrary.com/r/blog%3Aimmunefi-com-blog-bug-fix-reviews-dfx-finance-rounding-error-bugfix-review
- Tags: domain:web3 impact:funds-loss kind:bounty platform:blog platform:immunefi sev:critical tech:evm tech:solidity technique:source-review vuln:business-logic vuln:precision-loss

**Target:** AssimilatorV2 / Curve pool deposit on Polygon (EURS)
**Root cause:** In intakeNumeraireLPRatio, amount_ = (_amount.mulu(10**tokenDecimals) * 1e6) / _rate truncates to zero when _rate exceeds the numerator; no require(amount_ > 0) before safeTransferFrom, so zero tokens are pulled while LP tokens are still minted.
**Steps:**
1. Identify EURS on Polygon has only 2 decimals, making 10**tokenDecimals tiny and the division prone to truncation.
2. Call `curve_pool.deposit(deposit=18003307228925150, 0, 0, maxQuote, maxBase, deadline)` with a minuscule deposit so computed amount_ rounds to 0.
3. Loop the deposit ~10,000 times in one transaction; each iteration mints curve LP tokens without transferring EURS.
4. Call `curve_pool.withdraw(curvesToBurn, deadline)` to redeem inflated LP for a proportional share of EURS and USDC.
**How found:** Reviewer traced the deposit flow into AssimilatorV2.intakeNumeraireLPRatio and noticed the amount_ division could truncate to zero when _rate exceeds the numerator; non-standard 2-decimal EURS made the truncation economically exploitable.
**Exploitation:** Attacker needs only USDC approval (EURS approval unnecessary since amount_=0). Repeatedly depositing a tiny amount mints LP tokens for free; withdrawing them extracts ~172 EUR / ~190 USDC profit per attack, scalable to drain the $237k pool.
**Escalation:** Looping the deposit 10,000x within a single transaction amplifies per-call profit and progressively acquires a larger share of the pool.
**Insight:** When auditing AMM deposit/withdraw math, check tokens with unusually low decimals (2) where integer division truncation can zero out the transfer while shares are still minted; always verify a require(amount_ > 0) guards token pulls.
