Apr 22
15/04/23 Hundred Finance Hack Post-Mortem
At 2:12pm UTC on April 15th, 2023, the Optimism deployment of the Hundred Finance lending protocol was exploited by an attacker, who drained the platform of the entirety of assets held within hToken markets on the chain. The method by which the exploit was carried out relied upon an integer rounding vulnerability in the hToken contract logic for redeeming underlying tokens, a vulnerability that presents itself when a market is empty.
In total, the attacker drained 1,030 ETH, 1,265,979 USDC, 1,113,431 USDT, 865,143 SUSD, 842,788 DAI, 457,286 FRAX and 20,854 SNX from the protocol, with a combined value of approximately $6.8 million USD at the time the hack was carried out. These amounts include assets stolen from the current deployment, as well as around $50,000 USD of ETH, USDC and SNX that remained on the previous Optimism deployment of the app, awaiting withdrawal by their owners. Funds stolen in the hack were supplied by 180 individual wallets, the owners of which are now unable to use their hTokens to reacquire the underlying cryptocurrencies that they had supplied.
Following the hack, the attacker sent the majority of stolen assets to the Ethereum mainnet, swapping them to alternatives that are not subject to pausing by their issuers. The SNX and SUSD tokens, however, remain on Optimism, where, a week later, they have so-far not moved further. Similarly, as of posting, there has been no attacker-initiated transactions on the attacker’s mainnet account since the day of the attack.
Mechanism of the Hack
On April 11th, 2023, the hacker’s wallet, 0x155DA45D374A286d383839b1eF27567A15E67528, withdrew approximately 1 ETH from Tornado Cash, portions of which were then sent to Optimism using the Optimism bridge and to Arbitrum using the Multichain bridge.
Three days later, a second withdrawal of 10 ETH was made from Tornado and used to purchase the WBTC that was then sent, along with further ETH, to Optimism to be used as a part of the attack.
Once the WBTC had been received by their Optimism wallet, the attacker deposited the BTC into the two empty hWBTC markets. One of the generated hWBTC tokens was used as a part of the exploit of the newest Hundred Finance deployment, while the second was used as part of the exploit of the former deployment in which user funds remained. This made them the sole holder of the two types of hWBTC token.
On the day of the hack, the attacker deployed two master contracts that, minutes later, would be used to carry out the same exploit on each deployment. These were both initiated within the space of 30 seconds of each other when the hWBTC tokens were sent to their respective master contracts.
The steps of the attack, occurring within one transaction per master contract, were as follows:
- The hWBTC received by the master contract is burned for the WBTC, emptying the market.
- A large WBTC flashloan is taken out by the master contract using Aave and sent to a drainer contract that it itself creates.
- The drainer contract uses a small portion of its WBTC to mint hWBTC, before redeeming all but 0.00000002 (2 wei).
- The drainer contract then donates WBTC to the hWBTC market, inflating the collateral value of the 0.00000002 hWBTC it holds. This is because in the getAccountSnapshot function, the value of exchangeRateMantissa relies on the amount of WBTC in the contract and not the amount used to generate hWBTC.
- At this stage, thanks to the flashloaned WBTC, the hWBTC has a collateral value that allows it to borrow any of the assets in any market in their entirety, which it then does.
- After borrowing all the assets on a market, the redeemUnderlying call is used by the drainer contract to withdraw all but 0.00000001 of the WBTC, but, due to a rounding error, this only burns half of the master contract’s 0.00000002 hWBTC.
- This rounding error occurs because when the amount of hWBTC needed to redeem the WBTC is calculated, the contract uses a withdrawal formula that rounds down. In the first instance that occurred during the hack, the 0.00000001999999999920048 hWBTC required to redeem 500.30063815 WBTC was rounded down to 0.00000001 hWBTC and successfully used to redeem.
- This meant that, at this point the drainer contract is left with all the WBTC except for the 0.00000001 WBTC that remained in the hWBTC market, the entire balance of the drained market and 0.00000001 hWBTC.
- The drainer contract then sends the WTBC and “borrowed” assets back to the master contract, which liquidates the drainer contract and seizes the remaining 1 wei hWBTC.
- The master contract can then redeem the hWBTC, emptying the market, thus allowing the process to be repeated, draining each of the markets on which assets are held in turn.
- Finally, the flashloan is repaid and the accumulated assets are sent by the master contract back to the hacker’s account on Optimism.
This vulnerability has existed in the Compound v2 code since its launch despite multiple audits, presenting itself when markets are launched with a collateral value in place but no depositors or following markets becoming empty due to user withdrawal post-launch. It can, however, be mitigated by:
- Minting Small cToken (or equivalent) Amounts at Market Creation
Ensuring that markets are never empty by minting small cToken (or equivalent) balances at the time of market creation prevents the rounding error being used maliciously. A deposit as small as 1 wei is sufficient. By having an initial deposit, the exploitable condition of an empty market can be avoided, making the attack unfeasible.
- Deactivate the RedeemUnderlying Function
Another approach to preventing the attack is the deactivation of the redeemUnderlying function. By disabling this function, the attacker would be unable to exploit the rounding bug during the withdrawal process. However, this option may require alternative methods for users to redeem their underlying tokens, and could impact the overall functionality and user experience of the platform.
Response
The Hundred Finance team became aware of the attack when, 14 minutes after it had occurred, an alert was received from Hypernative at 2:26 pm UTC.
In response, the process of pausing markets on all chains was begun so that the nature of the hack could be investigated without further funds being at risk. Users should be aware that this is a paused state that will remain in place for the time being, with only the ability to repay borrows and withdraw supplied assets available on all chains.
Simultaneous with the above, the project Discord and the Hundred Finance Twitter account was used to alert the community of the hack, with the Tweet published at 2:37pm UTC. Efforts had also begun to track funds and the identity of the hacker by reaching out to third-party cybercrime security professionals.
At 4:10pm UTC, the Hundred Finance Admin account on the Ethereum mainnet was used to send a message to the attacker’s address, in which the offer to discuss a bounty and repayment was made. Additionally, having become aware that the exploit remains possible in all Compound v2 forks that have empty markets, the team reached out to potentially vulnerable projects to ensure that they had taken remedial action.
During these and the hours that followed, a data gathering process was initiated that entailed consulting with the teams behind the various applications and protocols with which the attacker had interacted. This has allowed us to acquire clues on the identity of the hacker, evidence that can be further added to as the investigation progresses. The task of identifying affected wallets, amounts lost and coordinating the process of reporting these losses to law enforcement was also started. These were actions that were continued over the following days and will be continued on an ongoing basis.
On April 17th, two days after the hack, a $500k USD open bounty was issued for providing information leading to the arrest of the hacker and the return of all funds. This is a bounty that has already attracted interest, though it remains in place and open to any party.
Having received no direct response from the hacker by the Tuesday following the hack, at 1:31 pm UTC an ultimatum was put out through a second message sent to their mainnet account. This made a single and final public offer of a bounty of 10% of the value of the assets held, as well as a commitment not to pursue them further, in exchange for the return of the remaining 90% within 24 hours.
When, the following day, this offer went unaccepted, law enforcement was informed and criminal proceedings formally begun. This engagement with law enforcement is an ongoing process and we encourage our users to reach out and identify themselves to the extent possible in order to broaden our multi-jurisdiction response. This can be done by joining the project Discord and contacting a member of the team.
Going Forward
While there is still hope that the attacker will return the funds of their own accord, we are now doing everything in our power to retrieve by going down law enforcement channels and contracting forensic analysis. Due to the nature of law enforcement investigations and the potential need to avoid alerting the attackers to their progress in order to optimize the chance of their success, moving forward some information may be privileged. The Hundred Finance team will, however, remain available to answer user questions wherever possible and are united with those affected in the desire for a rapid resolution. Once assets are recovered, distribution to those who have suffered a loss will be carried out as rapidly and as equitably as is possible.
For further information or to coordinate a report to law enforcement, please visit the project Discord
If you have information that you believe may lead to the return of funds and capture of the hacker, in the process qualifying for the $500k USDC reward, please make contact at [email protected]
