Refinable Honeypot
What happened
De.Fi's REKT database lists Refinable (FINE), an Ethereum token at 0x58eadb9b…6fd9cf, as an Exit Scam/Honeypot dated 2021-04-22 and says the contract owner could disable the transfer function, which restricted users in selling their tokens. The verified source shows how: every transfer and transferFrom runs through a burnTokenCheck modifier that lets the owner, a changeable _safeOwner address and owner-whitelisted addresses move tokens freely, while any other holder can only send tokens to the hard-coded _unirouter address or to the owner. Anything else reverts with the message ERC20: transfer amount exceeds balance, so a sale into a pool address outside those exceptions fails and the holder's balance is not debited.
The code allows this; the source alone does not show which addresses the owner whitelisted or blacklisted, or what any holder lost, and De.Fi gives no loss figure.
How it happened
- The constructor sets
_owner = owner; _safeOwner = owner;, so the deployer address is both owner and the privileged_safeOwner. - Every
transferandtransferFromcalls_approveCheck, which carries theburnTokenCheckmodifier. While_owner == _safeOwner, the first transfer whose sender is the owner passes and runs_safeOwner = recipient, moving the privileged slot to whatever address received it. - After that, a transfer passes if
sender == _owner || sender == _safeOwner || recipient == _owner, or if the sender is in_whiteAddress. - Every other sender hits
if (amount < _sellAmount){ ... }else{require((sender == _safeOwner)||(recipient == _unirouter), "ERC20: transfer amount exceeds balance");_;}._sellAmountstarts at0and is private, soamount < _sellAmountis false until the owner sets it, and such a sender can only send to_unirouteror to the owner. A transfer to any other address, including a pool, reverts and the balance is untouched. - The owner can reshape this at will with owner-only functions whose names do not describe them:
increaseAllowance(address[] receivers)sets_whiteAddress[receivers[i]] = true,addApprove(address[] receivers)sets_blackAddress[receivers[i]] = true,decreaseAllowance(address safeOwner)sets_safeOwner = safeOwner, and a transfer from the owner to itself runs_sellAmount = amount. Blacklisted senders face the same_unirouter-only rule. - The file defines no function that changes
_owneror renounces ownership, and the owner-only_mint(address account, uint256 amount)can raise_totalSupplyand credit_balances[_owner]. The source alone does not show that any of these powers was used.
Protocol details
Build your security review skills
Work through hands-on labs covering real exploit mechanics, review techniques, and defensive patterns.