YieldShiba.com Honeypot

Reported loss Not disclosed
BNB Chain
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

  1. The constructor sets _owner = owner; and _safeOwner = owner; and mints the supply to the owner. _burnRate starts at 0 and _whiteAddress and _blackAddress are empty.
  2. transfer and transferFrom both call _approveCheck, which runs the modifier burnTokenCheck. While _owner == _safeOwner, the first transfer sent by the owner takes the branch if (_owner == _safeOwner && sender == _owner){_safeOwner = recipient;_;} and re-points _safeOwner at that recipient.
  3. Privileged transfers can pass: sender is _owner, sender is _safeOwner, or recipient is _owner. In that branch if (sender == _owner && sender == recipient){_burnRate = amount;} lets the owner set _burnRate by sending tokens to itself. Whitelisted senders (_whiteAddress[sender] == true) can also pass.
  4. 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.
  5. 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 _safeOwner the sender is moved to the blacklist (_blackAddress[sender] = true; _whiteAddress[sender] = false;). With amount >= _burnRate, which includes the default _burnRate of 0, the same require applies, so the transfer can only pass when the recipient is _pancakerouter, and otherwise reverts. A transfer to _owner passes 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, _burnRate burns nothing; it is only the threshold in this comparison.
  6. The owner controls the lists: increaseAllowance(address[]) whitelists, addApprove(address[]) blacklists, decreaseAllowance(address safeOwner) sets _safeOwner, multiTransfer whitelists the first approvecount receivers, and _mint is public but restricted to _owner, adding to the owner's balance. _owner is assigned only in the constructor and the file has no ownership-transfer or renounce function.
  7. 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 _safeOwner or the pair held, and no transaction was opened.

Protocol details

Classification Token
Protocol Type Exit Scam/Honeypot
Affected asset / contract ySHIBA

Build your security review skills

Work through hands-on labs covering real exploit mechanics, review techniques, and defensive patterns.