Full Report
DFX Finance is a decentralized exchange for stablecoins. The exchange had flash loan functionality as well. A flash loan is where a large amount of money can be borrowed by a user, as long as the funds can be sent back with a fee. The flash loan functionality completely lacked reentrancy protection. A nice visual from Peckshield shows a call to the flash() function then the deposit() function without escaping it. To prevent the stealing of funds on the flash loan, the balance after the flash loan MUST be equal or exceed the original balance. Here's where the vulnerability lies: this checks the overall balance! An attacker can take out a flash loan then deposit the funds into their account! By doing this, the balance is the same and the attacker has tricked the contract into thinking they have a very large sum of money. A few interesting takeaways. First, reentrancy protection should be added everywhere, even when it seems unnecessary. In this case, the flash loan didn't have the reentrancy protection but the deposit did. However, the deed was done! Second, this was audited by Trail of Bits in V1 and the functionality for the flash loan was audited by PickAx for V1. But, the reentrancy bug was not caught in the V2 audit. Overall, interesting bug from different function calls to the contract. Another discussion can be found at Twitter and Halborn.
Analysis Summary
# Incident Report: DFX Finance Reentrancy Attack and MEV Front-Run
## Executive Summary
On November 11, 2022, DFX Finance suffered a significant loss of approximately \$7.5 million from its Polygon liquidity pools due to a reentrancy vulnerability within its flash loan functionality. The attacker exploited a missing reentrancy protection check in the **flash()** function, allowing them to incorrectly satisfy the flash loan repayment condition by depositing LP tokens before repaying the borrowed assets. A subsequent MEV bot transaction front-ran the final withdrawal, capturing an additional \$3.2 million of the drained funds.
## Incident Details
- Discovery Date: November 11, 2022 (Inferred from incident date)
- Incident Date: November 11, 2022
- Affected Organization: DFX Finance
- Sector: Decentralized Finance (DeFi) / Stablecoin Exchange
- Geography: Polygon Network
## Timeline of Events
### Initial Access
- **Date/Time:** November 11, 2022
- **Vector:** Exploitation of Smart Contract Vulnerability (Reentrancy)
- **Details:** The attacker initiated a transaction sequence targeting the `usdc-xidr` pair contract.
### Attack Progression (Exploitation)
1. **Query & Borrow:** Attacker calls `viewDeposit()` to calculate required tokens, then invokes the **`flash()`** function to take out a flash loan of USDC and XIDR.
2. **Malicious Deposit:** The attacker immediately calls the **`deposit()`** method using the borrowed funds. This action calls `ProportionalLiquidity.proportionalDeposit()`, which mints new LP tokens representing the borrowed assets and registers them to the attacker's address.
3. **Balance Check Bypass:** The contract checks the overall balance requirement for the flash loan return. Because the attacker deposited the borrowed assets, their wallet balance appeared sufficient or compliant, bypassing checks that should have failed before the funds were fully settled/repaid. The essential vulnerability was that the check focused on the *overall* balance, not the net change within the transaction scope relative to the loan.
4. **Reentrancy Execution:** The **`flashCallback()`** method allowed the attacker to execute arbitrary logic, effectively withdrawing the entire contract reserves of USDC and XIDR while only the minted LP tokens remained associated with the attacker's address (as the borrowed amount was zeroed out internally).
5. **Final Withdrawal:** The attacker executed the **`withdraw()`** function, burned the fraudulently acquired LP tokens, and extracted the full reserves of USDC and XIDR tokens.
### Lateral Movement (Within Contract)
- The attack relied on sequential function calls within the atomic transaction: **`viewDeposit()`** -> **`flash()`** -> **`deposit()`** -> **`flashCallback()`** -> **`withdraw()`**.
### Data Exfiltration/Impact
- **Total Drained:** Approximately **\$7.5 million** worth of assets (USDC and XIDR).
- **Attacker Wallet:** \$4.3 million was transferred directly to the attacker's wallet.
- **MEV Front-Run:** An additional \$3.2 million was extracted by an MEV bot in a "sandwich attack" transaction positioned just before the attacker's final withdrawal transaction in Block 15941904.
### Detection & Response
- **Detection:** Implied by public disclosure following the loss of funds on Nov 11, 2022.
- **Response Actions:** (Not explicitly detailed in the provided text, but containment in DeFi typically involves pausing interactions or patching the contract immediately.)
## Attack Methodology
- **Initial Access:** Exploitation of vulnerable logic within the `flash()` function, leading to a recursive call path.
- **Persistence:** Not applicable in this single-transaction exploit.
- **Privilege Escalation:** Not applicable; leveraged inherent contract capabilities.
- **Defense Evasion:** The contract logic failed to prevent the recursive deposit/withdrawal loop (`flash()` -> `deposit(LP minting)` -> `flashCallback()`), bypassing the implicit requirement that borrowed funds must be repaid *before* withdrawn assets are settled.
- **Credential Access:** Not applicable (blockchain exploit).
- **Discovery:** Attacker identified a lack of reentrancy protection specifically in the flash loan function, even though other parts of the system (like the deposit function) may have had some general protection.
- **Lateral Movement:** Achieved through sequential, nested function calls enabled by the reentrancy path.
- **Collection:** The function allowed withdrawal of the pool's entire liquidity reserves.
- **Exfiltration:** Executing the final `withdraw()` function after the reentrancy loop finalized the transaction state.
- **Impact:** Financial loss of liquidity pool assets.
## Impact Assessment
- **Financial:** Estimated \$7.5 million loss from liquidity pools. \$3.2 million of this was further lost to a front-running MEV bot.
- **Data Breach:** Not applicable (asset theft impacting fund custody).
- **Operational:** Disruption to DFX Finance liquidity pools on the Polygon network.
- **Reputational:** Significant negative impact due to the large-scale exploit despite previous audits.
## Indicators of Compromise
- **Attacker Address (Defanged):** `0x14c19962e4a899f29b3dd9ff52ebfb5e4cb9a067`
- **MEV Bot Address (Defanged):** `0x6c6b87d44d239b3750bf9badce26a9a0a3d2364e`
- **Block Number:** 15941904
- **Behavioral Indicators:** Sequential calls involving `flash()`, `deposit()`, and subsequent withdrawal functions that manipulate balances inconsistently across the transaction lifecycle.
## Response Actions
*(Information not explicitly provided in the source text for containment, eradication, or recovery.)*
## Lessons Learned
- **Universal Reentrancy Protection:** Reentrancy protection must be applied rigorously across all functions, especially those dealing with fund transfers, even if a function *seems* protected elsewhere in the call chain (the deposit function's protection was ineffective against the preceding flaw in the flash loan function).
- **Flash Loan Check Rigor:** The check to ensure the balance meets or exceeds the original borrowed amount must be strictly enforced and validated against the net state change attributable to the loan, rather than relying on overall balance checks that can be manipulated by intermediate actions (like gaining new LP tokens).
- **Audit Gaps:** The vulnerability was missed in the V2 audit (performed by PickAx, or the V2 functionality was not covered), highlighting that audits are not infallible and security assessment must continuously evolve with code changes.
## Recommendations
- Implement Checks-Effects-Interactions pattern systematically across all state-changing functions.
- Utilize Reentrancy Guards (e.g., OpenZeppelin ReentrancyGuard) everywhere possible, ensuring guards check for external calls *before* state changes that affect loan repayment validation.
- Perform dedicated security review cycles specifically focused on the interaction logic between flash loans and deposit/withdrawal mechanisms involving LP token minting/burning.