GoalTimeN Finance Honeypot
What happened
De.Fi's REKT database lists GoalTimeN Finance (GTX) on Ethereum as an exit scam/honeypot and states that the contract owner could disable the transfer function, which restricted users in selling their tokens. In the verified source, every transfer and transferFrom runs ensure, which lets a transfer through only when the sender is the owner, the recipient is the owner, the sender is tradeAddress, or the sender is flagged in canSale. Every other sender falls through to condition, which returns false while _saleNum, _minSale and _maxSale are all zero, and the file contains no function that sets them.
As written, an ordinary holder can send tokens only to the owner address, so a sale into a liquidity pool reverts. Only the owner can exempt an address, through approveAndCall or transferownership. The code does not show whether or when the owner used those functions.
How it happened
- The constructor gives the deployer the whole supply and records it as the owner:
owner = msg.sender;andbalanceOf[msg.sender] = totalSupply;. transferforwards totransferFrom, andtransferFromcallsrequire(ensure(_from, _to, _value));before moving any balance.ensurereturns early only forif(_from == owner || _to == owner || _from == tradeAddress||canSale[_from]){ return true; }. Any other sender must passrequire(condition(_from, _value));.conditionstarts withif(_saleNum == 0 && _minSale == 0 && _maxSale == 0) return false;. These three variables areprivateand are never assigned anywhere in the file, so the check always fails for non-exempt senders. A holder who sells to a pool, directly or through a router, is the_fromaddress and reverts; the one destination that still works is the owner address.- Exemptions are owner-only:
approveAndCallsetscanSale[spender]=true, andtransferownership(which does not changeowner, despite its name) setstradeAddress = addr;. A transfer whose sender is a liquidity pool also hitsensure, so it passes only if the owner has exempted that address. approveAndCallalso writesbalanceOf[spender] = addedValue*(10**uint256(decimals));, which sets a balance directly without a transfer or a change tototalSupply.- The file has no function that changes or renounces
owner.
Protocol details
Build your security review skills
Work through hands-on labs covering real exploit mechanics, review techniques, and defensive patterns.