Back to all stories
Blogs
Incident Analysis
XPEPE Token Incident Analysis
2/12/2025
XPEPE Token Incident Analysis

Incident Summary

On 25 January 2025, an attacker exploited a vulnerability in XPEPE’s TokenStaker contract which led to a 99% drop of the token price. The root cause was due to an un-revoked spend allowance when withdrawing staked tokens enabling the attacker to use the transferFrom() method to gain 100% extra tokens after each withdrawal from staking.

xpepe2new

Key Transactions

Exploit Transaction: https://etherscan.io/tx/0xbdec39a74e620fc624f90483aff067b17044f81138e6c30038daf7f873159db4

Attack Flow

Addresses

Attack wallet: 0x269ff4d056252A30CAd249a4CD75cb9Bcfb1F46c

Attack contract: 0x64dc84faa300B5f27c7eBaE8D867d039337e5999

Vulnerable contract: 0x444156f2440D4CD7Ab84b4D0679476c6BDc61423

Step by Step

  1. UniswapV3Pool.flash() → In order to maximise the amount of tokens gained the attacker used a flash loan to borrow all 49B XPEPE tokens available in the XPEPE 5 pool, which they then staked via TokenStaker contract 0x444156f2440D4CD7Ab84b4D0679476c6BDc61423.

xpepe3

  1. TokenStaker.withdrawAll() → Immediately after staking, the attacker called the withdrawAll() function to remove their staked tokens. The totalAmount of tokens to return was then approved and transferred.

xpepe4new

  1. After withdrawing, the attacker called the transferFrom() function of the XPEPE contract. As the approval from step 2 was still in place the attacker could transfer tokens directly from the TokenStaker contract.

xpepe5new

  1. The attacker repeatedly cycled through steps 2 to 4: staking their balance, withdrawing it, and then calling transferFrom() to gain an additional 100% each time. Once all available XPEPE tokens had been drained, they sold them for 0.6805 ETH ($2,109.10).

Vulnerability

In the withdrawAll() function, tokens were approved to a user which allows them to retrieve their stake and rewards. The approval should have then been revoked once the user has claimed their tokens. The contract did contain a _spendAllowance() function which is used to update a user’s spend allowance but it was only called during transferFrom() and not the withdrawAll() function.

xpepe6new

xpepe7new

Fund Flow

The attacker’s wallet, 0x269ff4d056252A30CAd249a4CD75cb9Bcfb1F46c, was funded on 4 January 2025 via Tornado Cash on the Binance Smart Chain (BSC), 0.2 ETH was later bridged to Ethereum via Orbiter Bridge on 22 January.

xpepe8

xpepe9

Analysis of 0x269 shows that is also linked to several incidents:

xpepe10

On 2 February 2025, the attacker transferred 12ETH to Tornado Cash.

xpepe11

Conclusion

In 2024, exploits related to code vulnerabilities accounted for a total loss of ~$173M with an average loss of $795,080 per incident, highlighting the risks of deploying unaudited code.

To keep up to date on the latest incident alerts and statistics follow @certikalert on X, or read our latest analysis on certik.com.