Yearn-V3 Honeypot
What happened
This record covers a token named "Yearn-V3" (YV3) deployed on Ethereum on 7 June 2021 at 0x9a3098aa…6b3641 by 0x377A8FBF…1379Ab; it borrows the Yearn name but is not a Yearn Finance token. Its transfer and transferFrom run through a modifier, burnTokenCheck, that lets the owner and one owner-chosen address move tokens freely but makes ordinary holders' transfers revert with a fake "transfer amount exceeds balance" error unless the recipient is the Uniswap V2 router itself. A Uniswap sale sends tokens to the pair, not the router, so holders who are not whitelisted cannot sell.
Owner-only functions disguised with ERC-20 names (increaseAllowance, addApprove, decreaseAllowance) edit a whitelist, a blacklist and the privileged address, and a public owner-only _mint can create new tokens at any time. De.Fi's REKT database lists the token as a honeypot; no loss figure is recorded.
How it happened
- The constructor calls
_mint50 times. Each call credits the new tokens to_owner(_balances[_owner] = _balances[_owner].add(amount);) but emits aTransferevent naming 0x7A1057E6…fC4c67 or 0x2D407dDb…47d45C, so explorers show mints to addresses that never received the balance. - The owner's first outgoing transfer sets
_safeOwnerto its recipient. After that, transfers from_owneror_safeOwner, or to_owner, always pass. - For any other sender,
burnTokenCheckpasses the transfer only if the sender is whitelisted, or if the amount is below_sellAmount._sellAmountstarts at 0 and only the owner can raise it, by sending tokens to itself. - Every other transfer hits
require((sender == _safeOwner)||(recipient == _unirouter), "ERC20: transfer amount exceeds balance"). A sale through the Uniswap V2 router moves tokens from the seller to the pair, so it reverts with a misleading balance error. - If the owner does raise
_sellAmount, a small sale to_safeOwnergoes through once and then blacklists the seller:if(recipient == _safeOwner){_blackAddress[sender] = true; ...}. - The owner can whitelist addresses with
increaseAllowance(address[]), blacklist them withaddApprove(address[]), replace_safeOwnerwithdecreaseAllowance(address), and airdrop throughmultiTransfer, which also whitelists recipients and approves the router to spend their tokens. The contract has no function to renounce or transfer_owner.
Protocol details
Evidence
Build your security review skills
Work through hands-on labs covering real exploit mechanics, review techniques, and defensive patterns.