All incidents

Father Pepe Inu Unstake Drain

Share
May 29, 2023 15:20 UTCAttackLoss: 9,426,772.46 FAPENPending manual check1 exploit txWindow: Atomic
Estimated Impact
9,426,772.46 FAPEN
Label
Attack
Exploit Tx
1
Addresses
1
Attack Window
Atomic
May 29, 2023 15:20 UTC → May 29, 2023 15:20 UTC

Exploit Transactions

TX 1BSC
0xa2be65e439eb182e8f2acfe7eff9a4bab55eb3cd789dcc0ddd19bf811af78a93
May 29, 2023 15:20 UTCExplorer

Victim Addresses

0xf3f1abae8bfeca054b330c379794a7bf84988228BSC

Loss Breakdown

9,426,772.46FAPEN

Similar Incidents

Root Cause Analysis

Father Pepe Inu Unstake Drain

1. Incident Overview TL;DR

On BSC block 28637847, transaction 0xa2be65e439eb182e8f2acfe7eff9a4bab55eb3cd789dcc0ddd19bf811af78a93 let adversary EOA 0xa85783c652baf29a88c480522437ee4b9d3c1bb8 drain the FatherPepeInu token contract's internal fee bucket and immediately sell it through PancakeSwap. The attacker used helper contract 0x20a4b9a0d49ff14d16e29484f143975f293ad146, but the exploit path itself was fully permissionless and reproducible by any unprivileged caller.

The root cause is a broken authorization invariant in FatherPepeInu.unstake(uint256): the function only checks that balances[address(this)] is large enough, then credits balances[msg.sender] and debits the contract-held bucket. Because transfer fees are also routed into balances[address(this)], the contract accumulates a public pool of tokens that any caller can seize. The attacker realized 2042256597375684021 wei BNB gross and 2036738127375684021 wei BNB net after gas.

2. Key Background

FatherPepeInu (0xf3f1abae8bfeca054b330c379794a7bf84988228) is a fee-on-transfer token on BSC. Its verified source shows that buy and transfer fees are accumulated inside the token contract itself at balances[address(this)], which effectively creates a treasury-like token bucket.

Before the exploit, the BSC pre-state immediately before block 28637847 already satisfied every condition needed for an ACT realization:

  • FatherPepeInu.balanceOf(address(FatherPepeInu)) = 9521992386510669 raw FAPEN.
  • The future attacker-controlled helper held zero FAPEN.
  • The public FAPEN/WBNB Pancake pair at 0x1d1043d07b842c97a948e51c50470fdc7a02b9da held positive WBNB liquidity, so drained tokens could be monetized without any privileged counterparty.

The only protocol components needed for monetization were public Pancake contracts: PancakeRouter 0x10ed43c718714eb63d5aa57b78b54704e256024e, the FAPEN/WBNB pair, and WBNB 0xbb4cdb9cbd36b01bd1cbaebf2de08d9173bc095c.

3. Vulnerability Analysis & Root Cause Summary

This incident is an ATTACK, not a pure MEV rebalancing event. The vulnerability sits inside FatherPepeInu and is independent of attacker-specific infrastructure. The contract mixes two incompatible ideas: it collects protocol fees into the token contract's own balance, then exposes a public unstake(uint256) entrypoint with no owner check, no stake-share accounting, and no user-specific ledger. Once balances[address(this)] becomes positive, any caller can read the amount from public state and withdraw it into their own balance.

The violated invariant is straightforward: protocol-held tokens in balances[address(this)] must not become transferable to arbitrary callers unless the caller has a provable claim on that balance. FatherPepeInu does not enforce such a claim. The code-level breakpoint is the balance mutation inside unstake(uint256), where the contract credits balances[msg.sender] directly from the contract-held pool. Everything after that point, including approval and sale through PancakeRouter, is just monetization of already-stolen tokens.

4. Detailed Root Cause Analysis

The verified FatherPepeInu source on BscScan shows both the buildup of the fee bucket and the missing authorization on withdrawal:

function transferFrom(address sender, address recipient, uint256 amount)
    external
    override
    onlyValidAmount(amount)
    returns (bool)
{
    require(allowances[sender][msg.sender] >= amount, "Not enough allowance");

    uint256 fee = (amount * feeBuyer) / 100;
    uint256 amountAfterFee = amount - fee;

    _transfer(sender, recipient, amountAfterFee);
    _transfer(sender, address(this), fee);
    ...
}

function unstake(uint256 amount) external onlyValidAmount(amount) {
    require(balances[address(this)] >= amount, "Not enough staked balance to unstake");

    balances[msg.sender] += amount;
    balances[address(this)] -= amount;
}

This is the full exploit condition. transferFrom routes fees into the token contract's own balance, but unstake does not check owner, allowance, stakeShares, userStake[msg.sender], or any equivalent entitlement. There is no legitimate stake ledger anywhere in the withdrawal path. As a result, the token contract's fee bucket is effectively public inventory.

The collected execution trace for the exploit transaction shows the exploit unfolding exactly at that breakpoint:

FatherPepeInu::balanceOf(FatherPepeInu: [0xf3F1...8228]) [staticcall]
FatherPepeInu::unstake(9521992386510669)
FatherPepeInu::approve(PancakeRouter: [0x10ED...024E], 115792089237316195423570985008687907853269984665640564039457584007913129639935)
PancakeRouter::swapExactTokensForETHSupportingFeeOnTransferTokens(
  9521992386510669,
  0,
  [0xf3F1...8228, 0xbb4C...095c],
  0xA857...1BB8,
  1685373656
)
emit Transfer(from: 0x20a4...d146, to: PancakePair: [0x1d10...b9da], value: 9426772462645563)
emit Transfer(from: 0x20a4...d146, to: FatherPepeInu: [0xf3F1...8228], value: 95219923865106)
WBNB::withdraw(2042256597375684021)

That trace proves four critical facts:

  1. The attacker first read the contract-held fee bucket.
  2. The helper successfully called unstake for the entire bucket amount.
  3. The helper then sold the drained tokens through public Pancake liquidity.
  4. Only the configured transfer-fee residual, 95219923865106 raw FAPEN, returned to the token contract after the swap.

The balance-diff artifact independently confirms the profit predicate. EOA 0xa85783c652baf29a88c480522437ee4b9d3c1bb8 increased from 18354371469912239532 wei to 20391109597287923553 wei, a net gain of 2036738127375684021 wei after gas, while WBNB decreased by 2042256597375684021 wei on withdrawal.

5. Adversary Flow Analysis

  1. In deployment transaction 0x82d7dcc49209f789fb41c2f5652682b4391f288dcf09399bed7eca4ce1014dc5, EOA 0xa85783c652baf29a88c480522437ee4b9d3c1bb8 deployed helper contract 0x20a4b9a0d49ff14d16e29484f143975f293ad146.
  2. In exploit transaction 0xa2be65e439eb182e8f2acfe7eff9a4bab55eb3cd789dcc0ddd19bf811af78a93, the EOA called that helper.
  3. The helper queried balanceOf(address(FatherPepeInu)), learning the full drainable bucket of 9521992386510669 raw FAPEN.
  4. The helper called unstake(9521992386510669), which moved the entire token-contract balance into the helper's own balance.
  5. The helper approved PancakeRouter and sold the drained tokens through the public FAPEN/WBNB pool using swapExactTokensForETHSupportingFeeOnTransferTokens.
  6. Because FatherPepeInu is fee-on-transfer, the sale sent 9426772462645563 raw FAPEN into the pair and 95219923865106 raw FAPEN back to the token contract as the residual fee.
  7. PancakeRouter received 2042256597375684021 wei worth of WBNB, unwrapped it via WBNB.withdraw, and paid the native BNB proceeds to the attacker EOA.

The observed helper contract is incidental. The root strategy requires no privileged keys, no attacker-specific bytecode, and no private orderflow. Any clean EOA or freshly deployed helper could have repeated the same read, unstake, approve, and sell sequence from the same pre-state.

6. Impact & Losses

The protocol lost 9426772462645563 raw FAPEN, which is 9,426,772.462645563 FAPEN at 9 decimals. Only 95219923865106 raw FAPEN remained in the token contract after the swap because that amount was re-collected as the transfer fee on the sale itself.

The attacker monetized the drain into 2042256597375684021 wei BNB gross. With 5518470000000000 wei paid in gas, the attacker's observed native profit was 2036738127375684021 wei BNB net. The economic loss therefore originated from the FatherPepeInu fee bucket and was realized through public Pancake liquidity.

7. References

  • Exploit transaction on BSC: 0xa2be65e439eb182e8f2acfe7eff9a4bab55eb3cd789dcc0ddd19bf811af78a93
  • Helper deployment transaction on BSC: 0x82d7dcc49209f789fb41c2f5652682b4391f288dcf09399bed7eca4ce1014dc5
  • Victim contract: FatherPepeInu 0xf3f1abae8bfeca054b330c379794a7bf84988228
  • Monetization path: PancakeRouter 0x10ed43c718714eb63d5aa57b78b54704e256024e, FAPEN/WBNB pair 0x1d1043d07b842c97a948e51c50470fdc7a02b9da, WBNB 0xbb4cdb9cbd36b01bd1cbaebf2de08d9173bc095c
  • Source evidence: FatherPepeInu verified source on BscScan, especially transferFrom(address,address,uint256) and unstake(uint256)
  • Trace evidence: collected opcode-level trace for the exploit transaction under the validator-reviewed seed artifacts
  • Balance evidence: collected native balance delta artifact for the exploit transaction under the validator-reviewed seed artifacts