PotionBrew.net Honeypot
What happened
De.Fi's REKT database lists PotionBrew.net (POTION) on BNB Smart Chain as an Exit Scam/Honeypot, noting that the contract owner could disable the transfer function and so stop users selling. In the verified source at 0xd0fc4120…fe4f3a, transfer has no restriction, but transferFrom (the call an approved spender makes to pull tokens from a holder) requires allow[_from] == true. Only the deployer is allow-listed in the constructor, and only the address hard-coded in the onlyOwner modifier can add others with addAllow.
That same address can also overwrite any address's balance with mint. The code shows how pull-based sales can be blocked; no transaction showing a blocked sale was opened for this record.
How it happened
- The constructor gives the whole supply to the deployer and allow-lists only the deployer:
balances[msg.sender] = totalSupply; allow[msg.sender] = true;. transferchecks only the balance (require(balances[msg.sender] >= _value);), so moving tokens directly from a wallet is not restricted.transferFromadds a gate on the holder whose tokens are pulled:require(allow[_from] == true);. A holder who is not inallowcannot have tokens moved by an approved spender, so the call reverts even with a sufficient balance and allowance. Nothing adds receiving addresses toallowautomatically.addAllow(address holder, bool allowApprove) external onlyOwnersetsallow[holder] = allowApprove;, so it can allow or un-allow any holder. TheonlyOwnermodifier isrequire(msg.sender == address(1080614020421183795110940285280029773222128095634)), which is the address 0xbd486897…439192. It does not read theownervariable, and this address differs from the deployer 0x69feBA4a…003A31 shown in the deployment record.mint(address miner, uint256 _value) external onlyOwnerrunsbalances[miner] = _value;. That overwrites the balance (it does not add to it) and leavestotalSupplyunchanged, so the hard-coded address can set any holder's balance to any value, including zero.transferOwnershipis also behind the sameonlyOwnercheck but only changes theownervariable, which no permission check reads, so it does not move these powers to a new address. No function renounces them. Whether the hard-coded address usedaddAllowormintis not shown by the code.
Protocol details
Build your security review skills
Work through hands-on labs covering real exploit mechanics, review techniques, and defensive patterns.