Web3 企业级工程 - 初级篇:3. 部署一个 UniswapV3
2022-09-16 00:23
Box ⛩️
2022-09-16 00:23
订阅此专栏
收藏此文章

前沿

既然是一个循序渐进的教程,那么肯定不能一上来就开始写代码。就好比你想造一台永动机,你至少要知道这个永动机动起来是什么样子,你才能更好的去分解他。

所以这一章节我们主要是部署一个 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/v3-periphery@1.4.1

先安装好两个必要的合约仓库。要注意的是,@uniswap/v3-periphery@1.4.1 是带了版本号的,这是因为在编写本文的时候,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 不太适合写这种技术类文章,后续会切换到其他平台。

【免责声明】市场有风险,投资需谨慎。本文不构成投资建议,用户应考虑本文中的任何意见、观点或结论是否符合其特定状况。据此投资,责任自负。

相关Wiki
Box ⛩️
数据请求中
查看更多

推荐专栏

数据请求中
在 App 打开