SlowMist: Detailed Explanation of Uniswap’s ERC777 Re-entry Risk (Released in 2020)

SlowMist
Block Magnates
Published in
7 min readMay 8, 2023

--

Background

On April 18, 2020 Tokenlon announced the suspension of imBTC transfers because it discovered that an attacker used the ERC777 reentry vulnerability in the Uniswap liquidity contract to arbitrage the ETH-imBTC pool cycle. The attack method this time is a known vulnerability that exists on Uniswap v1. The vulnerability was first discovered by Consensys in April 2019. At that time, Consensys only discovered the risk, and had not found a token that could use this method to attack. Later, after imBTC was launched on Uniswap, since imBTC is implemented based on ERC777, by combining the characteristics of ERC777 and problems in Uniswap code, attackers can achieve arbitrage through reentrancy vulnerabilities. Next, we will analyze the attack methods and specific details of this arbitrage in the future.

Pre-knowledge

The ERC777 protocol is a token standard protocol on Ethereum. This protocol is an improved version of the ERC20 protocol on Ethereum. The main improvements are as follows:

1. Use the same concept as sending ether to send token, the method is: send(dest, value, data)

2. Both the contract and the ordinary address can control and refuse to send which tokens by registering the tokensToSend hook function (the refusal to send is realized by revert in the hook function tokensToSend)

3. Both the contract and the normal address can control and refuse to accept which tokens by registering the tokensReceived hook function (refusing to accept is realized by revert in the hook function tokensReceived)

4. tokensReceived can send tokens and notify the contract to accept tokens in one transaction through the hook function, unlike ERC20, which must be completed through two calls (approve/transferFrom)

5. Holders can “authorize” and “revoke” operators (operators: can send tokens on behalf of the holder) These operators are usually (decentralized) exchanges, check processors or automated payment systems

6. Each token transaction contains data and operatorData fields, which can pass data from holders and operators respectively

7. You can deploy a proxy contract that implements tokensReceived to be compatible with addresses that do not implement the tokensReceived function

Here, we need to pay special attention to the second point, the tokenToSend function in the ERC777 standard. According to the definition of the ERC777 protocol, token tokens that follow this standard will try to call the tokensToSend function of the token sender every time a token transfer occurs, and token holders can register their own contracts in the ERC1820 registration contract and some processes in the token transfer process are handled by defining some operations in this hook function, such as rejecting token sending or other operations.

Understanding these key points will help us understand the specific attack method of this attack. From now on, we can speed up a little and see what happened to Uniswap this time?

Detailed analysis

Query one of the attacker’s transactions via Etherscan 0x32c83905db61047834f29385ff8ce8cb6f3d24f97e24e6101d8301619efee96e

It can be found that the attacker transferred imBTC to the Uniswap contract twice, with the same amount of 0.00823084, and then received two ETHs from Uniswap, which seemed to be two very normal transactions, but in fact they were undercurrents and other mysteries. In order to better understand the details of the entire transaction, we need to view the specific details of the transaction through bloxy.info.

By querying the details of the transaction, we found that the attacker first exchanged some imBTC to Uniswap through the ethToTokenSwapInput function, and then exchanged imBTC for ETH for the first time through the tokenToEthSwapInput function, and then Uniswap first transferred the ETH to the attacker, and then called imBTC’s transferFrom function, since imBTC implements the ERC777 standard, when calling imBTC’s transferFrom function, imBTC will call the attacker’s tokensToSend function. Then, in the attacker’s tokensToSend function, the attacker will exchange imBTC for ETH for the second time, and then the process ends.

From the details of the transaction, there seems to be no problem here, and we continue to track the code of UniSwap.

The code above is the code of Uniswap’s ethToTokenSwapInput function. According to code analysis, Uniswap’s ethToTokenSwapInput function will call the ethToTokenInput function, and then first obtain the amount of eth that can be exchanged for tokens through getInputPrice, and then send the eth to the user through the send function, and finally transfer tokens into the contract through transferFrom. Let’s move on to the getInputPrice function.

By analyzing the getInputPrice function, we can know that the formula for calculating the amount of ETH obtained is

Putting this formula in the context of the ethToTokenInput function, the formula becomes

Under this formula, during a normal imBTC exchange process for ETH, the imBTC reserves used as the denominator should increase after the exchange, and the corresponding ETH reserves will decrease.

But reviewing the attacker’s operation method, when the attacker sends imBTC to ETH for the first time, Uniswap will first send ETH to the attacker. At this time, the ETH reserve in Uniswap decreases, and then Uniswap calls the transferFrom function, (note that at this time the attacker’s imBTC has not been deducted), and then when the attacker calls ethToTokenSwapInput for the second time in the transferFrom function, the formula for obtaining the exchanged ETH amount through getInputPrice will become like this:

Note that in the second exchange calculation, only the reserve of ETH has decreased, but the reserve of imBTC has not increased, which leads to the fact that compared with calling the ethToTokenSwapInput function alone, the attacker can in the process of using imBTC to exchange ETH for the second time, the numerator of the calculation formula has changed, but the denominator of the formula will not change. Compared with the normal exchange, the second exchange performed by the attacker through the re-entry method will obtain a small profit, resulting in a profit. By repeating this process, more ETH can be obtained through the same amount of imBTC, resulting in the loss of Uniswap business operators.

Defense method

1. Add OpenZeppelin’s ReentrancyGuard function to Uniswap’s tokenToEthSwapInput function to prevent reentrancy.

2. When performing token exchange, first deduct the user’s token, and then send ETH to the user.

At the same time, for this attack, the SlowMist security team recommends:

1. Add a lock mechanism to key business operation methods, such as: ReentrancyGuard of OpenZeppelin

2. When developing a contract, use the writing style of first changing the variables of this contract, and then making external calls

3. Before the project goes online, an excellent third-party security team is invited to conduct a comprehensive security audit to discover potential security issues as much as possible

4. When multiple contracts are connected, it is also necessary to check the code security and business security of the multi-party contracts, and fully consider the security issues under the combination of various business scenarios

5. The contract should set the pause switch as much as possible, so that when a “black swan” event occurs, it can be detected in time and stop the loss

6. Security is dynamic, and each project party also needs to capture threat intelligence that may be related to its own project in a timely manner, and timely investigate potential security risks

About SlowMist

SlowMist is a blockchain security firm established in January 2018. The firm was started by a team with over ten years of network security experience to become a global force. Our goal is to make the blockchain ecosystem as secure as possible for everyone. We are now a renowned international blockchain security firm that has worked on various well-known projects such as Huobi, OKX, Binance, imToken, Crypto.com, Amber Group, Klaytn, EOS, 1inch, PancakeSwap, TUSD, Alpaca Finance, MultiChain, O3Swap, etc.

Website:
https://www.slowmist.com
Twitter:
https://twitter.com/SlowMist_Team
Github:
https://github.com/slowmist/

--

--

SlowMist is a Blockchain security firm established in 2018, providing services such as security audits, security consultants, red teaming, and more.