Building Your First Uniswap Integration

·

Integrating with decentralized finance (DeFi) protocols is a foundational skill for modern blockchain developers. Among the most widely used DeFi platforms, Uniswap stands out as the leading automated market maker (AMM) on Ethereum, offering deep liquidity and open access to thousands of token pairs. For developers, building a smart contract that interacts with Uniswap unlocks powerful financial functionality — from automated trading to yield strategies.

This guide walks you through creating your first Uniswap V3 integration from scratch. You’ll set up a development environment, write a smart contract that executes a WETH-to-DAI swap, and test it locally using a forked Ethereum mainnet. Whether you're new to DeFi or expanding your Web3 toolkit, this tutorial gives you a reusable foundation for on-chain integrations.

Setting Up Your Development Environment

Before writing any code, you need a reliable local setup that simulates real blockchain conditions. The goal is to interact with actual deployed Uniswap contracts without paying gas fees or risking mainnet assets.

We’ll use Hardhat, a powerful Ethereum development environment, combined with Alchemy, a robust node provider that supports mainnet forking — a critical feature for testing integrations against live protocol states.

Create an Alchemy Account

To communicate with the Ethereum blockchain, your development tools need an RPC (Remote Procedure Call) endpoint. Alchemy provides high-performance, free-tier RPC services ideal for development.

👉 Generate a free API key and set up your Ethereum node in minutes.

Visit alchemy.com and sign up. Once registered, create a new app under the Ethereum network. Copy the HTTP API key — you’ll use it shortly to fork the mainnet.

Clone the Starter Project

Uniswap Labs provides a boilerplate repository to accelerate development. This project includes preconfigured Hardhat settings and dependency references.

Run the following commands in your terminal:

git clone https://github.com/Uniswap/uniswap-first-contract-example
cd uniswap-first-contract-example
npm install

This installs Hardhat, ethers.js, and Uniswap’s official V3 periphery libraries — everything needed to interact with the protocol.

Fork Ethereum Mainnet Locally

One of Hardhat’s most valuable features is the ability to fork Ethereum mainnet. Instead of starting from an empty test chain, you clone the entire current state of Ethereum — including all deployed contracts like Uniswap.

With your Alchemy API key, start the local node:

npx hardhat node --fork https://eth-mainnet.alchemyapi.io/v2/YOUR_API_KEY_HERE

Now you’re running a full Ethereum node on localhost:8545, complete with live Uniswap pools, token balances, and liquidity data. This environment mirrors production — perfect for safe, realistic testing.

Writing a Basic Swap Contract

Let’s build a smart contract that swaps Wrapped Ether (WETH) for DAI using Uniswap V3’s SwapRouter.

Open contracts/SimpleSwap.sol. The initial template includes standard Solidity declarations:

// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity =0.7.6;
pragma abicoder v2;

import '@uniswap/v3-periphery/contracts/interfaces/ISwapRouter.sol';
import '@uniswap/v3-periphery/contracts/libraries/TransferHelper.sol';

These imports bring in:

Now define the contract:

contract SimpleSwap {
    ISwapRouter public immutable swapRouter;

    address public constant DAI = 0x6B175474E89094C44Da98b954EedeAC495271d0F;
    address public constant WETH9 = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2;
    uint24 public constant feeTier = 3000;

    constructor(ISwapRouter _swapRouter) {
        swapRouter = _swapRouter;
    }
}

Here:

Implementing the Swap Logic

Add the core function:

function swapWETHForDAI(uint amountIn) external returns (uint amountOut) {
    TransferHelper.safeTransferFrom(WETH9, msg.sender, address(this), amountIn);
    TransferHelper.safeApprove(WETH9, address(swapRouter), amountIn);

    ISwapRouter.ExactInputSingleParams memory params = ISwapRouter.ExactInputSingleParams({
        tokenIn: WETH9,
        tokenOut: DAI,
        fee: feeTier,
        recipient: msg.sender,
        deadline: block.timestamp,
        amountIn: amountIn,
        amountOutMinimum: 0,
        sqrtPriceLimitX96: 0
    });

    amountOut = swapRouter.exactInputSingle(params);
    return amountOut;
}

This function:

  1. Transfers WETH from the user to the contract.
  2. Approves the SwapRouter to spend it.
  3. Executes a single-pool swap with exact input.
  4. Sends DAI directly to the user.
Note: In production, set amountOutMinimum to prevent slippage attacks.

👉 Discover how professional traders automate swaps with precision execution tools.

Testing the Contract Locally

Hardhat includes Chai for writing tests. Open test/SimpleSwap.test.js.

Deploy the contract:

const simpleSwapFactory = await ethers.getContractFactory('SimpleSwap');
const simpleSwap = await simpleSwapFactory.deploy(SwapRouterAddress);
await simpleSwap.deployed();

Wrap ETH into WETH for testing:

const signers = await hre.ethers.getSigners();
const WETH = new hre.ethers.Contract(WETH_ADDRESS, ercAbi, signers[0]);
await WETH.deposit({ value: hre.ethers.utils.parseEther('10') });

Approve the contract to spend WETH:

await WETH.approve(simpleSwap.address, hre.ethers.utils.parseEther('1'));

Execute the swap:

const amountIn = hre.ethers.utils.parseEther('0.1');
await simpleSwap.swapWETHForDAI(amountIn);

Verify the outcome by comparing DAI balances before and after.

Run the test:

npx hardhat test --network localhost

If you see “1 passing”, your integration works!

Frequently Asked Questions

Q: Why do I need to fork mainnet instead of using a testnet?
A: Testnets often lack liquidity and deployed contracts. Forking mainnet gives you access to real Uniswap pools with accurate pricing and reserves.

Q: Can I use this contract on other networks like Polygon or Arbitrum?
A: Yes! Deploy the same logic on any chain where Uniswap V3 is available — just update token addresses and router endpoints.

Q: What is slippage, and why should I care?
A: Slippage is the difference between expected and executed price. Always set amountOutMinimum in production to protect users.

Q: How do I handle failed swaps?
A: The exactInputSingle call reverts if output is below minimum. Wrap in try-catch or use off-chain price checks first.

Q: Is it safe to hardcode token addresses?
A: For learning, yes. In production, consider using address providers or making them configurable.

Q: Can I swap across multiple pools?
A: Yes — use exactInput with a path instead of exactInputSingle for multi-hop routes.

What’s Next?

Now that you’ve built and tested your first integration:

The full power of DeFi is now at your fingertips. With real-time liquidity access and composable finance primitives, your next innovation is just a few lines of code away.

👉 Access advanced trading APIs and blockchain tools to scale your DeFi projects.

For documentation and support, visit Uniswap Docs or join the Uniswap Discord. Happy coding!