Uniswap是基于以太坊的去中心化数字加密货币交易协议,它为代币持有者提供了简洁的接口来将一种ERC20代币兑换为另一种,并且交易所需的gas成本很低。区块链开发者可以自己的ERC20代币接入Uniswap以增强其流动性。在这个教程中,我们将学习如何将一个ERC20代币接入Uniswap协议,并且在教程的最后提供完整的实现源代码。
用自己熟悉的语言学习 以太坊DApp开发 :Java |Php | Python | .Net / C# | Golang | Node.JS | Flutter / Dart
1、Uniswap架构概述
首先我们需要先了解下Uniswap协议的架构,它主要包含两种类型的组件 —— 工厂合约和代币交换合约:
工厂合约/Factory Contract 用于管理代币交换合约,它负责创建新的代币交换合约并维护一个从代币地址到代币交换合约实例的映射表每一种ERC20代币都有自己的 代币交换合约/Exchange Contract,该合约负责完成两种代币的交换。
从开发者角度来看,将一个ERC20代币接入Uniswap协议的流程如下:
- 将ERC20代币协议部署到以太坊网络
- 利用Uniswap的工厂合约为前面部署的ERC20代币创建一个交换合约
- 使用交换合约实现自己的ERC20代币与其他代币的交换
每个代币交换合约智能用来将对应的ERC20代币与以太币交换。为了完成两种不同的ERC20代币的的交换,Uniswap使用以太币作为中间的桥梁,例如,先把Token A换成以太币,再将以太币换成Token B。
值得指出的是,Uniswap协议目前仅支持以太坊,并且只能在同一个以太坊网络上实现ERC20代币的交换。
出于演示目的,在这个教程中我们使用Rinkeby测试网来学习接入流程,在主网上该流程同样适用。教程中的演示代码使用如下的软件栈完成:Truffle v5.0.3
、Node.js v8.11.1
、Web3.js-1.0
。
2、ERC20代币合约开发与部署
首先让我们编写一个简单的ERC20代币合约用于测试:
保存后使用truffle compile
命令编译上述合约:
$ truffle compile
然后修改truffle-config.js
以便连接Rinkeby网络:
rinkeby: {
provider: function() {
return new HDWalletProvider(process.env.NMEMORIC, "https://rinkeby.infura.io/")
},
network_id: '4',
websockets: true,
gas: 6000000,
gasPrice: 10000000000
},
最后使用truffle deploy
命令将合约部署到Rinkeby测试网:
$ truffle deploy --network rinkeby
...
2_token.js
================= Replacing 'Token'
----------------------
> transaction hash: 0xd17a0dc69f54f78aa9a158682dc5bd24c281de959e3a7545ecb7d3c60cdadeab
> Blocks: 0 Seconds: 12
> contract address: 0xCC4d8eCFa6a5c1a84853EC5c0c08Cc54Cb177a6A
> account: 0x0E364EB0Ad6EB5a4fC30FC3D2C2aE8EBe75F245c
> balance: 2.57090605
> gas used: 1214459
> gas price: 10 gwei
> value sent: 0 ETH
> total cost: 0.01214459 ETH > Saving artifacts
-------------------------------------
> Total cost: 0.01214459 ETH
可以看到我们的ERC20代币部署到了Rinkeby测试网的以下地址,当然你的结果应该和这个不一样:
0xCC4d8eCFa6a5c1a84853EC5c0c08Cc54Cb177a6A
3、在Uniswap中创建代币交换合约
Uniswap的工厂合约已经由官方部署到Rinkeby测试网的如下地址:
0xf5d915570bc477f9b8d6c0e980aa81757a3aac36
工厂合约/Factory Contract 的ABI和源代码可以在Etherscan上查看:
为了创建我们的ERC20代币对应的Uniswap代币交换合约,需要调用Uniswap部署的工厂合约的createExchange()
方法。例如,在下面的代码中我们使用Infura来发送一个对该方法调用的签名交易:
用node.js运行上述代码即可:
$ node 1.create.exchange.js
运行结果类似如下内容:
注意,如果运行时提示错误如下错误信息:
Node error:{"code":-32601, "message": "The method eth_sendTransaction does not exist/is not available"},
表示Infura不支持eth_sendTransaction方法,也就是说你只能向Infura提交签名交易,而无法要求Infura帮你签名。
现在我们的ERC20代币的交换合约已经在Uniswap内部创建完成了。现在我们可以使用如下命令来查询这个合约的部署地址:
script/2.get.exchange.address.js
输出结果如下:
同样使用node.js运行:
$ node script/2.get.exchange.address.js
the exchange address for ERC20 token is: 0x416F1Ac032D1eEE743b18296aB958743B1E61E81
这表明我们已经为自己的ERC20代币合约成功创建了Uniswap交换协议。
4、为Uniswap代币交换协议添加流动性
现在我们可以访问代币交换协议了。下面是我们要用到的重要的合约地址:
- 我们的ERC20代币合约地址: 0xCC4d8eCFa6a5c1a84853EC5c0c08Cc54Cb177a6A
- Uniswap交换合约地址:0x416F1Ac032D1eEE743b18296aB958743B1E61E81
Uniswap代币交换合约需要预存一些代币以便提供初始的流动性。为此,我们首先需要授权代币交换合约可以操作我们钱包中的ERC20代币,然后再调用代币交换合约的addLiquidity()
方法同时存入ERC20代币和以太币:
- token.approve(exchange_address, TOKEN_RESERVE)
- exchange.addLiquidity(0, TOKEN_RESERVE, DEADLINE, transact={'value': ETH_RESERVE})
首先,我们运行命令$node cript/3.approve.exchange.js
来授权代币交换合约存取 我们的钱包地址上的ERC20代币:
接下来,我们运行命令 $node script/4.add.liquidity.js
向代币交换合约存入15个ERC20代币和0.1个以太币以便提供初始的流动性:
可以用etherscan来检查验证合约的账户余额:
5、用Uniswap实现去中心化交易
现在我们可以用Uniswap来实现以太币/ERC20代币或者两种ERC20代币之间的交换了。
在第一个测试中,我们将以太币发送给Uniswap代币交换合约,这会自动转换为ERC20代币,你可以执行命令$node script/5.eth2erc20.swap.js
进行测试,代码如下:
在Etherscan上可以看到已经存入Uniswap代币交换合约0.05个以太币,并且转化为5个ERC20代币发送回买家的钱包:
在第二个测试中,我们尝试交换两种不同的ERC20代币,例如将LINK代币转化为我们部署的ERC20代币:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rEbU0yMO-1593388918029)(uniswap-developer-guide/erc20-swap-code.jpeg)]
在上面的代码中,我们存入10个LINK代币并得到0.0015个自己部署的代币:
6、结论
在这个教程中,我们学习了如何创建一个ERC20代币并将其接入Uniswap去中心化交换协议以便增减这个代币的流动性。你可以在这里下载完整的实验代码:https://github.com/oceanprotocol/Nautilus/tree/master/3-uniswap 。
原文链接:Uniswap接入开发指南 — 汇智网