Foxography Honeypot
What happened
Foxography (FOXO, BNB Chain, contract 0x56e1ea00…90f0c3) guards transferFrom with a contextHandler modifier that lets the owner through and applies one of two tests to everyone else. By default it requires the sender's whole balance to be below an owner-adjustable limit, _maxTrxLimit; after the owner calls setSwapAndLiquifyEnabled(true), or sets the limit to 0, it rejects every non-owner sender. Router swaps pull tokens with transferFrom, so they are the path affected, while plain transfer has no guard.
De.Fi's REKT database lists the token as an Exit Scam/Honeypot dated 2021-06-15 and says the owner could disable the transfer function, which restricted users in selling their tokens; the listing gives no loss amount.
How it happened
- The constructor gives the deployer the supply,
_totalSupply = 100000000 * 10**15;with 9 decimals, and sets_maxTrxLimit = 10000000 * 10**15;, one tenth of the supply.swapAndLiquifyEnabledstarts asfalse. transferFromcarriescontextHandler(from, to), which runsif(from != owner) { if(swapAndLiquifyEnabled){ require(from == owner, "Order ContextHandler"); } else { require(balances[from] < _maxTrxLimit , "Order ContextHandler"); } }. The owner is exempt. Thetoargument is never used.- In the default state the test is on the sender's entire balance, not the amount being moved. A holder whose balance is at or above
_maxTrxLimit(<is strict) cannot usetransferFrom, while smaller holders can. - The owner can tighten this at any time.
setSwapAndLiquifyEnabled(bool)is owner-only; when set to true,require(from == owner, ...)makes everytransferFromfrom a non-owner address revert.setMaxTrxLimit(uint256 _input)is also owner-only, and a limit of 0 makesbalances[from] < _maxTrxLimitfalse for every holder. A router sale is atransferFromfrom the holder, so it reverts under either setting. transferhas no guard, so buys, where the pair sends tokens withtransfer, and wallet-to-wallet sends are not blocked by this modifier.burnTokens(uint256 _input) onlyOwnerrunsbalances[msg.sender] = balances[msg.sender] + (_input);and emits aTransferfrom the zero address, without changing_totalSupply; despite its name it adds to the caller's balance. Because the owner is exempt fromcontextHandler, the code lets such tokens be sold through the router.renounceOwnership(address _newOwner) onlyOwneronly writescurrentOwner, which is never read, so it does not give up ownership.nxOwneris declared and accepted byonlyOwnerbut is never assigned, so it stays the zero address.
Protocol details
Build your security review skills
Work through hands-on labs covering real exploit mechanics, review techniques, and defensive patterns.