Auditore Honeypot

Reported loss Not disclosed
BNB Chain
Honeypot

What happened

De.Fi's REKT database lists Auditore (ADTR, BNB Smart Chain, contract 0x7fb90769…16e68e) as an Exit Scam/Honeypot dated 2021-05-22 and says the owner could disable transfers so holders could not sell. In the verified source, a modifier called BeforeTransfer stores the recipient of the first transferFrom call in a variable nxOwner and then rejects every later transfer to that address unless the sender is _owner. If nxOwner holds the liquidity pair address, router sells revert with "Order TransferFromMiddleware".

The owner, or a second privileged address, can overwrite nxOwner through a function named transferOwnership.

How it happened

  1. Two privileged addresses are set in the Ownable constructor: _owner = msgSender; and _leaveowner = msgSender;. The onlyOwner modifier accepts either: require((_owner == _msgSender() || _leaveowner == _msgSender()), ...).
  2. Every _transfer carries the modifier BeforeTransfer(sender, recipient, fromTransfer). transfer passes fromTransfer = false; transferFrom passes true.
  3. The modifier's first branch is if(from != address(0) && nxOwner == address(0) && fromTransfer) nxOwner = to;. The first transferFrom call, from any caller with an allowance, stores its recipient in nxOwner. A liquidity addition through a router is a transferFrom into the pair, so that recipient would be the pair; the code alone does not show which address was stored.
  4. Once nxOwner is set, every later transfer runs else require((to != nxOwner || from == _owner), "Order TransferFromMiddleware");. Only a transfer sent by _owner may go to nxOwner; other holders cannot. A router sell is transferFrom(holder, pair, amount), so if nxOwner is the pair, to == nxOwner and from is the holder, and the call reverts before _balances[sender] is debited. Buys, which move tokens out of the pair, are not affected by this check.
  5. The function that changes this address is misleadingly named: function transferOwnership(address newOwner) public onlyOwner { nxOwner = newOwner; } does not change _owner; it overwrites nxOwner. Setting it to address(0) re-arms the capture on the next transferFrom; pointing it at an unused address lifts the block.
  6. renounceOwnership() clears only _owner; _leaveowner keeps onlyOwner access, so transferOwnership stays callable. After a renounce, the from == _owner exemption can no longer apply to any real sender. At the 2026-09-30 read, owner and getOwner in meta.json were still the deployer address.
  7. Whether the owner called transferOwnership, and which address nxOwner held, is not shown without a transaction.

Protocol details

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

Build your security review skills

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