Box

Box

3BoxTech Founder / Web3Box Founder/ solidity dev./Several years of experience in Solidity and full-stack development.
twitter

Web3 Enterprise Engineering - Beginner's Guide: 3. Deploying a UniswapV3

Frontier#

Since this is a progressive tutorial, we definitely can't start writing code right away. It's like wanting to build a perpetual motion machine - you need to know what it looks like in order to break it down better.

So in this chapter, our main focus is to deploy a UniswapV3, so the purpose of this chapter is to quickly and simply deploy a UniswapV3 for future integration with our program and Uni.

Installing Uni Package#

However, before installation, I recommend saving the template configured in Chapter 2 so that you don't have to configure it again in the future. Of course, this is optional.

First, install UniswapV3. We need to know one thing: Uniswap's contracts are divided into two - v3-periphery and v3-core. Let's briefly explain what these two repositories represent.

v3-core#

The core contract is responsible for managing the pool and factory in Uniswap.

Pool: A contract for storing funds and performing exchange operations.

Factory: A contract for creating pools in batches.

These two contracts are the core of Uniswap. They are the minimum contracts that can run normally even without the periphery.

v3-periphery#

Periphery contains peripheral contracts that provide users and developers with a unified interface or convenient tokens. The core contracts are NFTManager and SwapRouter.

NFTManager: A contract for recording various data on liquidity created by users.

SwapRouter: A wrapper that encapsulates various logic for exchanges.

Here, we won't go into too much detail about the logic of UniswapV3. Our focus is on how to deploy it.

To do this, execute:

yarn add @uniswap/v3-core @uniswap/[email protected]

Install the two necessary contract repositories. Note that @uniswap/[email protected] has a version number because at the time of writing this article, version 1.4.2 was missing the artifacts folder. If you are reading this article and the issue has been resolved, you don't need to specify the version number at the end.

Deploying via ByteCode#

There is actually only one way to deploy contracts, which is through bytecode. However, different tools provide different levels of abstraction. To the point where you only need to enter a contract name to deploy it. However, for the sake of understanding the principles, we will use the most basic deployment method.

First, create a deploy file. Create a file named 00_deploy_univ3.ts in the deploy folder.

The code content is as follows:

import { DeployFunction } from "hardhat-deploy/types";

const func: DeployFunction = async function () {
    
}

export default func;

This is the most basic framework function for a deploy file. The first thing we need to deploy is the factory contract in the core. So we modify the code as follows:

import { DeployFunction } from "hardhat-deploy/types";
import {
    abi as FACTORY_ABI,
    bytecode as FACTORY_BYTECODE,
} from '@uniswap/v3-core/artifacts/contracts/UniswapV3Factory.sol/UniswapV3Factory.json'
import { HardhatRuntimeEnvironment } from "hardhat/types";

const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) {
    const { deployments,ethers } = hre
    const [deployer] = await ethers.getSigners()
    await deployments.deploy("UniV3Factory", {
        from: deployer.address,
        contract: {
            bytecode: FACTORY_BYTECODE,
            abi: FACTORY_ABI
        },
    })
}

export default func;

With a few "details" added, our code becomes more enriched. Let's explain the key content here.

import {
    abi as FACTORY_ABI,
    bytecode as FACTORY_BYTECODE,
} from '@uniswap/v3-core/artifacts/contracts/UniswapV3Factory.sol/UniswapV3Factory.json'

This code imports the bytecode and ABI data from the official package provided by Uniswap, allowing us to directly fill in the content below.

await deployments.deploy("UniV3Factory", {
    from: deployer.address,
    contract: {
        bytecode: FACTORY_BYTECODE,
        abi: FACTORY_ABI
    },
})

This code deploys the V3Factory contract. The deploy function is provided by the hardhat-deploy plugin, and in the second parameter, we specify the bytecode and ABI - both of which are required.

Of course, we also need to modify the tsconfig.json file and add the option "resolveJsonModule": true. The modified file is as follows:

{
  "compilerOptions": {
    "target": "es2020",
    "module": "commonjs",
    "esModuleInterop": true,
    "forceConsistentCasingInFileNames": true,
    "strict": true,
    "skipLibCheck": true,
    "resolveJsonModule": true
  },
}

Next is the SwapRouter contract. We follow the same steps and modify the code as follows. You can also try it yourself.

import { DeployFunction } from "hardhat-deploy/types";
import {
    abi as FACTORY_ABI,
    bytecode as FACTORY_BYTECODE,
} from '@uniswap/v3-core/artifacts/contracts/UniswapV3Factory.sol/UniswapV3Factory.json'

import {
    abi as SWAP_ROUTER_ABI,
    bytecode as SWAP_ROUTER_BYTECODE,
} from '@uniswap/v3-periphery/artifacts/contracts/SwapRouter.sol/SwapRouter.json'
import { HardhatRuntimeEnvironment } from "hardhat/types";
import { constants } from "ethers";

const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) {
    const { deployments, ethers } = hre
    const [deployer] = await ethers.getSigners()
    const factory = await deployments.deploy("UniV3Factory", {
        from: deployer.address,
        contract: {
            bytecode: FACTORY_BYTECODE,
            abi: FACTORY_ABI
        },
    })

    await deployments.deploy("UniV3SwapRouter", {
        from: deployer.address,
        contract: {
            abi: SWAP_ROUTER_ABI,
            bytecode: SWAP_ROUTER_BYTECODE
        },
        args:[factory.address,constants.AddressZero]
        // The above are the parameters for deploying the contract, the first parameter is the factory address, and the second is the WETH address. Here, for convenience, we directly use the address 0 😁
    })
}

export default func;

So our deployment script is now complete. You can deploy the code to any network using the command yarn hardhat deploy.

However, deploying directly via bytecode has some drawbacks. For example, when an error occurs, you cannot obtain source code-level error tracing. Also, what we deploy is an incomplete version because we still lack the NonfungiblePositionManager, NonfungibleTokenPositionDescriptor, and NFTDescriptor contracts. However, their deployment methods are the same. You can try adding them using the above method. Consider it as homework.

Conclusion#

This chapter only builds the basic files for deploying Uniswap via bytecode. However, our content is not enough for an actual Uniswap operation. So in the next chapter, we will deploy UniswapV3 using a different method and write test cases. Once the test cases pass, we will deploy UniswapV3 using the source code compilation method.

PS: I found that Mirror is not suitable for writing technical articles like this, so I will switch to another platform in the future.

Loading...
Ownership of this post data is guaranteed by blockchain and smart contracts to the creator alone.