Skem.finance Honeypot

Reported loss Not disclosed
Ethereum
Honeypot

What happened

Skem.finance (SKEM) is an Ethereum token deployed on 4 May 2021 at 0x6c6291e6…cfedb7 by 0x164537C6…14D600, which is also its owner. Every transfer passes through a modifier, burnTokenCheck, that lets the owner, a second privileged address _safeOwner and owner-whitelisted wallets move tokens freely, but rejects an ordinary holder's transfer unless it is smaller than an owner-set _sellAmount, which starts at zero. The rejection reuses the message "ERC20: transfer amount exceeds balance", so a failed sale looks like a balance error.

If the owner's first outgoing transfer is the liquidity deposit, the Uniswap pair becomes _safeOwner and buys go through while sales revert. The owner can also whitelist, blacklist and mint to itself through functions named like standard allowance helpers. De.Fi's REKT database lists the token as an exit scam/honeypot.

How it happened

  1. The constructor sets _owner and _safeOwner to the owner argument and mints the supply to _owner. Because _mint requires msg.sender == _owner, the owner is the deploying address.
  2. burnTokenCheck begins with if (_owner == _safeOwner && sender == _owner){_safeOwner = recipient;_;}: the recipient of the owner's first outgoing transfer becomes _safeOwner. If that transfer is the Uniswap liquidity deposit, _safeOwner is the pair.
  3. Transfers pass unconditionally when sender == _owner || sender == _safeOwner || recipient == _owner, so with the pair as _safeOwner every buy (a transfer from the pair) succeeds.
  4. A sale is a transfer from the holder to the pair. For a holder who is not whitelisted, it passes only if amount < _sellAmount, and then if(recipient == _safeOwner){_blackAddress[sender] = true; ...} blacklists the seller. Otherwise require((sender == _safeOwner)||(recipient == _unirouter), "ERC20: transfer amount exceeds balance") reverts. _sellAmount starts at 0 and changes only when the owner transfers to itself, so by default no ordinary holder can sell or even send tokens to another wallet.
  5. The owner's levers are increaseAllowance(address[]) (whitelist), addApprove(address[]) (blacklist), decreaseAllowance(address) (set _safeOwner), multiTransfer (airdrop and whitelist the first approvecount receivers) and a public _mint that adds any amount to the owner's balance. _owner is set only in the constructor and there is no renounce function.

Protocol details

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

Build your security review skills

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