Living in a Lego House: The imBTC DeFi Hack Explained

Last week, several DeFi projects related to Tokenlon’s imBTC token were hacked, resulting in cryptocoins worth tens of millions of USD getting stolen.

At ZenGo, we hold the security of our customers to be our highest priority. Therefore, whenever a major hack occurs, we investigate it to make sure our customers are safe and to learn valuable lessons from the experience of others. In this blog, we will explain this attack and share our findings.

We’ll take a more in-depth look at Ethereum DeFi (Decentralized Finance) and token standards, and shed more light on reentrancy attacks, DeFi’s most notorious attack. We will conclude with some tips to help users avoid risky DeFi projects.

Is it a hat, or a boa digesting an elephant? imBTC UniSwap liquidity totally gone (source: UniSwap)

DeFi and the imBTC Token

The initial promise of cryptocurrencies, and most notably Bitcoin (BTC), was to make transferring money cheaper and more efficient while minimizing the role of intermediaries. DeFi takes this promise and extends it to more sophisticated financial services, such as lending and exchanging.

Due to the open nature of DeFi, each project can be seen as a “money Lego” piece, allowing the easy creation of new services, by putting different DeFi services together. 

The DeFi Money Lego: Creating a new DeFI service by connecting existing DeFi services (source: totle)

DeFi projects are mostly developed on the Ethereum blockchain, leveraging its smart contract functionality. As a result, Bitcoin holders cannot use their funds in Defi as it is implemented on a different blockchain.

To solve this issue, the Tokenlon exchange created the imBTC token, which is an Ethereum based token issued with a 1:1 anchor to BTC. Tokenlon’s users can deposit their BTCs and get imBTCs in return to play the DeFi game and redeem back to BTC when they want out.

imBTC Token and the ERC777 standard

When Tokenlon introduced imBTC, they had made an interesting design choice. Instead of using the tried and tested ERC20 token standard, which has been the choice of most popular tokens on Ethereum, they chose the relatively young ERC777 standard. 

ERC777 was designed to be a “drop-in replacement” for the ERC20 standard. ERC777 supports all ERC20 functionalities and, therefore, can be used, in theory, in a seamless manner in existing DeFi projects designed for ERC20.

Consequently, Tokenlon had no problem adding its newly created “Lego piece” (imBTC token) to existing DeFi platforms designed for ERC20 tokens, such as Uniswap for swapping (exchanging) to other assets and dForce for earning interest.  

Additionally, ERC777 has introduced the concept of “hooks,” to solve some of the ERC20 deficiencies, one of them described in our recent baDAPProve report. Using hooks lets the contract know that it is receiving or sending funds and allow it to act upon it.


Sending Erc777

Using hooks, a receiving contact can perform an action when receiving a token, for example, cancel the transaction if the wrong kind of tokens are sent to it. So it seems Tokenlon had taken the right choice: All of the ERC20 goodness with some additional cool features. However, as they discovered to their dismay, ERC777 hooks also open the door for some serious attacks!

Reentrancy Attacks Explained

Reentrancy attacks are a family of attacks against smart contracts. A reentrancy attack was the cause of one of Ethereum’s most notorious hack, the DAO attack.

Smart contracts can be exposed to reentrancy attacks when they call other contracts and do not protect themselves against the possibility that one of these external contracts is malicious. If the external contract is indeed malicious, it can call the calling contract again (“re-enter”) and make changes to its data in a way the unprepared calling contract was not expecting.

Let’s take a look at this example. Consider the following simple smart contract:

This example withdraw_all function is vulnerable to reentrancy attacks

The withdraw_all function receives the user address in the “sender” parameter.  The function checks if the user has balance and if so, it sends the balance to its address and updates the balance to zero as all money is sent.

This works well if “sender” is a regular address that just passively receives the money sent to it. 

However, if “sender” address is actually a malicious contract, then when money is sent to it, it can call The function withdraw_all(sender) immediately and interrupt the expected flow of the function.

When the withdraw_all function is called again by the malicious contract  (“re-entered”), it checks, as before, if the user has balance. Since the first withdraw_all function did not have the chance to update the balance yet (it only happens in the next line of code), this second withdraw_all function call would find that there is still balance and send it to the malicious sender. This process can be repeated multiple times until the sending contract is out of funds.

Reentrancy attacks can be lethal. However, if the contract is aware, it can defend itself against such attacks. In the example set out above, it is enough to move the balance update to zero before the sending to thwart the reentrancy attack.

Putting it all together: ERC20 DeFi + ERC777 Token

As shown above, ERC777 hooks allow contracts to perform additional functionality when they are receiving or sending funds. However, this very functionality can be abused to allow a malicious contract to perform a reentrancy attack on the unsuspecting calling contract.

Abusing ERC777 hooks to perform reentrancy attacks

Attackers abused imBTC’s ERC777 hooks to perform reentrancy attacks on the imBTC supporting DeFi platforms ( Uniswap, dForce ) mentioned above to steal more than $25 million USD in cryptotokens. The attacks were very similar in detail to the simple example shown above, causing users’ balance not to be updated, and thus allowing multiple withdrawals. For an even deeper analysis of the specifics of the attack, please see here

All of dForce locked funds ($25M) were stolen (source: defipulse)  

Proper design can help in thwarting reentrancy attacks, however, these DeFi projects did not stand a chance. They were designed for ERC20 tokens that did not support hooks and were taken by surprise by imBTC’s ERC777 hooks.  

Takeaways

The technical implications are clear. DeFi projects are simple to create, just like assembling a Lego house by adding pieces together. However, to build a solid house, it’s essential to perform thorough audits and tests.

That’s why when we integrated the Compound DeFi project into our ZenGo wallet to allow our customers to earn, we performed thorough due diligence to understand the inner workings of the project. As a user, you cannot audit DeFi projects yourself. But you should always check the reputation of every project you intend to use and not become a “guinea pig” of new services. It’s especially important to take extra precautions with projects that keep your money, such as lending or investment projects.

Stay safe out there!