ORAO Network Honeypot
What happened
ORAO Network (ORAO) is an Ethereum ERC-20 token whose transfers all pass through a burnTokenCheck modifier that treats senders differently. The deployer is the owner, the first address the owner sends tokens to becomes a privileged _safeOwner (on a DEX, typically the liquidity pair), and every other holder can only send tokens to one hard-coded _unirouter address, so a sell into the pair reverts with "ERC20: transfer amount exceeds balance". The owner can whitelist or blacklist holders, change _safeOwner, and set a _sellAmount threshold.
De.Fi's REKT database lists the token as an Exit Scam/Honeypot and describes it as a contract where the owner could disable the transfer function, which restricted users in selling their tokens.
How it happened
- The constructor sets
_owner = msg.sender;and_safeOwner = msg.sender;and mints198*1e6*(10**18)tokens (198,000,000 at 18 decimals) to the owner with_mint(_owner, ...). transferandtransferFromboth call_approveCheck, which is wrapped byburnTokenCheck(sender,recipient,amount). Its first branch isif (_owner == _safeOwner && sender == _owner){_safeOwner = recipient;_;}: while the owner and safe owner are the same address, the recipient of the owner's first outgoing transfer becomes_safeOwner. On a DEX that recipient would typically be the liquidity pair.- Next branch:
if (sender == _owner || sender == _safeOwner || recipient == _owner)lets the transfer pass with no restriction. That covers the owner, the_safeOwner(a pair pays out buyers through this path) and anyone sending to the owner. Inside it,if (sender == _owner && sender == recipient){_sellAmount = amount;}lets the owner set the_sellAmountthreshold by sending tokens to itself. - Every other sender falls to the remaining branches. If
_whiteAddress[sender]is true the transfer passes. If_blackAddress[sender]is true it must satisfyrequire((sender == _safeOwner)||(recipient == _unirouter), "ERC20: transfer amount exceeds balance");, and sincesender != _safeOwnerhere, the recipient must be_unirouter. A sell sends tokens to the pair, not to_unirouter, so it reverts. - An address on neither list reaches
if (amount < _sellAmount). With the defaultuint256 private _sellAmount = 0;this is never true, so theelsebranch runs the samerequireand the sell reverts. If the owner has set a threshold, a transfer below it passes and, whenrecipient == _safeOwner, the sender is added to_blackAddressby_blackAddress[sender] = true; _whiteAddress[sender] = false;; larger amounts revert. - The owner-only list functions carry misleading ERC-20 names:
increaseAllowance(address[] memory receivers)whitelists and un-blacklists,addApprove(address[] memory receivers)blacklists and un-whitelists, anddecreaseAllowance(address safeOwner)replaces_safeOwner.multiTransfersends tokens from the owner and whitelists and gives the router a maximum allowance for the firstapprovecountreceivers._mintispublicbut requiresmsg.sender == _owner, so the owner can add to its own balance and the total supply at any time. The contract has no function to renounce or transfer_owner. - What happened: De.Fi's REKT database lists this token as an Exit Scam/Honeypot dated 2021-09-13 with no loss figure. No opened transaction or holder page in this review shows a specific whitelist, blacklist,
_sellAmount,_mintor liquidity-removal call, or a failed sell.
Protocol details
Build your security review skills
Work through hands-on labs covering real exploit mechanics, review techniques, and defensive patterns.