教程: 利用Gelato搭建自动Uniswap交易

如何使用 Gelato 来执行定时交易

[Gelato](https://gelato.network/)用来帮助开发人员自动执行智能合约的工具。 我们都知道,以太坊上的智能合约无法定时执行任务,但是经常有这样的需求场景,例如 DEFI 合约需要定时给合约喂价。 实现定时任务常用的做法是编写一个执行合约交易脚本,然后使用外部定时任务去运行脚本,使用 Gelato 一个显而易见的优势是可以避免单点失败以及节约开发时间。 本教程以每2分钟自动在Uniswap上将DAI交换为ETH为示例, 学习悉如何使用Gelato构建自动执行的交易。 > 2分钟知识方便开发验证的时间,如果你看开发一个以太坊定投,可以按修改为一周或二周。 ![giphy.webp](https://img.learnblockchain.cn/attachments/2020/11/d5Cru97j5fa4b007f2eeb.webp) ## 项目创建 ### 环境准备 项目是基于node.js开发,因此需要我们先安装: - `node.js` - `yarn`(或`npm`) ### 克隆项目代码 Gelato 提供了教程的源码,把代码克隆到本地,并安装好相应的依赖库: ```bash git clone https://github.com/gelatodigital/gelato-uniswap.git cd gelato-uniswap yarn install # or npm install ``` > 有些版本的`node`可能会提示一些`gyp-error`错误,没关系。 ### 配置Infura Key及私钥 自动任务需要和进行链上的 Uniswap 交易,我们使用[Infura](https://learnblockchain.cn/article/1590)和节点通信,另外还需要用到用户私钥(用来支付),通常这类的私密信息放在不被代码管理的 .env 文件中(`.env`加到`.g​​itignore`): 在项目根目录下添加一个.env文件: ```bash touch .env ``` 将以下变量添加到.env文件中。 ``` DEMO_INFURA_ID="输入你的在 Infura 申请的 Project ID" DEMO_USER_PK="填入地址私钥,0x 先开头" DEMO_PROVIDER_PK="填入提供者私钥(用来代替用户付费,本文暂时不需要)" ``` [从这里](https://infura.io/) 你可以免费获得`DEMO_INFURA_ID` ,如果遇到问题,可查看[教程](https://blog.infura.io/getting-started-with-infura-28e41844cc89/)。 获取DEMO_USER_PK和DEMO_PROVIDER_PK 私钥的一种方法是安装Metamask并按照此[教程](https://metamask.zendesk.com/hc/en-us/articles/360015289632-How-to-Export-an-Account-Private-Key)导出所选地址的私钥,注意填入的的私钥需要以`0x`前缀。 此外,还需要为帐户存入一下ETH以便发起交易,`用户`钱包还需要存入一些 DAI 。 因为Demo 是基于`Rinkeby`进行开发的, ETH 可以从[水龙头](https://faucet.rinkeby.io/) 获取到,为了防止交易失败,最好将至少2 ETH存入与DEMO_USER_PK关联的帐户: 在用户钱包中包含ETH之后,运行以下命令可以获取100 个 Rinkeby DAI: ``` yarn get-dai ``` ## Gelato 是如何运作的 在使用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 任务](https://learnblockchain.cn/article/1356)来执行的。 Buidler 任务会使用到.env提供的`DEMO_USER_PK`作为钱包,再次确保账号下有Rinkeby ETH和DAI。 在我们的 Demo 为了可以更清楚地了解每一步发生了什么,才拆分为一个个步骤,在实际开发中,很多步骤可以合并在一起。 ### 1. 创建代理合约钱包 为了能够使用Gelato在Uniswap上执行交易,我们需要一个代理合约钱包,来代理用户与Gelato协议进行交互。可以将Gelato视作为一个模块,可以集成到任何智能合约里(包括智能合约钱包: 例如Gnosis Safe,dsProxy等),从而使这些合约可以在将来某个时候(满足指定条件,例如从现在开始的一天)执行交易。 在Demo中,为简单起见,使用Gelato 官方案例提供的[`GelatoUserProxy`](https://github.com/gelatodigital/gelato-uniswap/blob/master/contracts/user_proxies/GelatoUserProxy.sol)作为代理合约钱包。从理论上讲,可以使用任何智能合约代理,例如`GnosisSafe`或`Maker`的`DSProxy`。 运行以下命令部署 `GelatoUserProxy` 合约: ```bash yarn create-userproxy ``` 该命令会执行[`demo/Part-1_Gelato_User/step1-create-user-proxy.js`](https://github.com/gelatodigital/gelato-uniswap/blob/master/demo/Part-1_Gelato_User/step1-create-user-proxy.js)部署任务脚本,在部署脚本中, 是通过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 件事,运行以下脚本: ```bash yarn userproxy-setup ``` 该命令会执行[`demo/Part-1_Gelato_User/step2-user-proxy-setup.js`](https://github.com/gelatodigital/gelato-uniswap/blob/master/demo/Part-1_Gelato_User/step2-user-proxy-setup.js) 脚本,脚本里通过 `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兑换WETH** `Condition`条件会由GelatoCore智能合约检查,并在满足条件的区块上执行任务。 动作是其他智能合约要运行的某些逻辑,将由用户GelatoUserProxy检查或执行。你可以编写自己的`Condition`或`Action`合约,并将其与gelato一起使用,也可以像本教程中一样,使用现有的合约。 看看我们 Demo 的任务: ```js new Task({ conditions: [conditionEvery2minutes], // 条件 // 包含的动作,所有动作在一个交易完成(要么都失败) actions: [ actionTransferFrom, actionApproveUniswapRouter, actionSwapTokensUniswap, actionUpdateConditionTime, ], selfProviderGasLimit: estimatedGasPerExecution, // gas Limit selfProviderGasPriceCeil: 0, // gas 价格上限,0表示不在意价格 }); ``` 任务包含的4 个动作:转账、授权、Uniswap交易、更新时间,我们看一下核心的Uniswap交易动作: ```js 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`](https://github.com/gelatodigital/gelato-uniswap/blob/master/demo/Part-1_Gelato_User/step3-submit-task-uniswap.js) > 如果你有兴趣的话,还可以看看对应条件合约及执行动作合约: > **Condition合约:** [`contracts/gelato_conditions/ConditionTimeStateful.sol`](https://github.com/gelatodigital/gelato-uniswap/blob/master/contracts/gelato_conditions/ConditionTimeStateful.sol) > **Action合约:** 动作由[Uniswap V2 Router2](https://etherscan.io/address/0x7a250d5630b4cf539739df2c5dacb4c659f2488d) 合约执行 执行以下命令提交任务: ```bash yarn submit-task-uniswap-self-provider-and-monitor ``` 执行这个脚本会发送2个交易: 1. `approve(授权)`代理合约`GelatoUserProxy`可以转移3 DAI,因为之后代理合约要使用 Dai在uniswap上交易。 2. 将`任务`提交`GelatoCore.sol`,它定义了从现在开始每2分钟在uniswap上进行交易。 我们可以在Metmask或Etherscan上查看你的`USER`帐户余额中的`DAI`和`WETH`来确认交易是否执行,记得是在Rinkeby网络上哦。 我们也可以使用demo 提供的[demo/Part-1_Gelato_User/monitorBalanceChanges.js](https://github.com/gelatodigital/gelato-uniswap/blob/master/demo/Part-1_Gelato_User/monitorBalanceChanges.js) 来监听余额的变化: ```bash 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余额撤回其钱包,运行以下脚本: ```bash yarn withdraw-remaining-eth ``` 对应的脚本为:[`demo/Part-1_Gelato_User/step4-withdraw-remaining-eth.js`](https://github.com/gelatodigital/gelato-uniswap/blob/master/demo/Part-1_Gelato_User/step4-withdraw-remaining-eth.js),有兴趣可以查看。 到这里,这部分教程就完成了,你应该了解了如何使用 Gelato 来执行定时交易。 ## 接下来 在一些场景下,上述用户体验可能不够友好,因为它要求用户提前将ETH存入Gelato上,然后Gelato才能执行其任务。前面描述了另一种Gelato提供者:`外部提供者`,可以代表用户为交易付费,因此用户不必存款,从而创造出了更好的用户体验,我们在之后的文章再介绍。 ------ 本文由 [Cell Network](https://www.cellnetwork.io/?utm_souce=learnblockchain) 赞助支持。

Gelato用来帮助开发人员自动执行智能合约的工具。

我们都知道,以太坊上的智能合约无法定时执行任务,但是经常有这样的需求场景,例如 DEFI 合约需要定时给合约喂价。

实现定时任务常用的做法是编写一个执行合约交易脚本,然后使用外部定时任务去运行脚本,使用 Gelato 一个显而易见的优势是可以避免单点失败以及节约开发时间。

本教程以每2分钟自动在Uniswap上将DAI交换为ETH为示例, 学习悉如何使用Gelato构建自动执行的交易。

2分钟知识方便开发验证的时间,如果你看开发一个以太坊定投,可以按修改为一周或二周。

教程: 利用Gelato搭建自动Uniswap交易插图

项目创建

环境准备

项目是基于node.js开发,因此需要我们先安装:

  • node.js
  • yarn(或npm)

克隆项目代码

Gelato 提供了教程的源码,把代码克隆到本地,并安装好相应的依赖库:

git clone https://github.com/gelatodigital/gelato-uniswap.git

cd gelato-uniswap

yarn install  # or npm install

有些版本的node可能会提示一些gyp-error错误,没关系。

配置Infura Key及私钥

自动任务需要和进行链上的 Uniswap 交易,我们使用Infura和节点通信,另外还需要用到用户私钥(用来支付),通常这类的私密信息放在不被代码管理的 .env 文件中(.env加到.g​​itignore):

在项目根目录下添加一个.env文件:

touch .env

将以下变量添加到.env文件中。

DEMO_INFURA_ID="输入你的在 Infura 申请的 Project ID"
DEMO_USER_PK="填入地址私钥,0x 先开头"
DEMO_PROVIDER_PK="填入提供者私钥(用来代替用户付费,本文暂时不需要)"

从这里 你可以免费获得DEMO_INFURA_ID ,如果遇到问题,可查看教程。

获取DEMO_USER_PK和DEMO_PROVIDER_PK 私钥的一种方法是安装Metamask并按照此教程导出所选地址的私钥,注意填入的的私钥需要以0x前缀。

此外,还需要为帐户存入一下ETH以便发起交易,用户钱包还需要存入一些 DAI 。 因为Demo 是基于Rinkeby进行开发的, ETH 可以从水龙头 获取到,为了防止交易失败,最好将至少2 ETH存入与DEMO_USER_PK关联的帐户:

在用户钱包中包含ETH之后,运行以下命令可以获取100 个 Rinkeby DAI:

yarn get-dai

Gelato 是如何运作的

在使用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 任务来执行的。 Buidler 任务会使用到.env提供的DEMO_USER_PK作为钱包,再次确保账号下有Rinkeby ETH和DAI。

在我们的 Demo 为了可以更清楚地了解每一步发生了什么,才拆分为一个个步骤,在实际开发中,很多步骤可以合并在一起。

1. 创建代理合约钱包

为了能够使用Gelato在Uniswap上执行交易,我们需要一个代理合约钱包,来代理用户与Gelato协议进行交互。可以将Gelato视作为一个模块,可以集成到任何智能合约里(包括智能合约钱包: 例如Gnosis Safe,dsProxy等),从而使这些合约可以在将来某个时候(满足指定条件,例如从现在开始的一天)执行交易。

在Demo中,为简单起见,使用Gelato 官方案例提供的GelatoUserProxy作为代理合约钱包。从理论上讲,可以使用任何智能合约代理,例如GnosisSafeMakerDSProxy

运行以下命令部署 GelatoUserProxy 合约:

yarn create-userproxy

该命令会执行demo/Part-1_Gelato_User/step1-create-user-proxy.js部署任务脚本,在部署脚本中, 是通过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 脚本,脚本里通过 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兑换WETH

Condition条件会由GelatoCore智能合约检查,并在满足条件的区块上执行任务。

动作是其他智能合约要运行的某些逻辑,将由用户GelatoUserProxy检查或执行。你可以编写自己的ConditionAction合约,并将其与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

如果你有兴趣的话,还可以看看对应条件合约及执行动作合约: Condition合约: contracts/gelato_conditions/ConditionTimeStateful.sol Action合约: 动作由Uniswap V2 Router2 合约执行

执行以下命令提交任务:

yarn submit-task-uniswap-self-provider-and-monitor

执行这个脚本会发送2个交易:

  1. approve(授权)代理合约GelatoUserProxy可以转移3 DAI,因为之后代理合约要使用 Dai在uniswap上交易。

  2. 任务提交GelatoCore.sol,它定义了从现在开始每2分钟在uniswap上进行交易。

我们可以在Metmask或Etherscan上查看你的USER帐户余额中的DAIWETH来确认交易是否执行,记得是在Rinkeby网络上哦。

我们也可以使用demo 提供的demo/Part-1_Gelato_User/monitorBalanceChanges.js 来监听余额的变化:

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,有兴趣可以查看。

到这里,这部分教程就完成了,你应该了解了如何使用 Gelato 来执行定时交易。

接下来

在一些场景下,上述用户体验可能不够友好,因为它要求用户提前将ETH存入Gelato上,然后Gelato才能执行其任务。前面描述了另一种Gelato提供者:外部提供者,可以代表用户为交易付费,因此用户不必存款,从而创造出了更好的用户体验,我们在之后的文章再介绍。

本文由 Cell Network 赞助支持。

区块链技术网。

  • 发表于 2020-11-05 18:27
  • 阅读 ( 2119 )
  • 学分 ( 252 )
  • 分类:以太坊

评论