Excavator Honeypot
What happened
De.Fi's REKT database lists Excavator (EXC, BNB Smart Chain contract 0x6a872788…d3562b) as an exit scam/honeypot, noting that the contract owner could disable the transfer function, which restricted users in selling their tokens. In the verified source, a modifier on _transfer records the recipient of the first transferFrom in a variable named nxOwner and from then on reverts any transfer to that address unless the sender is _owner or _leaveowner. If that first recipient is the liquidity pool, ordinary holders can receive tokens from it but cannot sell back to it.
renounceOwnership clears only _owner; the second privileged address _leaveowner is not cleared, so the exemption and the owner-only functions stay with the deployer address 0x590A634D…F704aa. No loss figure is given by De.Fi.
How it happened
- The
Ownableconstructor stores the deployer in two variables:_owner = msgSender;and_leaveowner = msgSender;. TheExcavatorconstructor assigns the whole supply to the deployer:_balances[msg.sender] = _totalSupply;. transfercalls_transfer(..., false)andtransferFromcalls_transfer(..., true). Both run the modifierPancakeSwabV2Interface(sender, recipient, fromTransfer).- The modifier:
if(from != address(0) && nxOwner == address(0) && fromTransfer) nxOwner = to; else require((to != nxOwner || from == _owner || from == _leaveowner), "Order TransferFromMiddleware");. WhilenxOwneris empty, the firsttransferFromis let through and its recipient is stored asnxOwner. Any address that receives that firsttransferFrom, such as a liquidity pool filled through a router, becomes the blocked recipient. - After that, every transfer whose recipient is
nxOwnerreverts unless the sender is_owneror_leaveowner. A holder's sell through a router is atransferFromfrom the holder to the pool, so it reverts. Buys, where the pool is the sender and the buyer is the recipient, pass theto != nxOwnertest. transferOwnership(address newOwner)does not transfer ownership; it only setsnxOwner = newOwner;. It is restricted byonlyOwner, which accepts_owneror_leaveowner. PointingnxOwnerat an unused address lifts the block, and setting it to the zero address makes the nexttransferFromcapture a new recipient.renounceOwnershiponly sets_owner = address(0);. The_leaveownervariable is untouched, so after renouncing,_leaveownerstill passesonlyOwnerand still bypasses the sell block.- The fee variables
_fee,_feeLiqand_feeHoldersare declared but_transfernever reads them; it debits the sender's balance and credits the recipient with the sameamount.
Protocol details
Evidence
- report Token Sniffer reply tweet 1390015526294810624 (via fxtwitter) twitter.com
- address BscScan verified source for 0x6a872788234b8b93be6cbd73e9dcc0b7f0d3562b bscscan.com
- analysis Sourcify match for 0x6a872788234b8b93be6cbd73e9dcc0b7f0d3562b repo.sourcify.dev
- analysis De.Fi REKT database listing for EXC (Exit Scam/Honeypot) de.fi
Build your security review skills
Work through hands-on labs covering real exploit mechanics, review techniques, and defensive patterns.