# Introduce of HopeLend

HopeLend is a decentralized non-custodial lending protocol with multiple liquidity pools. It enables instant loans based on the state of the pool, and loans do not need to be individually matched on both sides; instead, they rely on pooled funds, the amounts borrowed, and their collateral. Like Aave, the diagram below describes the business flow of HopeLend.

In simple terms, users can deposit underlying assets to provide liquidity. When this liquidity generates income through lending, a portion of the earnings is distributed to the liquidity providers.

**Analysis Of HopeLend Attack**

In simple terms, the hacker attack process can be divided into two main parts:

- Exploiting the insufficient liquidity in Hopelend’s
**hEthWBTC**trading pool (with zero liquidity) to artificially inflate the value of**hEthWBTC**. Subsequently, the hacker uses the borrow function to drain all tokens (**HOPE**,**stHOPE**,**wstETH**,**WETH**,**USDT**,**USDC**) from the pool. - Exploiting the precision loss vulnerability in function
to drain the*rayDiv***2000 WBTC**borrowed from Aave through a flashloan and deposited into Hopelend, thereby emptying all the**WBTC**initially invested by the hacker in the early stages of the attack.

The exchange ratio between underlying assets and hTokens is controlled by the liquidityIndex, a metric representing the value of hTokens. In simple terms, when the ** liquidityIndex **is, for instance, 2, one hToken can be exchanged for 2 units of the corresponding underlying assets. The

**is determined based on the earnings generated, and its calculation involves the following method:**

*liquidityIndex*Here is the corresponding code:

In this attack, the hacker manipulated the liquidityIndex to artificially inflate the value of hTokens, causing a distortion in their value. Subsequently, the hacker used small units of hTokens to borrow substantial amounts of other underlying assets. This ultimately led to draining the underlying assets from other pools within Hopelend.

Following this, the hacker exploited the precision loss issue in function ** rayDiv **by repeatedly executing deposit and withdraw operations. Eventually, the hacker successfully emptied all the initially deposited WBTC into the pool, completing the attack.

## Stage 1

The hacker initiated the attack by using the deposit function to deposit the underlying asset **WBTC **and obtaining **hEthWBTC **tokens from mint function. Subsequently, through repeated flashloan transactions, the hacker manipulated the liquidityIndex of **hEthWBTC**, artificially inflating its price. Finally, leveraging minimal amounts of **hEthWBTC **as collateral, the hacker executed borrow operations to deplete all underlying assets except for **WBTC**.

Firstly, the hacker utilized a flashloan from Aave to borrow **2300 WBTC**. Subsequently, the hacker executed a deposit of **2000 WBTC** into Hopelend. Simultaneously, the corresponding trading pool minted **2000 hEthWBTC** as a deposit certificate for the hacker. Following this, the hacker employed Hopelend’s flashloan to borrow an additional 2000 WBTC. The hacker then transfer **2000 WBTC** into Hopelend’s trading pool. Subsequently, the hacker executed a withdraw operation, retrieving **1999.99999999 WBTC** and leaving a minimal amount of **0.00000001 WBTC** in the pool. The transfer and withdraw operations into Hopelend’s pool were conducted only during the initial flashloan.

This is because the hacker initiated a deposit of **2000 WBTC** into Hopelend, prompting Hopelend to mint 2000 corresponding hTokens (hEthWBTC) as deposit certificates. Subsequently, the hacker used Hopelend’s flashloan to borrow an additional **2000 WBTC**. Following this, the hacker executed a transfer of **2000 WBTC** into the pool corresponding to the underlying asset and then conducted a withdraw operation, retrieving 1999.99999999 WBTC. Since this pool was uninitialized, its liquidityIndex was set to 1. Consequently, the pool destroyed **1999.99999999 hEthWBTC**, leaving behind **0.00000001 hEthWBTC**.

Let’s examine how Hopelend updates the ** liquidityIndex** during a flashloan.

Firstly, ** IERC20(reserveCache.hTokenAddress).totalSupply() + reserve.accruedToTreasury** represents the total value of the corresponding hToken, and

**is the profit generated in this flashloan, i.e., the additional value created. Because the flashloan’s borrowing interest rate is 0.09%, and 30% of the profits go to the protocol, while 70% goes to the liquidity providers, each time the hacker borrows 2000 WBTC through a flashloan, the profit generated for the pool is**

*premiumToLP***. Therefore, in the formula above,**

*2000 * 0.09% * 70% = 1.26 WBTC***is equal to**

*premiumToLP***1.26 WBTC**.

Because ** reserve.accruedToTreasury** is 0, in simple terms, the value of hToken after the flashloan (

**liquidityIndex**) is calculated as follows:

Flashloaned hToken Value = ((Total Value of hToken in the Pool / Premiums to the Pool )+ 1) × Current Value of hToken in the Pool

Therefore, for the hacker to increase the value of hToken, it involves minimizing the total value of hToken in the pool. This explains why the hacker transfers the borrowed **2000 WBTC** to the pool after the flashloan. Since only withdraw operations lead to the destruction (burning) of hToken, if the hacker does not transfer assets to the pool, there are no assets for the pool to use in withdraw operations, preventing the destruction of the corresponding hToken.

To minimize the total value of hToken in the pool, the hacker executes a withdraw of **1999.99999999 WBTC**, leaving only **0.00000001 WBTC** (the minimum unit). Consequently, the pool bruns **1999.99999999 hEthWTBC**, leaving behind **0.00000001 hEthWTBC** (the minimum unit). As the pool corresponding to WBTC and hEthWTBC is uninitialized, the liquidityIndex at this point is 1, and the current total value of the pool is **0.00000001 hEthWTBC **(the minimum unit).

After the first flashloan, the value of **liquidityIndex **for hToken is updated to ** (126000000 * 10²⁷ / 1 + 1) * 1 = 126000001000000000000000000000000000**. At this point, the value of

**0.00000001 hEthWTBC**is equivalent to

**1.26000001 WBTC**.

For the second time, the hacker borrows **2000 WBTC** through a flashloan. Since the liquidityIndex was ** 126000001000000000000000000000000000126000001000000000000000000000000000 **after the first borrowing, the algorithm calculates the updated

**liquidityIndex**at this point as

**.**

*252000000999999999999999999948221218252000000999999999999999999948221218*By repeatedly executing flashloans, the hacker eventually raises the **liquidityIndex **for **hEthWTBC **to ** 75600000010000000000000000096556103367560000001000000000000000009655610336**, meaning

**0.00000001 hEthWTBC**can be exchanged for

**75.60000001 WBTC**.

These are the values of **liquidityIndex** for **hEthWTBC **after each flashloan.

Because there is still the hacker’s **0.00000001 hEthWBTC** (valued at **75.60000001 WBTC**) in the trading pool and its value is substantial, the hacker utilized the collateral in the pool (**0.00000001 hEthWBTC**) to borrow all tokens (**HOPE**, **stHOPE**, **WETH**, **USDT**, **USDC**) through the borrow operation.

## Stage 2

The hacker exploited the precision loss issue in function ** rayDiv **by repeatedly performing deposit and withdraw operations, depleting all the initially invested WBTC from the early stages of the attack.

The hacker initially deposited 151.20000002 WBTC and subsequently withdrew 113.40000000 WBTC. At this point, the liquidityIndex had already increased to ** 7560000001000000000000000009655610336**. When the hacker deposited 151.20000002 WBTC, the pool also minted 0.00000002 hEthWBTC. Upon the withdrawal of 113.40000000 WBTC, the corresponding hEthWBTC to be destroyed should be

**. However, due to truncation, only**

*0.000000019999999998015872***0.00000001 hEthWBTC**was burned.

This is Solidity code snippet of burn function.

In the provided context, _burnScaled appears to be a function responsible for scaling down the amount of hEthWBTC to be burned.

We can observe that the quantity of hToken to be burned is determined by the formula

Amount of burn = (Amount of withdrawn underlying asset / liquidity index of hToken).

However, to minimize the gas consumption associated with mathematical operations, ** rayDiv **function is used for division. The code snippet is as follows:

Because the calculation formula for the quantity of hToken to be burned is given by:

Amount of hToken to be burned = (Amount of withdrawn asset * 10²⁷ +(liquidity index of hToken / 2)) / liquidity index of hToken

At this point, the amount of asset to be withdrawn is 113.40000000 WBTC, and the liquidity index of hEthWBTC is ** 7560000001000000000000000009655610336**. Through calculation using python, we can obtain:

The quantity to be burned is calculated as (1.9999999998015872 * 10^-8) hEthWBTC. However, since this involves integer division using evm opcode div, it effectively performs floor division, discarding the decimal places. As a result, the final amount to be burned is (1 * 10^-8) hEthWBTC, equivalent to 0.00000001 hEthWBTC. This translates to only burning hEthWBTC worth 75.6 WBTC. Therefore, at this point, the hacker has profited by exploiting the precision loss vulnerability, gaining 37.8 WBTC (113.4 WBTC- 75.6 WBTC).

Subsequently, the hacker proceeded to continue deposit, adding 75.60000001 WBTC, and obtaining the pool’s mint 0.00000001 hEthWBTC. (Given that the liquidity index of hEthWBTC is 7560000001000000000000000009655610336, equivalent to 1 unit of the smallest hEthWBTC, i.e., 0.00000001 hEthWBTC, valued at 75.60000001 WBTC.) Consequently, the pool had 0.00000002 hTokens remaining.

Following this, the hacker executed a withdraw, retrieving 113.40000000 WBTC. Due to truncation, only 0.00000001 hToken was burned.

In other words, the hacker deposited 75.60000001 WBTC through deposit and subsequently withdrew 113.40000000 WBTC through withdraw, thereby generating a profit of 37.8000000 WBTC seemingly out of thin air. By continuously repeating this operation, the hacker ultimately emptied the previously invested WBTC, enabling the repayment of the loan from Aave. At this point, the entire attack process has been completed.

# Conclusion

The hacker initially exploit of the liquidity imbalance in the pool corresponding to the target asset, manipulating the liquidity index of the hToken associated with the target asset to distort its value. Subsequently, leveraging the collateral of a minimal amount of hToken, the hacker borrowed all other underlying assets. Following this, by exploiting a precision loss vulnerability in the contract’s division operation, the hacker repeatedly deposited and withdrew, depleting the underlying assets invested in the Hopelend attack. At this point, the hacker completed a complex attack against the DeFi project Hopelend, successfully draining all assets from HopeLend.