LV Finance Rug Pull
What happened
LV Finance was a September 2020 Ethereum yield farm: stakers deposited USDC, USDT, SUSHI, UNI, LINK and other tokens into twelve pool contracts to earn the LV token at 0xa77f34bd…5aab22. The pools' addReward function, callable only by the rewardDistribution address the owner sets, hid a backdoor: any reward value of 3 or less skips the reward logic and runs _migrate, which either flips a flag that blocks every withdraw or sends the pool's entire balance to the caller through a helper named upgrade that is really an ERC-20 transfer. On 19 September 2020 0xb19dE844…6DF6e6 called addReward(2) on the USDC pool and received 201,585.64 USDC in that single transaction.
The existing record says the same call was made on each pool, taking in total 201.5K USDC, 79.6K USDT, 8.1 LEND, 2.7K SUSHI, 816 UNI, 1K LINK, 1.3 SNX, 261 YFV, 0.02 YFI, 82.1 PYLON and 0.76 YFII, which were exchanged for ETH.
How it happened
- Each pool holds one deposit token in
_token(theUSDTPoolcopy hard-codes USDT).stakepulls tokens in, andwithdrawpays them back only whilerequire(_upgrade < 1,"contract migrated")holds. - The pool owner sets
rewardDistributionwithsetRewardDistribution, andaddRewardcarries theonlyRewardDistributionmodifier, so only that address can call it. addReward(uint256 reward)treats a value aboveMIN_REWARD = 3as a normal reward top-up. Any value of 3 or less falls toelse{super._migrate(reward);}._migrate(1)toggles_upgrade, which makes every staker'swithdrawrevert with "contract migrated". Any other value runs_token.upgrade(msg.sender, _token.balanceOf(address(this))), and theSafeERC20.upgradehelper encodestoken.transfer.selector, so the pool's whole balance goes to the caller.- What happened: in transaction 0xa5b92bb9…f03325 (19 September 2020, 14:53:08 UTC), 0xb19dE844…6DF6e6 called
addReward(2)on the USDC pool 0x9e1d0964…75deb7 and received 201,585.6402 USDC. - The existing record lists the twelve pools as 0x80c09d3c…59a494, 0x9e1d0964…75deb7, 0x7b63771f…c39f80, 0xa2a430ce…d6f27d, 0xb7b3ab63…dd2f3e, 0x828995b4…5f7a27, 0x5a529c3a…72bc6c, 0xd76e4470…02f7f1, 0xbca5fc48…89ca06, 0xc3dc2d24…7b903f, 0xe52dfd3d…2a3e14 and 0x478e26cb…d28c02, all drained the same way.
Protocol details
Evidence
- report Sourcify sources for USDTPool 0x80c09d3cc108fa52b7b63cdcc071daebc059a494 sourcify.dev
- transaction Etherscan transaction 0xa5b92bb9...3325 (addReward on the USDC pool) etherscan.io
- address Lv.Finance (LV) token verified contract code on Etherscan etherscan.io
- address USDTPool verified contract code on Etherscan etherscan.io
- address etherscan.io address 0x478e…code etherscan.io
- address etherscan.io address 0x5a52…code etherscan.io
- address etherscan.io address 0x7b63…code etherscan.io
- address etherscan.io address 0x8289…code etherscan.io
- address etherscan.io address 0x9e1d…code etherscan.io
- address etherscan.io address 0xa2a4…code etherscan.io
- address etherscan.io address 0xb7b3…code etherscan.io
- address etherscan.io address 0xbca5…code etherscan.io
- address etherscan.io address 0xc3dc…code etherscan.io
- address etherscan.io address 0xd76e…code etherscan.io
- address etherscan.io address 0xe52d…code etherscan.io
- analysis DeFiYield announcement channel post 69 (seed link) t.me
- analysis Sourcify match for 0xa77f34bde382522cd3fb3096c480d15e525aab22 on Ethereum repo.sourcify.dev
Build your security review skills
Work through hands-on labs covering real exploit mechanics, review techniques, and defensive patterns.