H2O Hack Analysis

lunaray
4 min readMar 18, 2025

Background introduction

On March 14, 2025, we detected an attack on the BNB Smart Chain project H2O. The attack hash is:

https://bscscan.com/tx/0x729c502a7dfd5332a9bdbcacec97137899ecc82c17d0797b9686a7f9f6005cb7

https://bscscan.com/tx/0x994abe7906a4a955c103071221e5eaa734a30dccdcdaac63496ece2b698a0fc3

The attacked project is H2O, and the attack caused a total loss of 22,000 USD.

Attack and incident analysis

In the first attack, the attacker first borrowed 100,000 USDT from the PancakeSwapV3 Pool using flashloan as the initial capital for the attack.

Subsequently, the initial borrowed funds were used to redeem 66,439,209 H2O in the USDT-H2O PancakeSwap Pair.

The attacker then frequently transferred H2O to the PancakeSwap Pair USDT-H2O, causing the USDT reserve and H2O reserve in the Pair to be unbalanced, and then used skim to balance reserve0 and reserve1 in the Pair to carry out the attack. The vulnerability of H2O appears in the transfer function, and we can see the specific implementation of the transfer function.

The problem specifically occurs in the function. When from is a PancakeSwap Pair, the _calulate function is called. Since the attacker takes advantage of the imbalance between Reserve0 and Reserve1 of the Pair and calls skim to transfer to itself, the sender of the transfer is the Pair address. Next, let’s take a look at the specific implementation of this function.

The logic of this function is very simple. It dynamically sets the reward rate (1%-5%, the lower the balance, the lower the rate) according to the balance of H2O tokens held by the contract itself, and distributes H2 or O2 tokens to users in proportion through on-chain random numbers; when a user holds at least 10 H2 and 5 O2, he can destroy the tokens in a 2:1 ratio (simulating the chemical reaction 2H₂+O₂→2H₂O) and exchange them for the H2O tokens in the contract. The actual exchange amount is limited by the balance of the contract.

The logic of the contract to generate on-chain random numbers is as follows:

Calculated based on blocktime, blocknumber and keccak256 of msg.sender. In the first attack, since the attacker did not have H2 Token and O2 Token, 169,731,921 O2 Token were obtained in this attack. Next, the attacker only needs to make getRandomOnchain()%2 == 1 to complete the attack. The attacker then made three more attempts, but the first two getRandomOnchain()%2 were both 0, resulting in the failure of the attack. The fourth attempt was the final one.

In the fourth attack, the attacker first borrowed 100,000 USDT from PancakeSwapV3 Pool using flashloan as the initial capital for the attack.

Subsequently, the initial borrowed funds were used to redeem 66,439,209 H2O in the USDT-H2O PancakeSwap Pair.

The attacker then frequently transferred H2O to the PancakeSwap Pair USDT-H2O, causing an imbalance between the USDT reserve and the H2O reserve in the Pair. He then used skim to balance the reserve0 and reserve1 in the Pair to carry out the attack.

According to our analysis above, getRandomOnchain()%2 is 1 in this attack, so H2O will mint H2Token. Because the attacker used getRandomOnchain()%2 to be 0 during the first attack, a large number of O2 Tokens were minted. Therefore, H2O burned H2 and O2 and transferred its own H2O to the attacker.

Finally, the attacker exchanged 122,820 USDT with the H2O that came out of thin air. After repaying the flashloan of 100,000 USDT and the interest of 50 USDT, the final profit was 22,770 USDT.

Summary

The main cause of this vulnerability is that when the H20 Token contract designed the economic model of buying from PancakeSwap Pair, it did not consider that skim could also achieve the same purpose when modifying the ERC20 transfer function, resulting in the attacker using skim to obtain a large amount of incentives out of thin air. It is recommended that the project party should conduct multi-party verification when designing the economic model, price calculation mechanism and code operation logic, and try to select multiple audit companies for cross-audit when auditing the contract before it goes online.

💬 Website 🐦Twitter

--

--

lunaray
lunaray

Written by lunaray

Lunaray takes a leading position in smart contract auditing and consulting service for blockchain security.

No responses yet