Defi部署教程 Uniswap部署 搭建去中心化交易所

操作系统:MAC OS 10.14.x,需要科学上网

目前大家可以很容易的将自己发行的Token挂在Uniswap上创建交易对并进行交易.如果有些朋友的需求不是发行Token而是创建一个自己的市场,可以通过本文了解到如何部署Uniswap去中心化交易所.
本文将会下载Uniswap的合约源码和前端代码,使用自己的账号部署Uniswap合约到测试网,前端部署到GitHub Pages.

演示地址: https://walker1992.github.io/uniswap-interface/ (请在测试网使用)

准备Uniswap合约源码

源码结构

Uniswap在Github上面开源了全部合约代码,其中包括核心合约,周边合约两部分.Uniswap还开源了前端代码,前端代码使用React开发.

  • 核心合约 uniswap-v2-core

  • 周边合约 uniswap-v2-periphery

  • 前端代码 uniswap-interface

在Uniswap的核心代码中,主要包含3个合约:工厂(Factory)合约,配对(pair)合约,ERC20合约.其中配对合约继承了ERC20合约,我们可以把它们看作一个合约.工厂合约通过create2方法部署配对合约,所以在部署合约时只需要部署工厂合约.
周边合约中包括一些示例代码,例如价格预言机,闪电交换,其中最重要的是路由合约.在周边合约的代码库中,包含两个路由合约:UnsiwapV2Router01,UnsiwapV2Router02.工厂合约和配对合约需要通过路由合约调用才能更好的完成交易所的全部功能,所以我们还要部署路由合约.
两个合约大部分相同,有小部分不同,如果将两个合约的差异化合并成一个合约,部署的时候将会出现out of gas,所以才被分成了两个合约.常用功能两个合约中都包括,所以我们部署其中任意一个路由合约都可以.

合约关系

从浏览器中下载合约源码

如果对合约代码并不熟悉,可以直接从以太坊浏览器中拷贝线上版合约源码

  • 工厂合约

  • 路由合约01[可选]

  • 路由合约02

部署合约

安装truffle

这里使用truffle作为部署合约的环境,其他的环境也可以

$ npm install truffle -g
创建项目
$ mkdir uniswap
$ cd uniswap
$ truffle init
目录结构
uniswap
└───contracts
    └───Migrations.sol
    └───(创建UniswapV2Factory.sol,将浏览器上的工厂合约源码拷贝进来)
    └───(创建UniswapV2Router02.sol,将浏览器上的路由合约源码拷贝进来)
└───migrations
    └───1_initial_migration.js
└───test
└───truffle-config.js

准备部署账户

Uniswap的路由合约在以太坊的主网和Ropsten,Rinkeby,Goerli,Kovan几个测试网的合约地址都是相同的,这样可以使Uniswap的前端不管切换到任何一个网络,路由地址都不会变.要想实现这个相同地址的部署,我们需要准备一个全新的账户用来部署合约.全新的账户指的是在部署合约之前的nonce值为0.因为合约的地址是根据你的账户地址和nonce值计算出来的,所以在不同网络中,如果nonce值相同,部署出的合约地址也相同.

通过助记词生成新账户

参考 BIP32 BIP39 BIP44 助记词 以太坊 账户
使用英文助记词,保存好助记词、对应的账户地址.

向新地址转帐ETH

通过一个已有Ether的账户向新账户转帐.测试网的Ether可以通过每个测试网的水龙头申请到测试币.

  • 获取测试币方法
    转账完成后,将助记词导入到Metamask中

准备WETH合约地址

在部署路由合约时,构造函数中需要填入工厂合约的地址和WETH合约的地址,由于WETH合约的地址在主网和测试网的地址都不相同,所以需要找到每个网络中WETH合约的地址.

WETH合约用于将Eth交换为erc20的Eth,由于Eth不是erc20的token,所以我们必须使用WETH作为交换媒介.

{
    mainnet:'0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2',
    ropsten:'0xc778417E063141139Fce010982780140Aa0cD5Ab',
    rinkeby:'0xc778417E063141139Fce010982780140Aa0cD5Ab',
    goerli:'0xB4FBF271143F4FBf7B91A5ded31805e42b2208d6',
    kovan:'0xd0A1E359811322d97991E03f863a0C30C2cF029C'
}

申请infuraKey

在部署合约之前,我们还需要使用infura作为免费节点,所以需要申请一个infuraKey

  • 申请地址:infura.io

  • 申请方法

配置truffle-congif.js

安装@truffle/hdwallet-provider模块,用于打开助记词的钱包,在项目目录中运行命令:

$ npm install @truffle/hdwallet-provider

如果我们需要在每个网络中都部署上Uniswap合约,就需要配置truffle-congif.js,可以将以下代码全部拷贝粘贴到文件中,覆盖原有代码.修改infuraKeymnemonic助记词

$ vim truffle-config.js 
const HDWalletProvider = require('@truffle/hdwallet-provider');
const infuraKey = "填写infuraKey";
const mnemonic = "填写助记词";
module.exports = {
  networks: {
    mainnet: {
      provider: () => new HDWalletProvider(mnemonic, `https://mainnet.infura.io/v3/` + infuraKey),
      network_id: 1,
      gas: 5500000,
      confirmations: 2,
      timeoutBlocks: 200,
      skipDryRun: true
    },    
    ropsten: {
      provider: () => new HDWalletProvider(mnemonic, `https://ropsten.infura.io/v3/` + infuraKey),
      network_id: 3,
      gas: 5500000,
      confirmations: 2,
      timeoutBlocks: 200,
      skipDryRun: true
    },    
    rinkeby: {
      provider: () => new HDWalletProvider(mnemonic, `https://rinkeby.infura.io/v3/` + infuraKey),
      network_id: 4,
      gas: 5500000,
      confirmations: 2,
      timeoutBlocks: 200,
      skipDryRun: true
    },    
    goerli: {
      provider: () => new HDWalletProvider(mnemonic, `https://goerli.infura.io/v3/` + infuraKey),
      network_id: 5,
      gas: 5500000,
      confirmations: 2,
      timeoutBlocks: 200,
      skipDryRun: true
    },    
    kovan: {
      provider: () => new HDWalletProvider(mnemonic, `https://kovan.infura.io/v3/` + infuraKey),
      network_id: 42,
      gas: 5500000,
      confirmations: 2,
      timeoutBlocks: 200,
      skipDryRun: true
    },
  },
  mocha: {
    // "timeout": 100000,
  },
  compilers: {
    solc: {
      version: "0.5.16",    // Fetch exact version from solc-bin (default: truffle's version)
      // docker: true,        // Use "0.5.1" you've installed locally with docker (default: false)
      // settings: {          // See the solidity docs for advice about optimization and evmVersion
      //  optimizer: {
      //    enabled: false,
      //    runs: 200
      //  },
      //  evmVersion: "byzantium"
      // }
    }
  }
}

部署脚本

在编写truffle的部署脚本之前,先准备一个常用账户作为设置交易所手续费收取账户的管理员地址.
然后在项目目录中运行命令,或者用编辑器创建文件migrations/2_deploy_contract.js

$ vim migrations/2_deploy_contract.js
const UniswapV2Factory = artifacts.require("UniswapV2Factory");
const UniswapV2Router02 = artifacts.require("UniswapV2Router02");
const feeToSetter = '设置手续费账户的管理员地址';
const WETH = {
    mainnet:'0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2',
    ropsten:'0xc778417E063141139Fce010982780140Aa0cD5Ab',
    rinkeby:'0xc778417E063141139Fce010982780140Aa0cD5Ab',
    goerli:'0xB4FBF271143F4FBf7B91A5ded31805e42b2208d6',
    kovan:'0xd0A1E359811322d97991E03f863a0C30C2cF029C'
};
module.exports = (deployer, network, accounts) => {
    // 由于合约版本不对,分开部署
    // deployer.deploy(UniswapV2Factory, feeToSetter).then((FactoryInstance)=>{
    //     return deployer.deploy(UniswapV2Router02,FactoryInstance.address,WETH[network]);
    // });

    //使用 solc vresion 0.5.16
    deployer.deploy(UniswapV2Factory, feeToSetter);

    //使用 solc vresion 0.6.6 
    //将UniswapV2Factory的合约地址替换掉
    deployer.deploy(UniswapV2Router02,'0x4207CD6E113E364220EC08e2Ff446973437859fd',WETH[network]);
    
}

部署合约

在项目目录运行命令:

$ truffle migrate -f 2 --network ropsten

$ truffle migrate -f 2 --network mainnet
$ truffle migrate -f 2 --network rinkeby
$ truffle migrate -f 2 --network goerli
$ truffle migrate -f 2 --network kovan

小知识

module.exports = {
  networks: {
    ropsten: {
      provider: () => new HDWalletProvider(mnemonic, `https://ropsten.infura.io/v3/xxx... infuraKey `),
      network_id: 3,
      gas: 7500000
    },  
  },
}

ropsten网络定义中的provider使用实例化的HDWalletProvider.HDWalletProvider以助记符和期望的网络为参数. Infura主页上提供Infura支持的网络列表.Provider值被封装在一个函数中,这可以确保它在需要之前不会被初始化,如果连接到多个网络,这一点尤为重要. 关于该主题的更多信息,请参阅Truffle文档的网络配置部分.
默认情况下,由助记符产生的第一个账户将负责执行合约迁移任务。 但如果需要的话,你可以传入参数以指定要使用的帐户.例如,要使用第三个帐户:
new HDWalletProvider(mnemonic, "https://ropsten.infura.io/xxx", 2);
账户索引是从零开始的,所以2表示第三个地址.

现在已经将Uniswap的路由合约和工厂合约都部署在所有的网络中了,你可以在控制台的信息中找到两个合约的地址,也可以在以太坊浏览器中找到,在以太坊浏览器中搜索新账户的地址,显示出来的新账户的交易信息中,将会显示两个创建合约的交易,第二个创建的合约是路由合约,将路由合约的地址记录下来,接下来会用到.

部署Uniswap前端

克隆前端代码

在项目目录运行命令:

//克隆前端代码
$ git clone https://github.com/Uniswap/uniswap-interface.git
$ cd uniswap-interface
//安装依赖库
$ yarn
//测试运行一下
$ yarn start

如果运行成功,将会打开一个浏览器,同时打开Uniswap的前端界面.

修改路由地址

在Uniswap的前端中以常量的形式定义了Uniswap的路由地址,我们只需要修改路由地址就可以让前端链接到你的路由合约中
修改文件: 项目目录/uniswap-interface/src/constants/index.ts第6行

import { AbstractConnector } from '@web3-react/abstract-connector'
import { ChainId, JSBI, Percent, Token, WETH } from '@uniswap/sdk'

import { fortmatic, injected, portis, walletconnect, walletlink } from '../connectors'

export const ROUTER_ADDRESS = '0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D' //修改成你的路由合约地址
......

保存后运行yarn start即可看到效果

将代码部署到GitHub Pages

创建GitHub项目

创建项目的方法可以自行baidu

将前端代码添加到GitHub项目仓库

//删除原先Uniswap项目中的.git目录
$ cd uniswap-interface
$ rm -rf .git
//初始化git,并将Unsiwap前端代码添加到自己的项目仓库中
$ git init
$ git add .
$ git commit -m "init"
$ git branch -M main
$ git remote add origin https://github.com/用户名/项目名.git
$ git push -u origin main

安装并部署gh-pages

我们将通过gh-pages模块将前端代码部署到github.io,在前端代码的目录运行:

$ yarn add gh-pages
// 编译react和部署gh-pages
$ yarn build
//修改package.json
$ vim package.json
{
  "name": "@uniswap/interface",
  "description": "Uniswap Interface",
  "homepage": "https://用户名.github.io/项目名称",//修改这里
......

// 添加部署的脚本,还是在package.json中
......
"scripts": {
    ......
    "deploy": "gh-pages -d build" //添加这一行
  },

保存退出之后,在前端代码的目录运行:

$ git add .
$ git commit -m "gh-pages"
$ git push
$ yarn deploy

在浏览器中打开https://用户名.github.io/项目名称/index.html就可以打开自己的交易所啦.
如果不输入地址结尾的index.html在项目刚部署之后会报错,过一段时间就可以不输入了.

扩展

部署自己的weth

可以将以太坊浏览器中的weth源码拷贝下来,自己部署一个属于自己的weth合约

可信token列表

Uniswap有一个自己的可信token列表,同样被设置在项目目录/uniswap-interface/src/constants/index.ts文件中,在最后一行就是.你可以将这个链接地址的文件拷贝下来,设置成自己需要的可信token地址列表,然后上传到github目录中,再修改index.ts文件中的链接地址,这样就可以让你自己的交易所中拥有自己设置的可信token列表了

参考:
手把手教你部署自己的uniswap交易所
truffle 开发笔记(一)
uniswap(v2)接入快速入门总结
defi uniswapV3源代码分析之一 增加流动性add liquidity

你可能感兴趣的:(Defi部署教程 Uniswap部署 搭建去中心化交易所)