KURMA Honeypot

Reported loss Not disclosed
BNB Chain
Honeypot

What happened

De.Fi's REKT database lists KURMA on BNB Smart Chain as an exit scam/honeypot, noting that the contract owner could disable the transfer function and so restrict users from selling. In the verified source every transfer runs through a burnTokenCheck modifier. Unless the sender is whitelisted, a holder can send tokens only to the hard-coded router address or to the owner, so a sale into a liquidity pair reverts with the message "ERC20: transfer amount exceeds balance" even though the holder's balance is sufficient.

The owner controls the whitelist and blacklist and can change the _safeOwner address.

How it happened

  1. The constructor stores the deployer-supplied address as both owner and safe owner (_owner = owner; _safeOwner = owner;) and mints the initial supply to it. There is no transferOwnership or renounceOwnership function, so _owner cannot be changed.
  2. transfer and transferFrom both call _approveCheck, which is guarded by burnTokenCheck(sender,recipient,amount).
  3. While _owner == _safeOwner, the owner's first transfer takes the first branch: if (_owner == _safeOwner && sender == _owner){_safeOwner = recipient;_;}. After that, the recipient of that transfer is _safeOwner. Which address that was is not shown by the source.
  4. Privileged paths pass: if (sender == _owner || sender == _safeOwner || recipient == _owner) lets the owner, the safe owner, and anyone sending to the owner through. The owner can also set the threshold with a self-transfer: if (sender == _owner && sender == recipient){_sellAmount = amount;}.
  5. Any other sender who is in _whiteAddress passes. The owner fills the whitelist through multiTransfer (the first approvecount receivers are whitelisted and approved for _unirouter) and increaseAllowance(address[] receivers). addApprove(address[] receivers) does the reverse and sets _blackAddress.
  6. A blacklisted sender faces require((sender == _safeOwner)||(recipient == _unirouter), "ERC20: transfer amount exceeds balance");. Because the safe owner was already handled above, this reduces to recipient == _unirouter (0x05fF2B0D…608C7F).
  7. A sender that is neither whitelisted nor blacklisted: with _sellAmount at its initial 0, amount < _sellAmount is never true, so the final else runs the same require and only a transfer to _unirouter passes. A router swap sells by moving tokens from the holder to the pair, so the recipient is the pair and the call reverts. If the owner has set _sellAmount, smaller transfers pass, and one sent to _safeOwner also moves the sender to _blackAddress and removes them from _whiteAddress.
  8. The owner can also mint more: _mint is public, restricted to _owner, and always credits _balances[_owner] regardless of its account argument.
  9. What the code allows: the owner decides who can sell and can add supply. What happened: De.Fi's REKT database lists the token as an exit scam/honeypot; no transaction showing the owner calling these functions, and no pair address, was opened.

Protocol details

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

Build your security review skills

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