Zero Hour Technology || Vyper Reentrancy Lock Vulnerability Caused by Curve Hacking Attack Full Path Analysis

event background

From 21:10 on July 30 to 06:00 on July 31, a large-scale attack occurred on the chain, resulting in the loss of funds in multiple Curve pools. The root cause of the bugs are all due to a reentrancy lock failure in certain versions of Vyper.

 

attack analysis

Through the preliminary analysis of the transaction data on the chain, we sorted out the attacked transactions, and further analyzed the attack process, because the attack involved multiple transaction pools.

The pETH/ETH pool was attacked and traded:

https://etherscan.io/tx/0xa84aa065ce61dbb1eb50ab6ae67fc31a9da50dd2c74eefd561661bfce2f1620c

msETH/ETH pool was attacked transaction:

https://etherscan.io/tx/0xc93eb238ff42632525e990119d3edc7775299a70b56e54d83ec4f53736400964

alETH/ETH pool attacked transaction:

https://etherscan.io/tx/0xb676d789bb8b66a08105c844a49c2bcffb400e5c1cfabd4bc30cca4bff3c9801

CRV/ETH pool attacked transaction:

https://etherscan.io/tx/0x2e7dc8b2fb7e25fd00ed9565dcc0ad4546363171d5e00f196d48103983ae477c

https://etherscan.io/tx/0xcd99fadd7e28a42a063e07d9d86f67c88e10a7afe5921bd28cd1124924ae2052

Since the attack process is basically the same, we mainly analyze the pETH/ETH pool attack transactions in detail:

0xa84aa065ce61dbb1eb50ab6ae67fc31a9da50dd2c74eefd561661bfce2f1620c

Transaction by 0x6ec21d1868743a44318c3c259a6d4953f9978538

Call the attack contract 0x9420F8821aB4609Ad9FA514f8D2F5344C3c0A6Ab, and create a one-time attack contract by this contract

0x466b85b49ec0c5c1eb402d5ea3c4b88864ea0f04, and carry out the next attack process in the constructor of the one-time attack contract;

 

The attacker obtains 80,000 WETH from Balancer through flash loan, and withdraws all of it as ETH through the contract.

 

Immediately afterwards, 40,000 ETH liquidity was provided to Curve's pETH/ETH pool, and approximately 32,431.41 pETH-ETH LP Tokens were received

 

Then the liquidity removal function was called in the attack contract, but we can see from the contract function call stack that the contract returned and called the fallback function of the contract itself when executing the liquidity removal, and in the fallback function The add liquidity operation of the trading pair is also called.

 

According to the contract source code analysis of the pETH/ETH transaction pair, the contract is called again using the contract’s fallback function during the transfer, and contract reentry occurs here, but the LP contract uses reentry locks for adding liquidity and removing liquidity ,As shown below:

 

However, reentrancy still occurred in the actual call stack, which led to the subsequent addition of 40,000 ETH to the LP Token through the attacker's contract and the acquisition of about 82,182.76 pETH/ETH Lp Tokens, which were removed at the end of the callback function of the attack contract The 32,431.41 pETH/ETH Lp Token added at the beginning obtained about 3,740.21 pETH and 34,316 ETH.

 

Then call the remove liquidity function, remove about 10,272.84 pETH/ETH LP Token and get about 1,184.73 pETH and 47,506.53 ETH.

 

The remaining more than 70,000 pETH/ETH LP Tokens are still in the attacker's contract, as shown in the figure below:

 

Next, the attacker exchanged approximately 4,924.94 pETH for 4,285.10 ETH through the Curve pETH/ETH pool.

 

Finally, the attacker converted about 86,106.65 ETH into WETH, returned the flash loan funds of 80,000 WETH to Balancer, and transferred about 6,106.65 WETH of the profit funds to the address 0x9420f8821ab4609ad9fa514f8d2f5344c3c0a6ab.

 

So far, the analysis of the attack process against the pETH/ETH pool has been completed. It is a classic re-entry profit operation. However, by analyzing the source code of the attacked contract, the contract has a corresponding re-entry lock mechanism. Normally speaking It can prevent reentry operations, but does not deny the attacker's reentry operations;

Let's review the description of the reentrant lock in Vyper, and know that the implementation of the reentrant lock is to use the specified slot at the beginning of the function to store whether it is locked or not.

 

We will decompile and view the bytecode of the attacked LP contract:

https://library.dedaub.com/ethereum/address/0x466b85b49ec0c5c1eb402d5ea3c4b88864ea0f04/decompiled

 

It can be seen that the slots for storing reentrant locks in the two functions are not consistent, so the reentrant locks are invalidated, which in turn leads to profit being exploited by attackers.

The Vyper project official also tweeted that there is indeed a reentry lock failure in some versions.

 

By comparing its version 0.2.14 and version 0.2.15, it is found that there is a change in the reentrant lock related setting file data_positions.py corresponding to Vyper. The changed code sets the storage key of the reentrant lock separately, and , each reentrant lock will occupy a different storage slot, resulting in the contract's reentrant lock function being unavailable.

 

This bug has been fixed in PRs: #2439 and #2514

Among them, the problem of adding multiple reentrant storage slots has been fixed, as shown in the figure below:

 

event summary

This attack involved a wide range of attacks. The root cause was that the smart contract infrastructure Vyper versions 0.2.15, 0.2.16, and 0.3.0 had unreasonable reentry lock designs, which led to the use of these versions later. The reentry lock failed in the project and was eventually hacked.

  • It is recommended to choose a stable technology stack and corresponding version during project development, and conduct strict testing on the project to prevent similar risks.

Guess you like

Origin blog.csdn.net/m0_37598434/article/details/132241328