---
title: Uniswap V2 Periphery with EVM on Polkadot
description: Deploy and test unmodified Uniswap V2 Periphery Router contracts on Polkadot Hub using standard Hardhat and TypeScript with the EVM execution path.
categories:
- Smart Contracts
- Tooling
url: https://docs.polkadot.com/smart-contracts/cookbook/eth-dapps/uniswap-v2/periphery-v2/
word_count: 2065
token_estimate: 3807
version_hash: sha256:a9f58d3b51713dd4c1921f1b9cf7ed135181f8d3af72f0c8c42c3c977f68ea60
last_updated: '2026-06-04T16:08:37+00:00'
---

# Deploy Uniswap V2 Periphery with EVM

## Introduction

The [Uniswap V2 Periphery](https://developers.uniswap.org/docs/protocols/v2/overview) contracts provide the Router layer that sits on top of the [Uniswap V2 Core](/smart-contracts/cookbook/eth-dapps/uniswap-v2/core-v2/) Factory and Pair contracts. While V2 Core handles the low-level AMM logic, the Periphery Router contracts expose the user-facing functions for adding liquidity, removing liquidity, and executing token swaps safely with built-in deadline and slippage protection.

This tutorial follows the EVM execution path. With EVM (powered by [REVM](https://github.com/bluealloy/revm), a Rust implementation of the Ethereum Virtual Machine), you deploy the same unmodified Solidity contracts using the same standard Hardhat toolchain you already know. No special compiler plugins, no contract rewrites, and no porting effort. If your project compiles with vanilla Hardhat, it runs on Polkadot Hub through EVM.

This tutorial walks you through cloning, compiling, testing, and deploying the Uniswap V2 Periphery contracts on Polkadot Hub using Hardhat and TypeScript. By the end, you will have a fully functioning WETH contract, Factory, Router02, two ERC-20 test tokens, and a trading pair deployed to the Polkadot Hub TestNet.

## Prerequisites

Before starting, make sure you have:

- [Node.js](https://nodejs.org/) v22.0.0 or later and npm installed
- Basic understanding of [Solidity](https://www.soliditylang.org/) and TypeScript
- Familiarity with the [Hardhat](/smart-contracts/dev-environments/hardhat/) development environment
- Some test tokens to cover transaction fees, obtained from the [Polkadot faucet](https://faucet.polkadot.io/). See [Get Test Tokens](/smart-contracts/faucet/#get-test-tokens) for a guide to using the faucet
- A wallet with a private key for signing transactions
- Basic understanding of how AMMs and liquidity pools work
- Completion of the [Uniswap V2 Core tutorial](/smart-contracts/cookbook/eth-dapps/uniswap-v2/core-v2/), as the Periphery contracts depend on V2 Core

## Set Up the Project

Start by cloning the Hardhat examples repository, which contains the Uniswap V2 Periphery project with a standard Hardhat and TypeScript configuration:

1. Clone the repository and navigate to the Uniswap V2 Periphery project:

    ```bash
    git clone https://github.com/polkadot-developers/revm-hardhat-examples.git
    cd revm-hardhat-examples
    git checkout a871364c8f4da052855b5c8ee4ed6b89fd182cb1
    cd uniswap-v2-periphery-hardhat/
    ```

2. Install the required dependencies:

    ```bash
    npm install
    ```

    !!! note
        The Periphery project depends on the V2 Core contracts through a local file reference (`"@uniswap/v2-core": "file:../uniswap-v2-core-hardhat"`). The `npm install` command resolves this automatically from the sibling directory in the repository.

3. Compile the contracts:

    ```bash
    npx hardhat compile
    ```

    If the compilation is successful, you should see output similar to the following:

    <div id="termynal" data-termynal>
      <span data-ty="input"><span class="file-path"></span>npx hardhat compile</span>
      <span data-ty>Downloading solc 0.5.16</span>
      <span data-ty>Downloading solc 0.6.6</span>
      <span data-ty>Compiling 24 Solidity files</span>
      <span data-ty>Successfully compiled 24 Solidity files</span>
    </div>
    After running this command, the compiled artifacts (ABI and bytecode) appear in the `artifacts` directory.

## Configure Secure Key Management

This project uses [Hardhat Configuration Variables](https://v2.hardhat.org/hardhat-runner/docs/guides/configuration-variables) to manage private keys securely. Unlike `.env` files, configuration variables are stored outside your project directory and are never at risk of being committed to version control.

To set your private key for TestNet deployment, run:

```bash
npx hardhat vars set TESTNET_PRIVATE_KEY
```

When prompted, paste your private key. Hardhat stores it securely and makes it available through `vars.get("TESTNET_PRIVATE_KEY")` in the configuration file.

!!! warning
    Keep your private key safe and never share it with anyone. If it is compromised, your funds can be stolen.

The `hardhat.config.ts` file references the variable conditionally, so the project works without it for local development:

```typescript title="hardhat.config.ts"
networks: {
    hardhat: {
      allowUnlimitedContractSize: true,
    },
    localNode: {
      url: "http://127.0.0.1:8545",
    },
    polkadotTestnet: {
      url: "https://services.polkadothub-rpc.com/testnet",
      accounts: vars.has("TESTNET_PRIVATE_KEY")
        ? [vars.get("TESTNET_PRIVATE_KEY")]
        : [],
    },
  },
```

!!! note
    You only need the `TESTNET_PRIVATE_KEY` variable when deploying to the Polkadot Hub TestNet. Local development against the development node does not require any key configuration.

## Uniswap V2 Periphery Architecture

Before interacting with the contracts, it is essential to understand how the Periphery layer extends the V2 Core system. While the [V2 Core](/smart-contracts/cookbook/eth-dapps/uniswap-v2/core-v2/) contracts handle low-level pool operations, the Periphery contracts provide a safe and convenient interface for end users and integrating applications.

The Periphery layer introduces three major components:

- **WETH9 contract**: A standard Wrapped Ether contract that allows native ETH to be used as an ERC-20 token. The Router uses WETH to support functions that accept native ETH directly (such as `addLiquidityETH` and `swapExactETHForTokens`), wrapping and unwrapping it transparently.
- **Router01 contract**: The original Router implementation providing core functions for adding and removing liquidity, and executing multi-hop token swaps through a path of pairs. It validates deadlines and minimum output amounts to protect users from slippage and front-running.
- **Router02 contract**: The production Router that extends Router01 with additional support for fee-on-transfer tokens. Functions like `swapExactTokensForTokensSupportingFeeOnTransferTokens` handle tokens that deduct fees on every transfer, ensuring swaps complete correctly even when the received amount is less than the sent amount.

This architecture separates user-facing logic from the core AMM primitives, keeping the Core contracts simple and immutable while allowing the Periphery to evolve independently.

The project scaffolding is as follows:

```text
uniswap-v2-periphery-hardhat/
├── contracts/
│   ├── interfaces/
│   │   ├── IERC20.sol
│   │   ├── IUniswapV2Router01.sol
│   │   ├── IUniswapV2Router02.sol
│   │   └── IWETH.sol
│   ├── libraries/
│   │   ├── SafeMath.sol
│   │   └── UniswapV2Library.sol
│   ├── test/
│   │   ├── CompileHelper.sol
│   │   ├── DeflatingERC20.sol
│   │   ├── ERC20.sol
│   │   ├── RouterEventEmitter.sol
│   │   └── WETH9.sol
│   ├── UniswapV2Router01.sol
│   └── UniswapV2Router02.sol
├── ignition/
│   └── modules/
│       └── UniswapV2Router02.ts
├── scripts/
│   └── deploy.ts
├── test/
│   ├── shared/
│   │   ├── fixtures.ts
│   │   └── utilities.ts
│   ├── UniswapV2Router01.test.ts
│   └── UniswapV2Router02.test.ts
├── hardhat.config.ts
├── package.json
└── tsconfig.json
```

Key differences from a typical Ethereum Hardhat project are minimal. The Solidity contracts are the original Uniswap V2 Periphery source, using both Solidity 0.5.16 (for the V2 Core dependency) and 0.6.6 (for the Router contracts) with no modifications. The Hardhat configuration includes a multi-compiler setup to handle both versions. The test files use TypeScript (`.test.ts`) and avoid `loadFixture` for compatibility with the Polkadot execution environment.

## Test the Contracts

The project includes a comprehensive test suite with 50 tests across two test files. The Router01 test file covers 38 tests for liquidity operations, token swaps, ETH swaps, and permit-based liquidity removal. The Router02 test file covers 12 tests for fee-on-transfer token support and additional swap scenarios.

To run the tests locally:

1. Start the local development node. Follow the steps in the [Local Development Node](/smart-contracts/dev-environments/local-dev-node/) guide to set it up.

2. In a new terminal, run the test suite against the local node:

    ```bash
    npx hardhat test --network localNode
    ```

    The tests are configured with a 120-second Mocha timeout to accommodate Polkadot network block times. The result should look similar to the following:

    <div id="termynal" data-termynal>
      <span data-ty="input"><span class="file-path"></span>npx hardhat test --network localNode</span>
      <span data-ty>Compiling 24 Solidity files</span>
      <span data-ty>Successfully compiled 24 Solidity files</span>
      <span data-ty></span>
      <span data-ty>UniswapV2Router{01,02}</span>
      <span data-ty>  UniswapV2Router01</span>
      <span data-ty>    ✔ factory, WETH</span>
      <span data-ty>    ✔ addLiquidity (12045ms)</span>
      <span data-ty>    ✔ addLiquidityETH (11987ms)</span>
      <span data-ty>    ✔ removeLiquidity (17234ms)</span>
      <span data-ty>    ✔ removeLiquidityETH (17456ms)</span>
      <span data-ty>    ✔ removeLiquidityWithPermit (12134ms)</span>
      <span data-ty>    ✔ removeLiquidityETHWithPermit (17523ms)</span>
      <span data-ty>    swapExactTokensForTokens</span>
      <span data-ty>      ✔ happy path (12378ms)</span>
      <span data-ty>      ✔ amounts (6145ms)</span>
      <span data-ty>    swapTokensForExactTokens</span>
      <span data-ty>      ✔ happy path (12401ms)</span>
      <span data-ty>      ✔ amounts (6178ms)</span>
      <span data-ty>    swapExactETHForTokens</span>
      <span data-ty>      ✔ happy path (12367ms)</span>
      <span data-ty>      ✔ amounts (6134ms)</span>
      <span data-ty>    swapTokensForExactETH</span>
      <span data-ty>      ✔ happy path (12489ms)</span>
      <span data-ty>      ✔ amounts (6201ms)</span>
      <span data-ty>    swapExactTokensForETH</span>
      <span data-ty>      ✔ happy path (12356ms)</span>
      <span data-ty>      ✔ amounts (6167ms)</span>
      <span data-ty>    swapETHForExactTokens</span>
      <span data-ty>      ✔ happy path (12412ms)</span>
      <span data-ty>      ✔ amounts (6189ms)</span>
      <span data-ty>  UniswapV2Router02</span>
      <span data-ty>    ✔ factory, WETH</span>
      <span data-ty>    ✔ addLiquidity (12067ms)</span>
      <span data-ty>    ✔ addLiquidityETH (11998ms)</span>
      <span data-ty>    ✔ removeLiquidity (17289ms)</span>
      <span data-ty>    ✔ removeLiquidityETH (17512ms)</span>
      <span data-ty>    ✔ removeLiquidityWithPermit (12156ms)</span>
      <span data-ty>    ✔ removeLiquidityETHWithPermit (17534ms)</span>
      <span data-ty>    swapExactTokensForTokens</span>
      <span data-ty>      ✔ happy path (12389ms)</span>
      <span data-ty>      ✔ amounts (6156ms)</span>
      <span data-ty>    swapTokensForExactTokens</span>
      <span data-ty>      ✔ happy path (12423ms)</span>
      <span data-ty>      ✔ amounts (6187ms)</span>
      <span data-ty>    swapExactETHForTokens</span>
      <span data-ty>      ✔ happy path (12378ms)</span>
      <span data-ty>      ✔ amounts (6145ms)</span>
      <span data-ty>    swapTokensForExactETH</span>
      <span data-ty>      ✔ happy path (12501ms)</span>
      <span data-ty>      ✔ amounts (6212ms)</span>
      <span data-ty>    swapExactTokensForETH</span>
      <span data-ty>      ✔ happy path (12367ms)</span>
      <span data-ty>      ✔ amounts (6178ms)</span>
      <span data-ty>    swapETHForExactTokens</span>
      <span data-ty>      ✔ happy path (12423ms)</span>
      <span data-ty>      ✔ amounts (6198ms)</span>
      <span data-ty></span>
      <span data-ty>UniswapV2Router02</span>
      <span data-ty>  ✔ quote</span>
      <span data-ty>  ✔ getAmountOut</span>
      <span data-ty>  ✔ getAmountIn</span>
      <span data-ty>  ✔ getAmountsOut (6123ms)</span>
      <span data-ty>  ✔ getAmountsIn (6145ms)</span>
      <span data-ty></span>
      <span data-ty>fee-on-transfer tokens</span>
      <span data-ty>  ✔ removeLiquidityETHSupportingFeeOnTransferTokens (23456ms)</span>
      <span data-ty>  ✔ removeLiquidityETHWithPermitSupportingFeeOnTransferTokens (23567ms)</span>
      <span data-ty>  swapExactTokensForTokensSupportingFeeOnTransferTokens</span>
      <span data-ty>    ✔ DTT -> WETH (12345ms)</span>
      <span data-ty>    ✔ WETH -> DTT (12378ms)</span>
      <span data-ty>  ✔ swapExactETHForTokensSupportingFeeOnTransferTokens (12367ms)</span>
      <span data-ty>  ✔ swapExactTokensForETHSupportingFeeOnTransferTokens (12389ms)</span>
      <span data-ty></span>
      <span data-ty>fee-on-transfer tokens: reloaded</span>
      <span data-ty>  swapExactTokensForTokensSupportingFeeOnTransferTokens</span>
      <span data-ty>    ✔ DTT -> DTT2 (12401ms)</span>
      <span data-ty></span>
      <span data-ty>50 passing (25m)</span>
    </div>
!!! tip
    If tests time out, ensure your local development node is running and accessible at `http://127.0.0.1:8545`.

## Deploy the Contracts

After successfully testing the contracts, you can deploy them to the Polkadot Hub TestNet using [Hardhat Ignition](https://hardhat.org/ignition/docs/getting-started#overview). The Ignition module at `ignition/modules/UniswapV2Router02.ts` deploys WETH9, the UniswapV2Factory, and the UniswapV2Router02 contracts.

Make sure you have [configured your private key](#configure-secure-key-management) and that your account has test tokens. Then run:

```bash
npx hardhat ignition deploy ./ignition/modules/UniswapV2Router02.ts --network polkadotTestnet
```

When prompted, confirm the target network name and chain ID. Ignition deploys the contracts in two batches (Factory and WETH9 in parallel, then Router02) and prints all deployed addresses. The output should look similar to the following:

<div id="termynal" data-termynal markdown>
  <span data-ty="input">npx hardhat ignition deploy ./ignition/modules/UniswapV2Router02.ts --network polkadotTestnet</span>
  <span data-ty>✔ Confirm deploy to network polkadotTestnet (420420417)? … yes</span>
  <span data-ty>&nbsp;</span>
  <span data-ty>Hardhat Ignition 🚀</span>
  <span data-ty>&nbsp;</span>
  <span data-ty>Deploying [ UniswapV2Router02Module ]</span>
  <span data-ty>&nbsp;</span>
  <span data-ty>Batch #1</span>
  <span data-ty> Executed UniswapV2Router02Module#UniswapV2Factory</span>
  <span data-ty> Executed UniswapV2Router02Module#WETH9</span>
  <span data-ty>&nbsp;</span>
  <span data-ty>Batch #2</span>
  <span data-ty> Executed UniswapV2Router02Module#UniswapV2Router02</span>
  <span data-ty>&nbsp;</span>
  <span data-ty>[ UniswapV2Router02Module ] successfully deployed 🚀</span>
  <span data-ty>&nbsp;</span>
  <span data-ty>Deployed Addresses</span>
  <span data-ty>&nbsp;</span>
  <span data-ty>UniswapV2Router02Module#UniswapV2Factory - 0x3Ca8f8C6De9d51B4e14e9Ab7D6d2e38A39C93B85</span>
  <span data-ty>UniswapV2Router02Module#WETH9 - 0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D</span>
  <span data-ty>UniswapV2Router02Module#UniswapV2Router02 - 0xC36442b4a4522E871399CD717aBDD847Ab11FE88</span>
  <span data-ty="input"><span class="file-path"></span></span>
</div>
## Where to Go Next

<div class="grid cards" markdown>

-   <span class="badge tutorial">Tutorial</span> __Uniswap V3 Core__

    ---

    Deploy unmodified Uniswap V3 Core contracts on Polkadot Hub using Hardhat and the EVM execution path.

    [:octicons-arrow-right-24: Get Started](/smart-contracts/cookbook/eth-dapps/uniswap-v3/core-v3/)

-   <span class="badge guide">Guide</span> __Hardhat on Polkadot__

    ---

    Learn how to create, compile, test, and deploy smart contracts on Polkadot Hub using Hardhat.

    [:octicons-arrow-right-24: Reference](/smart-contracts/dev-environments/hardhat/)

-   <span class="badge guide">Guide</span> __Local Development Node__

    ---

    Set up and run a local development node for testing your smart contracts against Polkadot.

    [:octicons-arrow-right-24: Set Up](/smart-contracts/dev-environments/local-dev-node/)

</div>
