Auditore 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
- Two privileged addresses are set in the
Ownableconstructor:_owner = msgSender;and_leaveowner = msgSender;. TheonlyOwnermodifier accepts either:require((_owner == _msgSender() || _leaveowner == _msgSender()), ...). - Every
_transfercarries the modifierBeforeTransfer(sender, recipient, fromTransfer).transferpassesfromTransfer = false;transferFrompassestrue. - The modifier's first branch is
if(from != address(0) && nxOwner == address(0) && fromTransfer) nxOwner = to;. The firsttransferFromcall, from any caller with an allowance, stores its recipient innxOwner. A liquidity addition through a router is atransferFrominto the pair, so that recipient would be the pair; the code alone does not show which address was stored. - Once
nxOwneris set, every later transfer runselse require((to != nxOwner || from == _owner), "Order TransferFromMiddleware");. Only a transfer sent by_ownermay go tonxOwner; other holders cannot. A router sell istransferFrom(holder, pair, amount), so ifnxOwneris the pair,to == nxOwnerandfromis 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. - The function that changes this address is misleadingly named:
function transferOwnership(address newOwner) public onlyOwner { nxOwner = newOwner; }does not change_owner; it overwritesnxOwner. Setting it toaddress(0)re-arms the capture on the nexttransferFrom; pointing it at an unused address lifts the block. renounceOwnership()clears only_owner;_leaveownerkeepsonlyOwneraccess, sotransferOwnershipstays callable. After a renounce, thefrom == _ownerexemption can no longer apply to any real sender. At the 2026-09-30 read,ownerandgetOwnerin meta.json were still the deployer address.- Whether the owner called
transferOwnership, and which addressnxOwnerheld, is not shown without a transaction.
Protocol details
Evidence
Build your security review skills
Work through hands-on labs covering real exploit mechanics, review techniques, and defensive patterns.