On July 30th between 13:10 and 22:00 UTC, a series of exploits resulted in loss of funds from several Curve pools. The source of the vulnerability in each case is a malfunctioning reentrancy lock in certain versions of Vyper.
Affected pools and amount extracted by each exploit:
Another pool potentially affected is Arbitrum’s Tricrypto pool. Auditors and Vyper devs could not find a profitable exploit, but Curve is advising LPs to exit that pool as a precaution.
On July 30th at 16:44 UTC, Vyper official Twitter acknowledged a bug affecting Vyper versions 0.2.15, 0.2.16, and 0.3.0. The compiler had a bug which negated the reentrancy protection. This bug was patched in version 0.3.1 (accidentally, as the bug remained unknown until July 30th). All contracts after 0.3.1 are in general without this bugged reentrancy guard.
Source: Twitter
The bug was introduced in this PR: #2391
The bug was patched in PRs: #2439 and #2514
Curve's contracts become vulnerable when making a raw_call to send native tokens. The affected Curve pools were each using one of the aforementioned Vyper versions and are paired with native ETH. Tokens using the ERC-777 standard have also been affected, although Curve pools involving these tokens have all largely been deprecated (e.g. pBTC and HOME). ERC-777 adds callbacks, making those pools susceptible to the same reentrancy issue. Pools paired with WETH have not been affected.
There appear to be multiple actors involved with the exploits and at least one is working with the Curve team to recover funds. 2,879.65 ETH (~$5.4m) extracted from the CRV/ETH pool by c0ffeebabe.eth has been returned to the Curve team.
The Arbitrum Tricrypto pool might be at risk of being exploited. While security researchers have not identified a profitable exploit, Curve is recommending users to exit this pool in an abundance of caution.
Source: Twitter
On July 30th at 13:10 UTC, an exploit occurred that drained pETH from the Curve pool. The attacker swapped pETH to WETH for a profit of 6,106.65 WETH (~$11m).
Source: Phalcon Explorer
The exploit logic was as follows:
The reentrancy occurred between the remove liquidity and add liquidity actions. A pool depositor should ordinarily be entitled to pool tokens equal to the product of the total pool token supply and the the fraction of the depositor’s supplied liquidity. However, due to the reentrancy bug, the allotted pool tokens were calculated with the pre-burn balances. This allowed the exploit to infinite mint pool tokens to create a fraudulent claim on the entire contents of the pool.
At time of writing, the funds are held in the JPEGd_69 Exploit wallet address.
The pETH/ETH Curve pool contained ~$21m TVL at the time of the incident, and all funds have since been drained or otherwise removed by users. While the emergency DAO is unable to take action to pause the pool or influence user funds in any way, it is able to freeze CRV gauge emissions to the pool. This action is expected shortly.
On July 30th at 14:50 UTC, an exploit occurred that drained msETH from the Curve pool. The attacker retained a profit of 866.55 ETH (~$1.6m) and 959.71 msETH (~$1.8).
Source: Phalcon Explorer
The exploit logic was as follows:
The reentrancy occurred between the remove liquidity and add liquidity actions. A pool depositor should ordinarily be entitled to pool tokens equal to the product of the total pool token supply and the the fraction of the depositor’s supplied liquidity. However, due to the reentrancy bug, the allotted pool tokens were calculated with the pre-burn balances. This allowed the exploit to infinite mint pool tokens to create a fraudulent claim on the entire contents of the pool.
At the time of writing, the c0ffeebabe.eth address appears to be a whitehat and is working with the Curve team to recover funds (as seen in on-chain messages here and here). The address was also involved with the CRV/ETH pool exploit described below and has returned proceeds from that. However, the address is still in possession of the msETH and ETH attained from the msETH/ETH pool exploit.
The msETH/ETH Curve pool contained ~$4.1m TVL at the time of the incident, and essentially all funds have since been drained or otherwise removed by users. While the emergency DAO is unable to take action to pause the pool or influence user funds in any way, it is able to freeze CRV gauge emissions to the pool. This action is expected shortly.
On July 30th at 15:34 UTC, an exploit occurred that drained alETH from the Curve pool. The attacker retained a profit of 7,258.70 ETH (~$13.6m) and 4,821.55 alETH (~9m).
Source: Phalcon Explorer
The exploit logic was as follows:
The reentrancy occurred between the remove liquidity and add liquidity actions. A pool depositor should ordinarily be entitled to pool tokens equal to the product of the total pool token supply and the the fraction of the depositor’s supplied liquidity. However, due to the reentrancy bug, the allotted pool tokens were calculated with the pre-burn balances. This allowed the exploit to infinite mint pool tokens to create a fraudulent claim on the entire contents of the pool.
At the time of writing, the funds are held in the alETH Exploit wallet address.
Prior to the exploit, Alchemix was able to withdraw 8,027.35 alETH from the pool (tx). As disclosed in this Twitter post, Alchemix was in the process to remove 5,000 ETH from its AMO when they were frontrun by the exploiter. This has resulted in a partial loss of backing for alETH.
The alETH/ETH Curve pool contained ~$46m TVL at the time of the incident, and essentially all funds have since been drained or otherwise removed by users. While the emergency DAO is unable to take action to pause the pool or influence user funds in any way, it is able to freeze CRV gauge emissions to the pool. This action is expected shortly.
There were 2 exploit transactions involved with the CRV/ETH pool (the second being a whitehat).
Exploit 1
On July 30th at 19:08 UTC, an exploit occurred that drained CRV and ETH from the Curve pool. The attacker retained 7,193,401.77 CRV (~$5.1m at time of exploit) and 7,680.49 WETH (~$14.2m) as profit.
Source: Phalcon Explorer
The exploit logic was as follows:
The reentrancy occurred between the remove liquidity and add liquidity actions. A pool depositor should ordinarily be entitled to pool tokens equal to the product of the total pool token supply and the the fraction of the depositor’s supplied liquidity. However, due to the reentrancy bug, the allotted pool tokens were calculated with the pre-burn balances. This allowed the exploit to infinite mint pool tokens to create a fraudulent claim on the entire contents of the pool.
This exploit is unique because an arbitrage exploit was also conducted in addition to the "reentrancy guard bug" exploit (which affected all four pools). The reason for this is that the CRV-ETH pool is the only non-stable pool exploited in this event.
At the time of writing, the funds have been transferred to a CRV/ETH Exploit wallet address.
Exploit 2
On July 30th at 22:00 UTC, a second exploit occurred that drained 2,879.65 ETH remaining in the pool. This was a whitehat action by c0ffeebabe.eth and the proceeds were returned to the Curve team shortly thereafter (tx).
Source: Phalcon Explorer
The exploit logic was as follows:
Following the first exploit, the pool had broken balances. It thought it contained a CRV balance, while in reality all CRV had been drained in the first hack. By depositing some CRV and calling claim_admin_fees
, the pool balance could be synced. The hacker donated CRV to the pool, synced balances, and then exchanged a few CRV for most of the ETH.
At the time of writing, the funds have been returned to the Curve Deployer address in this tx.
The CRV/ETH Curve pool contained ~$47m TVL at the time of the incident, and most funds have since been drained or removed by users. The pool still contains some ETH, which existing LPs can withdraw by calling remove_liquidity_one_coin
.
While the emergency DAO is unable to take action to pause the pool or handle user funds in any way, it is able to freeze CRV gauge emissions to the pool. This action is expected shortly.
Immediate next steps are to kill gauge emissions to the affected pools and create new plain pools for alETH, msETH, and pETH. New pools should be paired with WETH or the new ETH pool implementation. CRV already has a new Tricrypto pool paired with crvUSD and ETH that is not affected by the reentrancy bug.
The Curve team will continue to explore all avenues for the recovery of user funds and updates on the situation will be made on the social channels (Twitter, Telegram, and Discord).