ElonCash Honeypot
What happened
ElonCash (ECS) is a BNB Smart Chain token whose burnTokenCheck modifier wraps every transfer and transferFrom. With its default state, a holder who has not been whitelisted can only send tokens to one hard-coded _unirouter address, so a sale into a liquidity pair is rejected. De.Fi's REKT database lists the token as an exit scam/honeypot and states that the owner could disable the transfer function, which restricted users in selling their tokens.
The code also lets the owner whitelist or blacklist addresses, redirect the privileged _safeOwner and mint to the owner.
How it happened
- The constructor stores the owner and sets the same address as the privileged account:
_owner = owner; _safeOwner = owner;._unirouteris hard-coded as0x05fF2B0DB69458A0750badebc4f9e13aDd608C7F, and_sellAmountstarts at0. - Both
transferandtransferFromcall_approveCheck, which is guarded byburnTokenCheck(sender,recipient,amount). The sender's balance is debited normally inside_approveCheck; the modifier only decides whether the call runs. - First branch:
if (_owner == _safeOwner && sender == _owner){_safeOwner = recipient;_;}. While_safeOwnerstill equals the owner, the first transfer from the owner makes its recipient the new_safeOwner. The source does not say who that recipient is. - Second branch:
if (sender == _owner || sender == _safeOwner || recipient == _owner)lets the call run. Anyone can therefore send tokens to_owner. A self-transfer by the owner also executes_sellAmount = amount;. - Any other sender: whitelisted addresses pass. A blacklisted sender passes only if
recipient == _unirouter, becausesender == _safeOwnerwas already handled above. An address on neither list passes ifamount < _sellAmount, otherwise only if(sender == _safeOwner)||(recipient == _unirouter). With_sellAmountat its initial0,amount < _sellAmountis never true. - A router-style sale calls
transferFrom(holder, pair, amount). For a non-whitelisted holder the recipient is the pair, not_unirouter, so it reverts withERC20: transfer amount exceeds balance, unless the holder is whitelisted or the amount is below a non-zero_sellAmount. Likewise a purchase pays out from the pair; it passes only if the pair is_safeOwneror whitelisted, which the source does not show. - Owner powers:
increaseAllowance(address[])whitelists and un-blacklists,addApprove(address[])blacklists and un-whitelists,decreaseAllowance(address safeOwner)sets_safeOwnerto any address,multiTransferairdrops and whitelists the firstapprovecountrecipients while granting_uniroutera maximum allowance, and_mint(address account, uint256 amount)is public but requiresmsg.sender == _ownerand addsamountto_balances[_owner]. The source has no function to change or renounce_owner. - Whether the owner used any of these functions is not shown by the source. De.Fi's REKT database lists the token as a honeypot dated 2021-05-18.
Protocol details
Build your security review skills
Work through hands-on labs covering real exploit mechanics, review techniques, and defensive patterns.