利用Gelato搭建自动Uniswap交易
Gelato[1]用来帮助开发人员自动执行智能合约的工具。我们都知道,以太坊上的智能合约无法定时执行任务,但是经常有这样的需求场景,例如 defi 合约需要定时给合约喂价。实现定时任务常用的做法是编写一个执行合约交易脚本,然后使用外部定时任务去运行脚本,使用 Gelato 一个显而易见的优势是可以避免单点失败以及节约开发时间。本教程以每 2 分钟自动在 Uniswap 上将 DAI 交换为 ETH 为示例, 学习悉如何使用 Gelato 构建自动执行的交易。
2 分钟知识方便开发验证的时间,如果你看开发一个以太坊定投,可以按修改为一周或二周。
项目创建环境准备项目是基于 node.js 开发,因此需要我们先安装:· node.js· yarn(或npm)克隆项目代码Gelato 提供了教程的源码,把代码克隆到本地,并安装好相应的依赖库:git clone https://github.com/gelatodigital/gelato-UNIswap.gitcd gelato-uniswapyarn install # or npm install有些版本的node可能会提示一些gyp-error错误,没关系。配置 Infura Key 及私钥自动任务需要和进行链上的 Uniswap 交易,我们使用Infura[2]和节点通信,另外还需要用到用户私钥(用来支付),通常这类的私密信息放在不被代码管理的 .env 文件中(.env加到.gitignore):在项目根目录下添加一个.env 文件:touch .env将以下变量添加到.env 文件中。DEMO_INFURA_ID="输入你的在 Infura 申请的 Project ID"DEMO_USER_PK="填入地址私钥,0x 先开头"DEMO_PROVIDER_PK="填入提供者私钥(用来代替用户付费,本文暂时不需要)"从这里[3] 你可以免费获得DEMO_INFURA_ID ,如果遇到问题,可查看教程[4]。获取 DEMO_USER_PK 和 DEMO_PROVIDER_PK 私钥的一种方法是安装 Metamask 并按照此教程[5]导出所选地址的私钥,注意填入的的私钥需要以0x前缀。此外,还需要为帐户存入一下 ETH 以便发起交易,用户钱包还需要存入一些 DAI 。因为 Demo 是基于Rinkeby进行开发的, ETH 可以从水龙头[6] 获取到,为了防止交易失败,最好将至少 2 ETH 存入与 DEMO_USER_PK 关联的帐户:在用户钱包中包含 ETH 之后,运行以下命令可以获取 100 个 Rinkeby DAI:yarn get-daiGelato 是如何运作的在使用 Gelato 之前,先简单介绍一下 Gelato 的运作原理。Gelato 由一个中继服务器网络组成,这些网络的执行者(Executors)被激励为 Dapp 用户执行某些任务(Task)。“我们”需要为这些执行者(Executors)付费,以便运行自动化基础架构,并代表你的用户提交将来的交易。在 Gelato 上,付费的主体(上一句话的我们)称为Gelato Providers(提供者),需要预先存入 ETH,以在满足预定条件时通过提交交易来支付执行者以执行任务。有两种Gelato Providers:1. 自我提供者(Self-Providers)是最终用户或 Dapps 自己,他们直接向执行者支付费用,因此必须先将 ETH 存入 Gelato 再使用。他们自己为将来的交易付费,前面.env 中的 DEMO_USER_PK 就是用来作为自我提供者,2. 外部提供者(External Providers),可以代 Dapp 用户向执行者付款。例如,这些是 dapp 开发人员或 DAO,他们希望为用户提供出色的 UX,而代替用户在 Gelato 上存款。前面.env 中的 DEMO_PROVIDER_PK 就是用来作为外部提供者。在本教程中,如果作为自助提供者,自行支付执行者费用。在之后的文章,将介绍切换成为外部提供者角色。Gelato 使用详解现在到有趣的部分,在实践中体验 Gelato,体验使用 gelato 作为自动执行交易。我们的 Demo 会每2分钟在Uniswap上自动用DAI购买WETH,总共进行3笔交易。在 Demo 中与 Gelato 的交易是通过 Buidler 任务[7]来执行的。Buidler 任务会使用到.env 提供的DEMO_USER_PK作为钱包,再次确保账号下有 Rinkeby ETH 和 DAI。在我们的 Demo 为了可以更清楚地了解每一步发生了什么,才拆分为一个个步骤,在实际开发中,很多步骤可以合并在一起。1. 创建代理合约钱包为了能够使用 Gelato 在 Uniswap 上执行交易,我们需要一个代理合约钱包,来代理用户与 Gelato 协议进行交互。可以将 Gelato 视作为一个模块,可以集成到任何智能合约里(包括智能合约钱包: 例如 Gnosis Safe,dsProxy 等),从而使这些合约可以在将来某个时候(满足指定条件,例如从现在开始的一天)执行交易。在 Demo 中,为简单起见,使用 Gelato 官方案例提供的`GelatoUserProxy`[8]作为代理合约钱包。从理论上讲,可以使用任何智能合约代理,例如GnosisSafe或Maker的DSProxy。运行以下命令部署 GelatoUserProxy 合约:yarn create-userproxy该命令会执行`demo/Part-1_Gelato_User/step1-create-user-proxy.js`[9]部署任务脚本,在部署脚本中, 是通过 Gelato 已经部署好的 GelatoUserProxyFactory来部署GelatoUserProxy合约。2. 在 gelato 上预存 ETH,选择 gelato 执行者,并告诉 gelato 用户拥有哪种代理为了使新创建的用户代理与 Gelato 交互,还需要做一些配置:1. 需要在 Gelato 上存入一些 ETH,以支付执行者费用;2. 选择默认的 Gelato 执行者网络;3. 告诉 Gelato 需要与哪种智能合约(在本例中为 Proxy)交互。Gelato 可以与任何智能合约一起使用,它与代理标准无关,可以与任何智能合约代理标准(例如 Gnosis Safe,dsProxy,GelatoUser Proxy 等)一起使用。确保用户帐户中有足够的 ETH(1 ETH 以上)。为了完成上面的 3 件事,运行以下脚本:yarn userproxy-setup该命令会执行`demo/Part-1_Gelato_User/step2-user-proxy-setup.js`[10] 脚本,脚本里通过 GelatoUserProxy 合约向 GelatoCore 发起一个初始化Action(动作 - 下面介绍)完成配置,可以查看源码,探究细节。3. 通过代理合约钱包将任务提交给 Gelato在 Demo 中,想要让 Gelato 代表我们执行 3 笔交易(称为 Task),每笔交易每 2 分钟用 1 个 DAI 去兑换 ETH。Gelato Task(任务)只是Conditions(条件 - 什么时候执行交易) 和Actions(动作 - 交易应执行什么)的组合。在本 Demo,只有一个用于跟踪时间的条件和一个在 Uniswap 上进行交易的动作。但是,也可以根据需要将多个条件与多个动作组合为一个任务。在这里,定义Task(任务)为:· Condition(条件):每 2 分钟(或每次在以太坊上达到某个时间戳记时)· Action(动作):在 Uniswap 上用 1 DAI 兑换 WETH(调用 uniswap 智能合约上的交易函数)· Task(任务):每 2 分钟,在 Uniswap 上用 1 DAI 兑换 WETHCondition条件会由 GelatoCore 智能合约检查,并在满足条件的区块上执行任务。动作是其他智能合约要运行的某些逻辑,将由用户 GelatoUserProxy 检查或执行。你可以编写自己的Condition或Action合约,并将其与 gelato 一起使用,也可以像本教程中一样,使用现有的合约。看看我们 Demo 的任务:new Task({ conditions: [conditionEvery2minutes], // 条件 // 包含的动作,所有动作在一个交易完成(要么都失败) actions: [ actionTransferFrom, actionApproveUniswapRouter, actionSwapTokensUniswap, actionUpdateConditionTime, ], selfProviderGasLimit: estimatedGasPerExecution, // gas Limit selfProviderGasPriceCeil: 0, // gas 价格上限,0表示不在意价格 });任务包含的 4 个动作:转账、授权、Uniswap 交易、更新时间,我们看一下核心的 Uniswap 交易动作: const actionSwapTokensUniswap = new Action({ addr: UNISWAP_V2_Router_02, data: await bre.run("abi-encode-withselector", { contractname: "IUniswapV2Router02", functionname: "swapExactTokensForTokens", inputs: [DAI_AMOUNT_PER_TRADE, 0, tokenPath, myUserAddress, 4102448461], }), operation: Operation.Call, // This Action must be executed via the UserProxy });完整的任务和动作定义,可以查看代码:`demo/Part-1_Gelato_User/step3-submit-task-uniswap.js`[11]如果你有兴趣的话,还可以看看对应条件合约及执行动作合约:Condition 合约:`contracts/gelato_conditions/ConditionTimeStateful.sol`[12] > Action 合约:动作由Uniswap V2 Router2[13] 合约执行执行以下命令提交任务:yarn submit-task-uniswap-self-provider-and-monitor执行这个脚本会发送 2 个交易:· approve(授权)代理合约GelatoUserProxy可以转移 3 DAI,因为之后代理合约要使用 Dai 在 uniswap 上交易。· 将任务提交GelatoCore.sol,它定义了从现在开始每 2 分钟在 uniswap 上进行交易。我们可以在 Metmask 或 Etherscan 上查看你的USER帐户余额中的DAI和WETH来确认交易是否执行,记得是在 Rinkeby 网络上哦。我们也可以使用 demo 提供的demo/Part-1_Gelato_User/monitorBalanceChanges.js[14] 来监听余额的变化:yarn monitor-balances这样在定义任务交易执行时,可以在控制台看到打印出交易日志,类似下面: ___ Current Token BALANCES! ____ myUserWallet ETH Balance: 0.97978682 ETH myUserWallet DAI Balance: 99.0 DAI myUserWallet DAI Allowance: 2.0 DAI全部交易大概要 7 分钟完成。4. (可选) 将剩余的 ETH 取回“用户钱包”要将用户的剩余 ETH 余额撤回其钱包,运行以下脚本:yarn withdraw-remaining-eth对应的脚本为:`demo/Part-1_Gelato_User/step4-withdraw-remaining-eth.js`[15],有兴趣可以查看。到这里,这部分教程就完成了,你应该了解了如何使用 Gelato 来执行定时交易。接下来在一些场景下,上述用户体验可能不够友好,因为它要求用户提前将 ETH 存入 Gelato 上,然后 Gelato 才能执行其任务。前面描述了另一种 Gelato 提供者:外部提供者,可以代表用户为交易付费,因此用户不必存款,从而创造出了更好的用户体验,我们在之后的文章再介绍。
微信扫描关注公众号,及时掌握新动向
2.本文版权归属原作所有,仅代表作者本人观点,不代表比特范的观点或立场
2.本文版权归属原作所有,仅代表作者本人观点,不代表比特范的观点或立场