Foxography Honeypot

Reported loss Not disclosed
BNB Chain
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

  1. 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. swapAndLiquifyEnabled starts as false.
  2. transferFrom carries contextHandler(from, to), which runs if(from != owner) { if(swapAndLiquifyEnabled){ require(from == owner, "Order ContextHandler"); } else { require(balances[from] < _maxTrxLimit , "Order ContextHandler"); } }. The owner is exempt. The to argument is never used.
  3. 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 use transferFrom, while smaller holders can.
  4. The owner can tighten this at any time. setSwapAndLiquifyEnabled(bool) is owner-only; when set to true, require(from == owner, ...) makes every transferFrom from a non-owner address revert. setMaxTrxLimit(uint256 _input) is also owner-only, and a limit of 0 makes balances[from] < _maxTrxLimit false for every holder. A router sale is a transferFrom from the holder, so it reverts under either setting.
  5. transfer has no guard, so buys, where the pair sends tokens with transfer, and wallet-to-wallet sends are not blocked by this modifier.
  6. burnTokens(uint256 _input) onlyOwner runs balances[msg.sender] = balances[msg.sender] + (_input); and emits a Transfer from the zero address, without changing _totalSupply; despite its name it adds to the caller's balance. Because the owner is exempt from contextHandler, the code lets such tokens be sold through the router.
  7. renounceOwnership(address _newOwner) onlyOwner only writes currentOwner, which is never read, so it does not give up ownership. nxOwner is declared and accepted by onlyOwner but is never assigned, so it stays the zero address.

Protocol details

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

Build your security review skills

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