空头科学家 -- GMX 交互

Arbitrum Odyssey 第二周的任务开始啦。搞起来!此次的教程是关于GMX的代码交互,希望能对大家有所帮助。

我手动撸过银河小女孩,doctor sol和最近的web3 bnb,是挺枯燥的,但其中有个我愿意做下去的很重要的原因,就是我能通过这些交互式的任务去接触到新的协议和项目。每次看到感兴趣的DEFI项目,我都会去仔细读他们的官方文档,以去了解他们的协议的底层逻辑。这让我兴奋。我现在都记得第一次看到uniswap时,发现还有这种交易模式的喜悦。这次的教程里包含了一点对项目的介绍,和我自己对项目的理解。也希望大家能多去看看这些新的项目,多去支持和拥抱感兴趣的协议。

GMX

  • 去中心化交易所,提供主流代币的杠杆合约交易。
  • 不是自动做市商,没有自己的价格决定机制,价格取决于外部预言机,因此零滑点。
    • 预言机价格 → chainlink + 主流中心化交易所(Binance, FTX and Bitfinex)
  • GLP是GMX发行的一个指数,是平台的流动性提供者代币。GLP池本质上是一个流动性池,用户购买GLP,充当trader的对手方,赚取手续费。
    • 如果GMX上的交易者获利,GLP持有者就会出现亏损,反之亦然。
  • GMX协议通过对交易的开仓和平仓收取费用,以及每隔一小时扣除杠杆头寸的 "借贷费 "来获得收入。
    • 协议收入(ETH) 70% 支付给 GLP持有者,30%支付给GMX质押者。
    • 目前 GLP 的 apr 32.04%,其中包括了 70%的协议收入和 esGMX 奖励。esGMX 可以和普通GMX代币一样质押,或者1年后转换成 GMX。

个人很喜欢这个协议。它提供了2种角色,指数投资者和交易员。两者都能获得其对应的服务。

  • 指数投资者(GLP持有者)除了本身投资指数外,还可以享受额外的70%协议收入(ETH)
  • 交易员可以享受0滑点以及高额杠杆(30x)。

但由于可以开杠杆的量是有GLP所持有的总代币数量决定的,所以资金利用率方面有一定上限。此外,由于GLP持有者为杠杆交易提供流动性,当杠杆交易者出现亏损时,他们将获得利润,反之亦然。所以还有有一定风险的,而整体的风险和币价是正相关的。

Arbitrum Odyssey- GMX任务

下面进入正题,三个任务都要做:

首先我们来理一下逻辑。我们之前通过HOP把ETH 从polygon 跨链到了 Arbiturm。所以我们现在账户上,只有eth资产。因此我们要做的,就是接下来三件事:

  1. 通过swap,把 ETH 换成 USDC
    1. yield protocol 需要 USDC,可以换 50 u。
    2. 用 USDC 比用 ETH 购买GLP更加便宜,可以再多换点。
  2. 开一个杠杆交易的头寸,过一段时间,把它平掉
  3. 用USDC购买 GLP

Contract ABI

我们做交互的底层逻辑,就是去使用这些应用/协议的合约。所以首先要找到合约地址。下面是GMX中,我们需要用的到合约地址,GMX全部地址可以看这个链接

获得地址后,我们要知道怎么才能和合约进行交互。这里就要用到ABI。ABI → Application Binary Interface,应用二进制接口。**ABI决定了我们如何在合同中调用函数并获得数据。**以太坊智能合约是部署在以太坊区块链上的字节码。一个合约中可能有几个函数。通过ABI,我们就可以指定调用合约中的哪个函数,以及我们所期望返回的数据格式。

怎么获得 contract abi

  1. 找到合约地址,例如,Router: 0xaBBc5F99639c9B6bCb58544ddf04EFA6802F4064
  2. 把合约代码复制到remix里面,
    1. 选择合适的compiler。
    2. 点击编译(compile)
    3. 然后复制abi 到 想要的文件夹里面。我们这里是放在abi.json里面的。
  3. 发现 开源合约在 arbiscan.io 最下面直接就有 abi,可以忽略 2了。

SWAP

逻辑和上次用1inch交易是一样的:

  1. 连接钱包
  2. 批准使用代币
  3. 发送交易

我们需要做一些准备工作:

  1. Alchemy注册个账号,申请一个免费的Arbitrum的api_key。
    1. 不懂的去谷歌上搜一搜教程,应该挺多的。
  2. 找到我们要用到的合约地址,复制ABI,并分别存成各自的文件。 上面讲过了。

准备工作做好了,就可以开始撸代码了。首先初始化一些,我们会用到的常量:

  • 由于我们是用ETH换取USDC,所以 tokenIn 是 WETH, tokenOut 是 USDC。
初始化常量
初始化常量

接下来就是 批准代币交易,此时我们要批准WETH。合约的方程都是在合约代码里面能看到的。比如approvedPluginsapprovePlugin ,就可以在router里面查看到。链接进去,点contract,点code,就可以看到了。这里这个合约是开源的,可以看到。不是开源的就得找其他办法了。

下面写了个函数,估计我们能收到多少USDC

接下来就是交易了。可以看到,我设置的minAmountOut是预计能拿到的99%,也就是允许了1%的滑点。

交易
交易

思路

可能有朋友会问,我是怎么找到这些信息的,我的思路从哪里来的?

其实我一般是从结果来思考的。比如如何实现这个swap的脚本?我就先去官方文档看有没有例子。发现并没有代码例子,但是给了合约地址和简单的说明。发现用的是router这个合约,我就去看了一下这些合约上的交易。看到有人执行过SWAP,我就仔细去看了看它调用了什么方程,然后他的输入是什么。比如下面这个例子

我们可以看到他是把WETH换成了USDC。

看input data,就看到了他是调用了 swapETHToTokens 这个函数。再把input data 解析一下,就看到了我们想要的 input 内容,知道我们需要调用swapETHToTokens ,并且传入下图的参数,就可以执行swap了。再去看看具体的合约代码,就知道 swapETHToTokens 到底是在干嘛了。

这里的 _path 就是我们的交易的路径;_minOut 就是我们期待的最小产出,如果低于产出,我们就不会执行交易;_receiver 就是最后收代币的地址。_path_receiver 都是固定的,但_minOut 就不是。那怎么确定_minOut呢?一个简单的逻辑就是设置成以当前价格计价的产出的百分比。官方文档其实是有写 reader 里有一个 getAmountOut函数,可以获得执行前获得互换金额。这样我们就可以让 _minOut = getAmountOut()* 百分比。

Bingo!这样,我们就可以调用 swapETHToTokens 函数,实现代码交互了!

杠杆交易

杠杆交易就稍微复杂点。同样的逻辑,我们去看官方文档。里面有说如何进行杠杆交易。

https://gmxio.gitbook.io/gmx/contracts
https://gmxio.gitbook.io/gmx/contracts

这里的话,我是自己在官网上试了一下,我自己开仓做多ETH的话,发现项目调用的是 PositionRouter 这个合约,然后使用的是createIncreasePositionETH 这个函数。输入值破译后如下图:

具体每个参数的解释,可以看官方文档。这里主要讲一下_acceptablePrice,是指的开仓时接受的最大(多头)或最小(空头)指数价格的美元值。我在Vault.priceFeed找到了提供价格的合约,发现了提供价格的函数 getPrice。所以下面写了一个函数,用来获取当前价格。

接下来就是开仓了,首先准备调用 createIncreasePositionETH 需要用到的参数和输入。其中最近这一天, execution fee 从 0.0006e 变成了 0.002e 又变回了0.0006e,感觉是根据arbitrum 网络拥堵情况决定的。

GMX是真的鸡贼,把
GMX是真的鸡贼,把

amountInsizeDelta 是直接传入的输入。

  • amountIn 是指我们的抵押品的数量(我们这里是ETH的数量)
  • sizeDelta 是指我们想要到达的仓位大小。GMX 规定的是直接 数额 乘以 10^30,遵守就好。
最小抵押品的USD值为10USD
最小抵押品的USD值为10USD

可以看到上图,我们是存入0.01ETH,开仓15美金。假设ETH=1000,存入价值为0.001*1000 = 10美金,开仓15美金,杠杆比例就是1.5。

接下来,我们就批准一下代币使用。

最后调用 createIncreasePositionETH 开仓就好了。

开仓完成后,可以去GMX上看一下,是否有对应的仓位。我试过,没啥问题。开仓的脚本化,就完成了!接下就是平仓。

同样的逻辑,我们在router合约里找到了,平仓用的是createDecreasePosition 这个函数。然后去找找调用了这个函数的交易,破译input。这里官方文档讲的挺详细了,就直接用官方文档了。

和开仓没有什么大的区别。着重讲2个inputs。_collateralDelta 是指要提取的抵押品金额的USD值,因为我们是取eth出来,这里填0就好了。_sizeDelta是指仓位大小变化的USD值。

输入
输入

可以看到 _sizeDelta 我其实是自己写了个 get_position 的函数,从 reader_contract 读取我当前仓位的总值。也就是,我实际执行的是平掉当前的仓位。

下面在获取一下当前的价格,把可接受的价格设置成当前价格的99%,也就是允许1%的滑点。因为是平多仓,所以可接受的价格应该低于当前价格。

接下来就是执行交易了。

Mint GLP

前面有提到,GLP是GMX发行的一个指数,是平台的流动性提供者代币。这里如何 mint GLP 就不继续展开了,大家可以尝试一下,和我交流哈哈。

最后

因为大家的热情,Arbitrum 的 gas fee 被干到了好高,现在Odyssey的任务也暂停了,刚好可以好好学习一下代码交互。

https://dune.com/luigy/Arbitrum-Analytics
https://dune.com/luigy/Arbitrum-Analytics

这个教程大概花了我3天左右的时间(=人工交互1000+个号😂),我也是一步一步自己摸索,不断地试错。但我发现其实,底层逻辑都差不多。第一就是明确要实现什么,然后去协议把整个流程走一遍。懂了用户的交互流程后,就可以去看官方的开发者文档,然后找例子。如果例子不够详细,就自己找合约,找官方的github去看解释,或者看别人或自己的交易记录,去看调用的什么合约,用的什么input,最后写写代码就出来了。当然这里面还有很多学问,包括你对项目背后逻辑的理解等。

如果有什么错误,还望大家能指出来。

合约交互的教程,我就停更在这儿了。后面有兴趣再写。希望能对大家有所帮助。Cheers!


项目代码

参考链接

下面是一些个人链接,欢迎大家关注。

Subscribe to June
Receive the latest updates directly to your inbox.
Mint this entry as an NFT to add it to your collection.
Verification
This entry has been permanently stored onchain and signed by its creator.