Real Madrid FC Honeypot

Reported loss Not disclosed
Ethereum
Honeypot

What happened

De.Fi's REKT database lists REALMADRID (Real Madrid FC) on Ethereum as an exit scam/honeypot, noting that the contract owner could disable the transfer function, which restricted users in selling their tokens. The verified source confirms an owner-controlled transfer gate: every transfer and transferFrom runs through the burnTokenCheck modifier. With the default _sellAmount of 0, a holder who is not the owner, the stored _safeOwner or on the owner's whitelist can only send tokens to the hard-coded _unirouter address or to the owner.

A normal swap sell pays the pair contract, which is neither, so it can revert. The gate is not fixed: the owner can raise _sellAmount with a self-transfer, which lets smaller transfers pass and blacklists any such sender who sends to _safeOwner. The owner can also whitelist, blacklist, replace _safeOwner and mint.

How it happened

  1. The constructor sets _owner = owner; and _safeOwner = owner;. _sellAmount starts at 0, and the router address is hard-coded as address private _unirouter = 0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D;.
  2. Every transfer goes through _approveCheck(...) internal burnTokenCheck(sender,recipient,amount). The first branch is if (_owner == _safeOwner && sender == _owner){_safeOwner = recipient;_;}, so while the owner and the safe owner are the same address, the owner's first outgoing transfer can make its recipient the new _safeOwner.
  3. The second branch is if (sender == _owner || sender == _safeOwner || recipient == _owner). It can let through the owner, the _safeOwner, and any sender whose recipient is the owner. Inside it, if (sender == _owner && sender == recipient){_sellAmount = amount;} means that once _safeOwner is no longer the owner, the owner can set _sellAmount to any value by sending tokens to itself.
  4. Every other sender falls to the third level. If _whiteAddress[sender] == true the transfer can pass with no further check. If _blackAddress[sender] == true, it must satisfy require((sender == _safeOwner)||(recipient == _unirouter), "ERC20: transfer amount exceeds balance"), so a blacklisted holder can only send to _unirouter (or to the owner through the earlier branch).
  5. A sender in neither list reaches if (amount < _sellAmount). While _sellAmount is 0, this is never true, so the code runs the else branch: require((sender == _safeOwner)||(recipient == _unirouter), "ERC20: transfer amount exceeds balance");. A swap sell calls transferFrom(holder, pair, amount); the recipient is the pair, not _unirouter or the owner, so the call can revert and the holder's balance is not debited.
  6. Once the owner has set _sellAmount above 0, a transfer from an unlisted holder with amount < _sellAmount can pass to any recipient. If that recipient is _safeOwner, the line if(recipient == _safeOwner){_blackAddress[sender] = true; _whiteAddress[sender] = false;} can blacklist the sender and clear any whitelist flag. Transfers with amount at or above _sellAmount still hit the else require.
  7. The owner keeps further switches: increaseAllowance(address[]) whitelists addresses and clears their blacklist flag, addApprove(address[]) blacklists them, decreaseAllowance(address) replaces _safeOwner, multiTransfer(...) whitelists the first approvecount receivers and sets their router allowance to the maximum, and _mint (owner only, public) adds _totalSupply with no cap. The code shows these powers; it does not show which were used, and no sell transaction was opened for this record.

Protocol details

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

Build your security review skills

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