Back to Blog

#6: Hundred Finance Incident: Catalyzing the Wave of Precision-Related Exploits in Vulnerable Forked Protocols

Code Auditing
February 16, 2024

On April 16th, 2023, Hundred Finance, a Compound V2 fork, was attacked, leading to a loss of about $7.4 million. The attack involved two main issues:

  • A precision loss issue (an incorrect rounding issue);
  • A empty markets, which allowed the hacker to manipulate the exchangeRate.

Compound V2, the most forked lending protocol according to DeFiLlama, boasts over 100 forks. Audited by OpenZeppelin and proven in battle, its contracts are deemed secure. Yet, the Hundred Finance attack highlighted how precision loss, especially in low liquidity, can critically affect DeFi protocol security, triggering a wave of similar exploits across notable forks like Midas and Radiant.

For a deeper understanding, you are encouraged to consult the full analysis. Below, we provide a succinct introduction to this incident, highlighting it as one of the top ten security incidents of 2023.

Background

Overview of Hundred Finance

Hundred Finance is a fork of Compound v2 that operates across multiple mainnets, utilizing Chainlink oracles. Unlike traditional finance lending practices, DeFi lending protocols like Compound and Aave do not allow for over-collateralized borrowing. Simply put, if you deposit $100 worth of Token A, you can only borrow assets worth less than $100. According to the risk control coefficients of most protocols, this ratio typically ranges from 50% to 80%.

For lending protocols, common attack methods include price manipulation and reentrancy. Interestingly, Hundred Finance had previously experienced a reentrancy attack in March 2022, but this incident created a new attack vector.

hToken

Lending protocols that fork from Compound and Aave create a corresponding accounting token for each underlying token (collateral). For Hundred Finance:

  • USDC corresponds to hUSDC
  • WBTC corresponds to hWBTC

The exchange rate between underlying token and hToken is referred to the exchangeRate.

  • When depositing assets, users should call the mint() of the hToken.
  • When withdraw assets, user should call the redeem() of the hToken.

exchangeRate

The following is the formula for calculating the exchangeRate: image

Where:

  • getCash(): The amount of underlying token balance owned by this hToken contract. This is a key parameter that can be manipulated. Please remember this.
  • totalBorrows(): The amount of underlying token currently loaned out by the market, and the amount upon which interest is accumulated to suppliers of the market.
  • totalReserves(): Reserves are an accounting entry in each hToken contract that represents a portion of historical interest set aside as cash which can be withdrawn or transferred through the protocol’s governance.
  • totalSupply(): The number of tokens currently in circulation in this hToken market.

Note: The exchangeRate between a hToken and the underlying asset e.g. (dai vs hDai or eth vs hEth) begins at 0.020 and increases at a rate equal to the compounding market interest rate.

Liquidation

To prevent bad debt, lending protocols allow any user to liquidate another user's debt. Let's use the following example to illustrate:

  1. Alice deposits BTC worth $100 and borrows ETH worth $70.
  2. If the price of ETH rises or the price of BTC falls, Alice's assets may reach the liquidation threshold.
  3. Bob can use a certain amount of ETH to liquidate Alice's BTC, bringing Alice's debt back to a healthy level to ensure the safety of the protocol's funds (the protocol rewards users who initiate liquidation).

Liquidation is not the focus of this attack, but it was involved in the attack. Here, we only need to know that any user can liquidate another user's debt with one type of Token, which will reduce the corresponding hToken.

The Vulnerability

Precision Loss Issue

The hacker makes that when collateral is withdrawn through redeem(), the calculation for the amount of hToken to be deducted results in 1.99999992 (very close to 2 but less than 2). When converting to an integer in truncate(), the use of rounding down leads to a final result as 1.

exchangeRate

The calculation of the exchangeRate, as previously introduced, involves getCash(), which refers to the amount of underlying balance owned by the hToken contract. By directly transferring underlying tokens into the contract (without mint, just transferring), the hacker can manipulate the exchangeRate. However, it's important to note that this exchangeRate issue alone does not compromise security of the protocol; Hackers cannot profit from it in isolation. In the context of this attack, it was primarily exploited to amplify the hacker's gains, allowing them to rapidly deplete the pool. Otherwise, the attack shifts from a single, decisive strike to a series of minor stabs, requiring numerous iterations to have a significant impact.

To be brief, the precision loss is key issue in this attack.

The Attack Process

Here is the attack transaction, and we will now use the Phalcon Explorer to analyze this complex transaction.

Transaction: 0x6e9ebcdebbabda04fa9f2e3bc21ea8b2e4fb4bf4f4670cb8483e2f0b2604f451

  1. Borrow 500 WBTC from Aave V3 through a Flashloan.

  2. Redeem all the previously acquired hWBTC, reset hWBTC's totalSupply to 0.

The objective before is prepare reserve funds using a flashloan and to reset hWBTC as a new market.

  1. Create the second attack contract (hereafter referred to as Attack Contract 2) and transfer all WBTC (500.30063816 WBTC) to Attack Contract 2.

  2. Mint() hWBTC using 4 WBTC to produce 200 hWBTC.

  3. Redeem() 199.99999998 hWBTC, leaving the hWBTC total at 0.00000002 (2 wei hWBTC).

  4. Transfers all WBTC (500.30063816 WBTC) into hWBTC. Note, direct transfers do not increase hWBTC; it can be seen as donating WBTC to the pool. The main purpose of this step is to manipulate the exchangeRate mentioned earlier. At this point, hWBTC's totalSupply remains at 2 wei hWBTC, but there are now 500.30064194 WBTC, making the exchangeRate hundreds of times the original.

  5. Borrow 1021 Ether from the hETH market.

  6. Redeem() 50030063815 WBTC, where, after calculation, 1.9999992 hBTC should be deducted, but due to precision loss, only 1 hBTC is deducted, creating a significant precision loss (nearly 50%). At this point, the hacker has 500 WBTC + 1021 Ether, successfully profiting 1021 Ether.

  7. The attacker liquidate() the remaining hWBTC, resetting its totalSupply to 0, in preparation for continuing attacks on other markets. Given that almost all WBTC within hWBTC has been withdrawn, the hacker manages this with just 0.000002 Ether.

  8. Continue to attack other markets, draining the entire protocol.

  9. Repay the Flashloan to Aave.

Security Recommendations

Mitigations for Lending Protocol

This issue is prevalent, particularly for forks of Compound and Aave. A proactive approach involves, when launching new markets, minting some accounting token to ensure the totalSupply never goes to 0.

Mitigations for Precision Loss Issue

To better circumvent the series of issues due to precision loss, setting a minimum value is an effective method in practice. This strategy helps to avoid the significant impact caused by precision loss when dealing with very small values.

Sign up for the latest updates
~$11.3M Lost: Multicall Router, Nostra | BlockSec Weekly
Security Insights

~$11.3M Lost: Multicall Router, Nostra | BlockSec Weekly

This report, covering 2026/09/14 - 2026/09/20, examines two security incidents with approximately $11.3M in combined losses, on Ethereum and Starknet. In the larger one, a multicall router accepted its own address as a dispatch target, so the nested call reached the Gateway module of a Safe wallet carrying the router's own already-authorized identity instead of the external caller's, and roughly 2,900 `aEthrsETH` was routed out of that wallet into an attacker-created Uniswap v4 pool. On Starknet, Nostra's oracle integration required a minimum of only one aggregated source, so when only two of the three configured price sources reached the aggregation, a manipulated thin-pool quote averaged with a normal quote to value `NSTR` at roughly $49.52, supporting approximately $3.5M of borrowing against overvalued collateral.

~$320M Lost: Liquid Network, Symbiosis Exploits | BlockSec
Security Insights

~$320M Lost: Liquid Network, Symbiosis Exploits | BlockSec

This report, covering 2026/09/07 - 2026/09/13, examines two security incidents that caused approximately $320M in losses, including the Liquid Network exploit of 2026/09/06 that the previous report did not cover. The larger was that Liquid Network exploit, where the rangeproof validation cache in Elements derived its key by hashing four fields — two of them variable in length — concatenated with nothing marking the boundaries between them, so a verdict recorded for one output was returned for another whose proof was never examined, letting the attacker create 4,000 unbacked L-BTC and peg out nearly all of them as bitcoin. On the Bitcoin route of the Symbiosis cross-chain bridge, spanning BNB Smart Chain, Ethereum and Rootstock, off-chain code that reads Bitcoin deposits took the depositor's identity from a field the depositor controls and then subtracted its fee from the deposit without checking whether the fee itself was negative, letting a 330-satoshi deposit mint `46,116,860,184.27388234 syBTC`; the pools it had to be sold through held only 11.26 syBTC, so the loss to liquidity providers and users came to an estimated 9.97 BTC (~$770K).

~$9.4M Lost: Injective, Aquifer Exploits | BlockSec Weekly
Security Insights

~$9.4M Lost: Injective, Aquifer Exploits | BlockSec Weekly

During the past week (2026/08/31 - 2026/09/06), four security incidents caused approximately $9.4M in losses across Injective, Solana, Ethereum, and Flow EVM. The largest was the Injective exploit, where an insurance fund identifier collided with a binary options market identifier and the settlement path never compared their denominations, draining about $4.8M; Aquifer on Solana lost about $2.47M because its swap path invoked an unvalidated caller-supplied Token Program, and Notional Finance V1 on Ethereum lost about $1.73M to an unchecked `uint128` cast that valued a debt at zero. Ankr FLOW on Flow EVM closed out the week with about $410K drained through a staking entry point that skipped its pause guard and minted against a stale ratio.

Best Security Auditor for Web3

Validate design, code, and business logic before launch. Aligned with the highest industry security standards.

BlockSec Audit