【SlowMist Technical Analysis】Uniswap's ERC777 Reentrancy Vulnerability and Defense Methods

share
【SlowMist Technical Analysis】Uniswap

Original Title: "Slow Mist: Detailed Explanation of the ERC777 Reentrancy Vulnerability in Uniswap"

According to ChainNews, on April 18th, Tokenlon announced the suspension of imBTC transfers after discovering that an attacker exploited a reentrancy vulnerability in the Uniswap liquidity contract using ERC777 to conduct ETH-imBTC pool arbitrage. This attack method is a known vulnerability on Uniswap v1, first discovered by Consensys in April 2019. At that time, Consensys only identified the risk without finding tokens that could exploit this method for attacks. Subsequently, after imBTC was listed on Uniswap, due to imBTC being implemented based on ERC777, attackers were able to conduct arbitrage through the reentrancy vulnerability by combining the features of ERC777 and issues in the Uniswap code. Below, we will analyze the attack method and specific details of this arbitrage.

Table of Contents

Preparation

The ERC777 protocol is a token standard protocol on Ethereum, an improvement over the ERC20 protocol on Ethereum. The main improvements are as follows:

1. Sending tokens follows the same concept as sending Ether, using the method: senddest, value, data

2. Both contracts and regular addresses can control and reject which tokens to send by registering the tokensToSend hook function (rejection of sending is achieved by using revert in the hook function tokensToSend)

3. Both contracts and regular addresses can control and reject which tokens to accept by registering the tokensReceived hook function (rejection of acceptance is achieved by using revert in the hook function tokensReceived)

4. tokensReceived can complete token sending and notify the contract of token acceptance in a single transaction, unlike ERC20, which requires two separate calls (approve/transferFrom) to complete

5. Owners can "authorize" and "revoke" operators (operators: those who can send tokens on behalf of the owner), these operators are typically (decentralized) exchanges, check processors, or automated payment systems

6. Each token transaction includes data and operatorData fields to pass data from the owner and operators respectively

7. By deploying a proxy contract that implements tokensReceived, it can be compatible with addresses that do not implement the tokensReceived function

Here, the second point is particularly noteworthy in the ERC777 standard, which is the tokenToSend function. According to the definition of the ERC777 protocol, tokens following this standard will attempt to call the tokensToSend function of the token sender every time a token transfer occurs. Token holders can register their contract by ERC1820 and define certain operations in this hook function to handle certain processes during token transfers, such as rejecting token transfers or other operations.

Understanding these key points helps us grasp the specific attack methods in this case. Now, let's speed up a bit and see what happened with Uniswap in this scenario.

Detailed Analysis

By querying one of the attacker's transactions through Etherscan 0x32c83905db61047834f29385ff8ce8cb6f3d24f97e24e6101d8301619efee96e

It can be observed that the attacker transferred imBTC twice to the Uniswap contract, each time with the amount of 0.00823084, and then received two transactions of ETH from Uniswap. While these transactions may appear normal, there are hidden intentions. To better understand the details of this transaction, we need to examine the specific details of the transaction through bloxy.info.

By querying the details of the transaction, we find that the attacker first exchanged some imBTC for ETH through the ethToTokenSwapInput function with Uniswap, then initiated the first exchange of imBTC for ETH through the tokenToEthSwapInput function. Uniswap first sent the ETH to the attacker, then called the transferFrom function of imBTC. Since imBTC follows the ERC777 standard, when calling the transferFrom function of imBTC, imBTC will invoke the attacker's tokensToSend function. Subsequently, in the attacker's tokensToSend function, the attacker initiated a second exchange of imBTC for ETH, and the process ended.

Looking at the transaction details, there seems to be no issue here; we continue to track Uniswap's code.

The code above is the Uniswap ethToTokenSwapInput function. According to the code analysis, the Uniswap ethToTokenSwapInput function will call the ethToTokenInput function, then use getInputPrice to determine the amount of Ether that can be exchanged for tokens, subsequently sends the Ether to the user using the send function, and finally transfers the tokens into the contract using transferFrom. Let's delve into the getInputPrice function.

Analyzing the getInputPrice function, we can see that the formula for calculating the amount of ETH received is

When placing this formula into the context of the ethToTokenInput function, the formula becomes

In this formula, during a normal exchange of imBTC for ETH, the imBTC reserve should increase after the exchange, and correspondingly, the ETH reserve should decrease.

However, looking back at the attacker's actions, during the first exchange of imBTC for ETH, Uniswap first sent ETH to the attacker, reducing the ETH reserve in Uniswap. Then, Uniswap called the transferFrom function. Notably, the attacker's imBTC was not deducted at this point. Subsequently, in the transferFrom function, during the attacker's second call of ethToTokenSwapInput, the formula for calculating the exchanged ETH amount changes to:

In this second exchange calculation, only the ETH reserve decreases, while the imBTC reserve does not increase. This allows the attacker, through reentrancy, to alter the numerator in the calculation formula during the second exchange with imBTC for ETH, without changing the denominator. Compared to a normal exchange, the attacker can profit slightly through reentrancy during the second exchange, resulting in a profitable outcome. By repeating this process, the attacker can acquire more ETH with an equal amount of imBTC, leading to losses for Uniswap.

Defense Methods
  1. Include OpenZeppelin's ReentrancyGuard function in Uniswap's tokenToEthSwapInput function to prevent reentrancy issues.
  2. Deduct the user's tokens first before sending ETH to the user during token exchanges.

Additionally, the SlowMist Security Team recommends the following for handling this attack:

  1. Implement locking mechanisms in critical business operation methods, such as OpenZeppelin's ReentrancyGuard.
  2. When developing contracts, adopt a writing style that first modifies variables in the contract before making external calls.
  3. Prior to project launch, conduct a comprehensive security audit with a reputable third-party security team to identify potential security issues.
  4. When integrating multiple contracts, ensure a thorough code and business security check on all parties involved to address security issues arising from various business scenarios.
  5. Set up pause switches in contracts as much as possible to promptly detect and mitigate potential "black swan" events.
  6. Security is dynamic; project teams should proactively gather threat intelligence related to their projects and promptly address potential security risks.

Final Thoughts

The DeFi world has been buzzing these past few days, with imBTC at the forefront as an ERC777 token. While the ERC777 protocol has been criticized, is the cause of this attack event really related to imBTC or the ERC777 protocol?

If Uniswap properly incorporates ERC777 compatibility, uses ReentrancyGuard, and deducts the user's tokens before sending ETH during token exchanges, would such issues not occur?

As a tokenized version of Bitcoin on Ethereum, imBTC's security is not an issue when operating independently. However, third-party DeFi platforms, when integrating, should consider the compatibility between the platform's business logic and the tokens being integrated to avoid unnecessary security issues arising from compatibility. Instead of solely blaming the protocol and token provider.

Original Article Link

Related Reading

  • Conscience Found? Dramatic Turn in Lendf Incident, Attacker Returns All Stolen Funds
  • [SlowMist Analysis] Detailed Analysis and Defense Recommendations for DeFi Platform Lendf.Me's Hack

Join Telegram now for the most accurate blockchain news and cryptocurrency updates!