NeedForSpeed Finance Rug Pull

Reported loss $82K
Ethereum
Rugpull

What happened

NeedForSpeed.Finance (RFI-NFS, Ethereum contract 0x77b97372…eb44db) is a Reflect (RFI) fork that takes a 3% holder fee and a 3% burn on every transfer. Its transfer-blocking control is _setMaxTxAmount: the owner can set the per-transfer cap to any value, including zero, and the cap applies to every transfer where neither side is the owner. De.Fi's REKT database describes the token as a custom ERC20 with logic that allows blocking token transfers.

De.Fi's listing says the project ran a fundraising event through the Token Sale contract 0x21c76e2a…18d0b0, that the funds were sent to the contract deployer (transaction 0x4f71d08f…1f8d0a), that all 125 ETH was used to add initial liquidity (transactions 0x1286d6c6…2fc01a, 0xfbe58652…9c472e and 0x2f5a1600…14ea6f), and that the deployer then removed the liquidity (transactions 0x8ecb6bd2…09de99, 0x874091d6…d34124 and 0x2775cd7f…9cb262).

Etherscan's page for 0x874091... shows the deployer 0xD3f001a9…41a2bF removing liquidity through Uniswap V2 Router 2 on 2021-04-27 at 12:31:58 UTC and receiving about 30.48 ETH (about $82.8K at Etherscan's valuation), in line with the $82,091 loss. The pages for 0x8ecb... and 0x2775... show other activity: a removal of about 14.45 ETH on 2020-12-13 at 13:22 UTC, before this contract was deployed that day at 17:02 UTC, and a removal from a TFL/ETH pair on 2021-05-27.

On-chain owner() reads the zero address (2026-09-30), so ownership was renounced at some point; the source cannot show what the cap was set to before that.

How it happened

  1. The constructor gives the whole supply to the deployer: _rOwned[_msgSender()] = _rTotal;. The supply is _tTotal = 1 * 10**6 * 10**7 base units with 8 decimals, which is 100,000 tokens.
  2. A per-transfer cap starts at uint256 private _maxTxAmount = 2000e8; (2,000 tokens) and _transfer enforces it unless one side is the owner: if(sender != owner() && recipient != owner()) followed by require(amount <= _maxTxAmount, ...). _transfer also requires amount > 0.
  3. The cap has no lower bound. function _setMaxTxAmount(uint256 maxTxAmount) external onlyOwner() assigns _maxTxAmount = maxTxAmount;, while the fee setter next to it is bounded by require(taxFee >= 1 && taxFee <= 10, ...). With the cap at 0, every transfer between non-owner addresses reverts: a holder's sell through the router (transferFrom into the pair) and a buy out of the pair both fail, while transfers to or from the owner still pass.
  4. renounceOwnership() sets _owner = address(0);. After that owner() is the zero address, no transfer qualifies for the exemption and _setMaxTxAmount can no longer be called, so the last cap value stays for good. Renouncing does not undo a cap set earlier.
  5. What was reported: De.Fi's listing says the deployer removed the liquidity, and the opened Etherscan page for 0x874091... shows the deployer removing liquidity on 2021-04-27 for about 30.48 ETH. No opened transaction shows a call to _setMaxTxAmount, so the listing's transfer-blocking claim is matched to this code control but not traced to a transaction.

Protocol details

Classification Yield Aggregator
Protocol Type Exit Scam/Rugpull
Affected asset / contract RFI-NFS
Protocol links Website

Build your security review skills

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