YieldShiba.com Honeypot
What happened
YieldShiba.com (ySHIBA, 18 decimals) on BNB Chain routes every transfer and transferFrom through a burnTokenCheck modifier that decides by sender, recipient and a stored threshold rather than by balance. A transfer can pass when the sender is the owner, the stored _safeOwner address or a whitelisted holder, when the recipient is _owner, when the recipient is the hard-coded _pancakerouter address, or when the amount is below _burnRate, a threshold the owner can set by sending tokens to itself. Any other transfer can revert with "BEP20: transfer amount exceeds balance" even though the balance is sufficient.
The owner can whitelist or blacklist holders and re-point _safeOwner. De.Fi's REKT database lists the token as an Exit Scam/Honeypot dated 2021-05-18 and says the contract owner could disable the transfer function, which restricted users in selling their tokens. No loss amount or transaction showing sells failing was verified.
How it happened
- The constructor sets
_owner = owner;and_safeOwner = owner;and mints the supply to the owner._burnRatestarts at 0 and_whiteAddressand_blackAddressare empty. transferandtransferFromboth call_approveCheck, which runs the modifierburnTokenCheck. While_owner == _safeOwner, the first transfer sent by the owner takes the branchif (_owner == _safeOwner && sender == _owner){_safeOwner = recipient;_;}and re-points_safeOwnerat that recipient.- Privileged transfers can pass: sender is
_owner, sender is_safeOwner, or recipient is_owner. In that branchif (sender == _owner && sender == recipient){_burnRate = amount;}lets the owner set_burnRateby sending tokens to itself. Whitelisted senders (_whiteAddress[sender] == true) can also pass. - A blacklisted sender can pass only if
require((sender == _safeOwner)||(recipient == _pancakerouter), "BEP20: transfer amount exceeds balance")holds, which for a non-privileged sender means the recipient is_pancakerouter. - A sender that is neither privileged, whitelisted nor blacklisted can pass in two ways. If
amount < _burnRate, the transfer goes through to any recipient, and if the recipient is_safeOwnerthe sender is moved to the blacklist (_blackAddress[sender] = true; _whiteAddress[sender] = false;). Withamount >= _burnRate, which includes the default_burnRateof 0, the samerequireapplies, so the transfer can only pass when the recipient is_pancakerouter, and otherwise reverts. A transfer to_ownerpasses in the privileged branch regardless of amount. The holder's balance is not the cause of a revert; the recipient and amount checks are. Despite its name,_burnRateburns nothing; it is only the threshold in this comparison. - The owner controls the lists:
increaseAllowance(address[])whitelists,addApprove(address[])blacklists,decreaseAllowance(address safeOwner)sets_safeOwner,multiTransferwhitelists the firstapprovecountreceivers, and_mintis public but restricted to_owner, adding to the owner's balance._owneris assigned only in the constructor and the file has no ownership-transfer or renounce function. - What happened is limited to what De.Fi's REKT database lists: an Exit Scam/Honeypot on 2021-05-18. The code does not show which address
_safeOwneror the pair held, and no transaction was opened.
Protocol details
Build your security review skills
Work through hands-on labs covering real exploit mechanics, review techniques, and defensive patterns.