On 21 July, 2023 the Conic Finance ETH Omnipool was exploited for 1724 ETH ($3.2 million) via a read-only reentrancy vulnerability. Despite having reentrancy guards in place, an incorrect assumption led to a reentrancy guard being bypassed. Conic paused the ETH Omnipool but a few hours later they lost a further $300,000 to MEV arbitrage in the crvUSD Omnipool.
Conic Finance operates Omnipools for the Curve Finance ecosystem and offer a platform for liquidity providers to diversify their exposure to multiple Curve pools. Users can provide liquidity into a Conic Omnipool which allocates funds across Curve in proportion to protocol controlled pool weights.
On 21 July, 2023 Conic Finance was exploited via a flash loan. An attacker flash loaned approximately $140 million which was used to manipulate Conic’s ETH Omnipool. Following the attack Conic confirmed the exploit was limited to the ETH pool and disabled deposits while they investigated.
Image: Conic Finance Twitter announcement Source: @ConicFinance
Conic Finance had also been exploited two weeks earlier on 4 July, 2023 when they lost $1,600 also via pool manipulation.
Image: Conic Finance flash loan exploit on 4 July. Source: Etherscan
Following the exploit the attacker sent the stolen funds to EOA 0x3d32. As of 27 July the wallet held a balance of 1727 ETH ($3,264,214). The attacker has been offered a white hat bounty of approximately 10%.
Image: Conic Finance attempt to negiotiate with the attacker. Source: Etherscan
The 24 hour deadline passed on 24 July and there still appears to have been no activity.
A few hours after the initial exploit, the Conic crvUSD Omnipool was also exploited due to an imbalance in the Curve pools caused by the initial exploit. MEV (Miner Extracted Value) bots took advantage of an arbitrage opportunity by conducting the following steps:
Swap crvUSD to USDC in the Curve pool
Deposit crvUSD into Conic
Swap USDC to crvUSD in the Curve pool
Withdraw the crvUSD from Conic
Repeat steps 1 to 4
Approximately $300,000 was taken from the crvUSD Omnipool. The MEV activity prompted Conic to pause all deposits to Omnipools to protect against any further loss. Conic finance reached out to the MEV operators and struck a deal with one of the MEV operators for a 10% bounty. The offer saw 81.30 ETH ($150K) returned to Conic Finance.
Image: A MEV owner returned 81.30 ETH to Conic Finance. Source: Etherscan
Summary of losses as of 27 July:
Total amount lost: Approximately $3.35 million.
Total amount returned: 91.30 ETH (Approximately $150K)
Contract Attacker: 0x743599ba5cfa3ce8c59691af5ef279aaafa2e4eb
ConicEthPool (Victim): 0xbb787d6243a8d450659e09ea6fd82f1c859691e9
The exploit is a result of read-only reentrancy despite Conic Finance having reentrancy guards in place.
“Our assumption was that Curve v2 pools using ETH have the ETH address (0xeee…eee) as one of their coins. However, they instead have the WETH address. This led to
_isETHreturning false, and in turn, to the reentrancy guard of the rETH pool being bypassed.” Source: Conic Finance Post Mortem
The attacker flash loaned assets worth approximately $134 million which included 20,000 stETH from AAVE as well as 20,550 rETH, 3000 CbETH and 28,504.2 WETH from Balancer.
The flash loaned funds were deposited via an ‘addLiquidity()’ call using the contract ‘vyper_contract'.
The attacker then called ‘remove_liquidity()' which burned the attacker’s LP tokens and transferred funds back to the attacker triggering a callback.
During the callback to the attacker they called ‘ConicEthPool.withdraw()’. As the remove_liquidity() function had not yet completed the ‘rETH-f.totalSupply()’ was incorrect. The attacker took advantage of this incorrect value to get more funds than was initially deposited.
Image: remove_liquidity function in the contract 'vyper_contract'. Source: Etherscan
The attacker transferred the funds to EOA 0x3d32c5a2e592c7b17e16bddc87eab75f33ae3010. As of writing the funds are still in the wallet.
This incident is the largest flash loan attack in July 2023 and the 7th largest we have recorded in 2023. With the EraLend exploit (link below) on 25 July it is also one of two read-only reentrancy exploits that occurred within the space of four days.
Understanding reentrancy is hugely important to secure smart contracts. Reentrancy can occur whenever a function calls another contract, as such an otherwise secure function can still lead to a contract being drained. Smart contracts should try to follow the process of Checks → Effects → Interactions in order to protect against reentrancy. Functions can be further protected by also using ReentrancyGuard which prevents a function from being re-entered.
What is a Reentrancy Attack? https://www.certik.com/resources/blog/3K7ZUAKpOr1GW75J2i0VHh-what-is-a-reentracy-attack
EraLend Incident Analysis https://www.certik.com/resources/blog/4NPEuNEiaUUcm6S3gdKKLP-eralend-incident-analysis