DFX Finance Smart Contract Vulnerability Explained
DFX Finance Smart Contract Vulnerability Explained
Overview:
On 11th November 2022, a Re-entrancy attack occurred, which resulted in draining a total of ~$7.5M from DFX Finance’s Polygon liquidity pools. The attacker could only transfer $4.3 million worth of assets into their wallet. The remaining portion–about $3.2 million– was extracted by an MEV bot in a front-running transaction, also called a sandwich attack.
Smart Contract Hack Overview:
- Attacker’s address: 0x14c1
- DFX Finance Code: 0x8888
- MEV Bot Address & transaction: 0x6c6b
- MEV Bot’s wallet address: 0xfde
- Unconventional ordering transaction Block: 15941904
- MEV Bot & wallet transaction address analysis: 0xfde0d
GitHub code link:
- https://github.com/dfx-finance/protocol-v1-deprecated/blob/main/contracts/Curve.sol#L583
- https://github.com/dfx-finance/protocol-v2/blob/main/src/Curve.sol
Decoding the Smart Contract Vulnerability:

- The attacker first called the “
usdc-xidr” pair contract’sviewDeposit()function, which accepts lptoken as an input and returns an array of how manyusdc&xidrtokens are required. This function also mints enoughlptokens. - The attacker borrowed enough
USDCandXIDRby invoking the flash function of DFX because the same project included aflash()code for flash loans. Link to Code — https://github.com/dfx-finance/protocol-v2/blob/90e5ae656f64ecf13e13b03b1cb7fb1d79e09f5b/src/Curve.sol#L645

- The borrowed USDC and XIDR were then redeposited into the transaction pair contract by the assailants using the deposit () method. Link to the code — https://github.com/dfx-finance/protocol-v1-deprecated/blob/5fbeac837e57ded52e25572390a90c189ef363b1/contracts/Curve.sol#L489

- The deposit function called the function
ProportionalLiquidity.proportionalDeposit(), which registered the attacker’s LP token and deposited the attacker’s borrowed funds into the transaction pair contract. https://github.com/dfx-finance/protocol-v2/blob/90e5ae656f64ecf13e13b03b1cb7fb1d79e09f5b/src/Curve.sol#L659

- Because there was no outstanding amount at the attacker’s address, the transactions satisfied the validation when the transaction pair contract’s balance was checked, bypassing the necessity for transaction pair checks to pay back the flash loan. Link

- The
flashCallback()method, in this case, allowed the attacker to withdraw the whole contract’s reserves of USDC and XIDR tokens and run arbitrary logic with no upfront cost in order to complete the flash loan transaction. Because the total token borrowed from the flash loan had now become zero, the attacker’s deposited lptoken remained in the contract’s balance. - To finish the attack, the attacker executed the withdraw () function, destroyed the lptoken, and grabbed the
usdcandxidrtokens. https://github.com/dfx-finance/protocol-v1-deprecated/blob/5fbeac837e57ded52e25572390a90c189ef363b1/contracts/Curve.sol#L516

- The withdraw () function had a Re-entrancy protection modifier which could not be triggered since the flash loan was completed but the lptokens deposited by the attacker still existed in the lending contract, which actually belonged to the attacker, thus allowing an attacker to call the emergencyWithdraw() function any number of time until attacker withdraw all the deposited tokens.
- Due to the MEV bots being activated, the attacker lost a significant amount of money to the owner of those bots and was only able to recover about $4M in stolen money.
Mitigation best practices:
- The contract state should have a Boolean lock called a mutex (mutually exclusive flag). “Locked” is false in its initial state. But before the vulnerable function is called, it switches to true, and after it’s done, it returns to false.
- Use reentrancy-preventive function modifications, such as Open Zepplin’s Re-entrancy Guard.
- Always ensure that any state changes occur internally first, such as updating balances or calling internal functions before calling external code.
- Use the check-effect-interaction pattern.
- Scan your contract against the latest common security vulnerabilities with 130+ patterns at SolidityScan, which includes the detection of Re-entrancy vulnerabilities.

Conclusion:
SolidityScan is an advanced smart-contract scanning tool that discovers vulnerabilities and reduces risks in code. Request a security audit with us, and we will help you secure your smart contracts. Signup for a free trial at https://solidityscan.com/signup