Box

Box

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

Web3企業級工程-初級篇:3. 部署一個UniswapV3

前沿#

既然是一个循序渐进的教程,那么肯定不能一上来就开始写代码。就好比你想造一台永動機,你至少要知道這個永動機動起來是什麼樣子,你才能更好的去分解它。

所以這一章節我們主要是部署一個 UniswapV3,所以這章節的目的是快速並且簡單的部署好一個 UniswapV3,用於未來我們程序和 Uni 的聯調。

安裝 Uni 包#

不過,在安裝之前,我推薦你把第二章配置好的模板保存起來,以後就不用重新配置了。當然,這是可選內容

首先安裝 UniswapV3,我們要知道一件事。Uniswap 的合約分為兩個,一個是v3-periphery 另外一個是v3-core 。現在簡單介紹一下這兩個倉庫的合約是代表什麼。

v3-core#

core 合約是 uniswap 中負責掌管 pool 和 factory 的倉庫。

pool:是資金存儲和交換運算的合約。

factory:用於批量創造 Pool 的合約。

這兩個合約是整個 uniswap 的核心。就算在沒有 periphery 的情況下,也能正常運行的最小合約。

v3-periphery#

periphery 存放的是外圍合約,這些合約是給用戶和開發者一個統一的接口或者是便捷的通證。核心合約有 NFTManager 和 SwapRouter。

NFTManager:一個用於記錄用戶創建的流動性各類數據的合約。

SwapRouter:包裝類,將交換的各種邏輯進行包裝抽象。

這裡我們不過度展開 UniswapV3 的邏輯。我們重點是如何去部署它。

通過執行

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

先安裝好兩個必要的合約倉庫。要注意的是,@uniswap/[email protected] 是帶了版本號的,這是因為在編寫本文的時候,1.4.2 版本缺少 artifacts 文件夾,相關 issue 如下。github-issue,如果當你看到這篇文章時,這個 issue 已經被解決了,那麼就不用加上末尾的版本號指定了。

通過 ByteCode 部署#

部署合約其實只有一種方式,就是從 bytecode 進行部署,但是不同的工具會提供不同等級的封裝。以至於封裝到極致後,你只需要輸入一個合約名稱就可以部署。不過為了方便了解原理,我們就使用最為基礎的部署方式進行部署。

我們先創建一個 deploy 文件。在 deploy 文件夾下創建一個名為 00_deploy_univ3.ts 的文件。

代碼內容如下。

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

const func: DeployFunction = async function () {
    
}

export default func;

這是一個 deploy 文件最基礎的框架函數,我們首先要部署的是 core 中的 factory 合約。所以我們修改代碼為。

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;

加了” 一點點” 細節後,我們的代碼豐富了起來。這裡先解釋一下關鍵內容。

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

這段代碼的內容是從 uniswap 提供的官方包中,引入 bytecode 和 abi 數據,這樣我們就能直接在下面進行內容填充。

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

這段代碼是部署 V3Factory 合約的代碼。其中 deploy 是 hardhat-deploy 插件提供的函數,我們在第二個參數中指定了 bytecode 和 abi—— 這兩個必須都要有。

當然,我們還要修改 tsconfig.json 文件,添加 "resolveJsonModule": true 的選項。修改後文件如下。

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

接下來是 SwapRouter 合約,我們如法炮製,修改代碼如下。當然你也可以嘗試自己動手試試。

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]
        // 上面是部署合約的參數,第一个參數為factory地址,第二個為WETH地址,這裡為了圖方便就直接用0地址啦😁
    })
}

export default func;

那麼我們的部署腳本到這裡就編寫完成了。通過命令yarn hardhat deploy 即可將代碼部署到任何網絡上。

不過,通過 bytecode 直接部署會有一些不好的地方,比如在出錯的時候,你無法獲得源碼級別的錯蹤追蹤。並且,我們部署的也是一個殘缺的版本,因為我們還缺少 NonfungiblePositionManager,NonfungibleTokenPositionDescriptor,NFTDescriptor 合約,不過,它們的部署方式都是一樣的。你可以試著用上述的方法添加它們。就當是課後作業啦。

结语#

這一個章節只構建了通過 bytecode 部署 uniswap 的基礎文件,但是我們的內容其實是不夠一個實際的 uniswap 運行的。所以在下一章節,我們會使用另外一種方式部署 uniswapv3,並且編寫測試用例。等測試用例通過後,我們再用源碼編譯的方式對 UniswapV3 進行部署。

PS:我發現 mirror 不太適合寫這種技術類文章,後續會切換到其他平台。

載入中......
此文章數據所有權由區塊鏈加密技術和智能合約保障僅歸創作者所有。