Skip to content
Exploiting a Uniswap exchange that uses an ERC777 token by leveraging the reentrant microtrading attack vector
JavaScript Shell
Branch: master
Clone or download
Latest commit 0bc85fc Jul 2, 2019
Permalink
Type Name Latest commit message Commit time
Failed to load latest commit information.
contracts Initial commit Jul 2, 2019
migrations Initial commit Jul 2, 2019
results Initial commit Jul 2, 2019
scripts Initial commit Jul 2, 2019
test Initial commit Jul 2, 2019
.gitignore Initial commit Jul 2, 2019
README.md Initial commit Jul 2, 2019
package-lock.json Initial commit Jul 2, 2019
package.json Initial commit Jul 2, 2019
requirements.txt Initial commit Jul 2, 2019
truffle-config.js Initial commit Jul 2, 2019

README.md

Exploiting an ERC777-token Uniswap Exchange

standard-readme compliant

Exploiting any Uniswap exchange that trades an ERC777 token by leveraging the reentrant microtrading attack vector

Table of Contents

Install

  1. Setup a Python virtual environment
$ pip3 install virtualenv
$ virtualenv -p python3 venv
  1. Activate virtual env & install Python dependencies (just Vyper)
$ source venv/bin/activate
$ pip install -r requirements.txt

If source venv/bin/activate does not work for you, try out with bash venv/bin/activate.

  1. Install NPM dependencies
$ npm install

Run

Once in the virtual environment (where Vyper must be installed), run

(venv)$ npm test

Exploit details

The proof of concept for the exploit is located in the test/uniswap.exploit.js file. It takes care of setting up the entire environment and running three test case scenarios.

The environment consists of:

The three test cases are:

  1. Legitimate trading with a single external sale: a user that holds tokens wants to operate on the exchange, to deposit tokens and receive ETH. This is done in a single transaction calling the tokenToEthSwapInput function. This is the regular use case for a Uniswap exchange.

  2. Legitimate trading with multiple external sales: same as case (1), but now the user submits multiple transactions instead of just 1. Therefore, this results in less profit than (1).

  3. Exploiting: the attacker deploys an attacker contract that will be in charge of operating in the exchange. The exploit is executed in a single transaction, reentering several times in the vulnerable function tokenToEthSwapInput by leveraging the ERC777 tokensToSend hook.

Why it works

By leveraging the tokensToSend hook, the attacker contract is called after receiving ETH (i.e. the exchange ETH balance has decreased) but before the token balance is modified (i.e. the exchange token balance has not decreased). As a consequence, reentering the vulnerable tokenToEthSwapInput will re-calculate the token-ETH exchage price, but this time with less ETH and same amount of tokens in reserves. Thus, the exchange will be buying the attacker tokens, paying in ETH, at a higher price than it should.

Learning resources

Disclaimer

This is a proof-of-concept exploit of an already public, disclosed and acknowledged vulnerability in Uniswap related to reentrancy attacks. Were that not the case, under no circumstances this proof-of-concept exploit would have been made public. Should you find any 0-day vulnerability in these contracts, please report directly to Uniswap.

You can’t perform that action at this time.