- On 27–02–2020 we deployed a new unannounced pool on the Ethereum mainnet. As we were still auditing, we did not release it in any public forum.
- Before the events that occurred, the pool had the following balances;
- DAI 56,526
- USDC 136,583
- USDT 214,618
- BUSD 95,961
First let’s go through the code in question;
- Transfer curve tokens from user to contract
- Remove liquidity from swap contract with curve tokens
- Swap yDAI to yUSDC via swap contract (no slippage checks)
- Swap yUSDT to yUSDC via swap contract (no slippage checks)
- Swap yBUSD to yUSDC via swap contract (no slippage checks)
- Withdraw yUSDC to USDC
- Return USDC
This is the contract; https://etherscan.io/address/0xf1e2c9b9720535bbed4edded48ed92235914f62d#code
Now the rest can be a bit tricky to follow, so please use the following spreadsheet as a guideline.
Post mortem 29-02-2020
Event log 0x44e Hash,Contract,Call, yCurve.fi , bCurve.fi ,P&L,yDAI,yUSDC,yUSDT,yTUSD,yBUSD…
There are 3 interacting users;
0x44e ~ the at loss user
0x818 ~ at gain user
0x431 ~ a friend of the system user
0x44e with a series of deposits and withdrawals tries to move BUSD to USDC.
The first few trades happen with no issues. (lines 6 to 11). 0x44e is essentially swapping BUSD for USDC.
At this point, the net result of the USDC pool is;
136,583 (seeded) + 26,103 + 14,929 — 39,532 +39,532–14,611–131,338 + 11,134 = 42,800
At line 12, 0x44e suffers the first slippage event from 143,316 Curve.fi tokens to 41,310 (of the remaining 42,800 ~ this happens due to the 3 zap swaps in the zapOutV4 code linked above).
At line 13, 0x44e deposits into the pool again, since there is extremely high BUSD, 0x44e is penalized for their unequal deposit.
At line 14, 0x44e tries to withdraw again, the pool only has the 14,093 USDC they deposited so again they trade 258,703 Curve.fi tokens to 14,131 USDC.
They repeat this one final time at line 16, for a total net loss of 561,902
During this same time 0x818 is interacting with the pool, due to the pool imbalances they see the massive spike in APR, and deposit into the pool. They try to withdraw to DAI (line 25), but since the pool is heavily imbalanced the they also suffer loss at first of 43.04% (14,692 Curve.fi tokens to 6,456 DAI). However, they notice the massive imbalance of BUSD, and their next action they remove_liquidity_imbalance to BUSD (line 26) for a profit of 268,29%, removing 33,546 Curve.fi for 89,999 BUSD.
Their net gain at this point is 139,957
At the same time, we noticed the spike in slippage, and asked 0x431 to fix the trades for us; at the time, the pool had the following balance;
0x431 executes two trades, line 35 and line 36;
- 89,752 USDC to 465,242 BUSD
- 89,752 DAI to 134,444 USDT
Net gain 420,182
Including system trade fees rewarded to the LP’s of 1,762
Both 0x443 and 0x818 have made contact. The gain is settled with 0x44e and their net loss from the trades is -141,720
0x818 after attempts at discussion blocked us and has since deleted their social media, their net gain was 139,957.
The events above are based on user interaction and were not a flaw of either the Curve or iearn systems. Both functioned exactly as designed. What was at fault was the zap, that should have included slippage protection. The next release will be focused around forcing minimum slippage and revert in these cases. Currently have this scheduled after this investigation.