Arbitrum Odyssey 第二周的任务开始啦。搞起来!此次的教程是关于GMX的代码交互,希望能对大家有所帮助。
我手动撸过银河小女孩,doctor sol和最近的web3 bnb,是挺枯燥的,但其中有个我愿意做下去的很重要的原因,就是我能通过这些交互式的任务去接触到新的协议和项目。每次看到感兴趣的DEFI项目,我都会去仔细读他们的官方文档,以去了解他们的协议的底层逻辑。这让我兴奋。我现在都记得第一次看到uniswap时,发现还有这种交易模式的喜悦。这次的教程里包含了一点对项目的介绍,和我自己对项目的理解。也希望大家能多去看看这些新的项目,多去支持和拥抱感兴趣的协议。
GLP
是GMX发行的一个指数,是平台的流动性提供者代币。GLP
池本质上是一个流动性池,用户购买GLP
,充当trader的对手方,赚取手续费。
GLP
持有者,30%支付给GMX
质押者。GLP
的 apr 32.04%,其中包括了 70%的协议收入和 esGMX
奖励。esGMX
可以和普通GMX代币一样质押,或者1年后转换成 GMX。个人很喜欢这个协议。它提供了2种角色,指数投资者和交易员。两者都能获得其对应的服务。
GLP
持有者)除了本身投资指数外,还可以享受额外的70%协议收入(ETH)但由于可以开杠杆的量是有GLP所持有的总代币数量决定的,所以资金利用率方面有一定上限。此外,由于GLP
持有者为杠杆交易提供流动性,当杠杆交易者出现亏损时,他们将获得利润,反之亦然。所以还有有一定风险的,而整体的风险和币价是正相关的。
下面进入正题,三个任务都要做:
首先我们来理一下逻辑。我们之前通过HOP把ETH 从polygon 跨链到了 Arbiturm。所以我们现在账户上,只有eth资产。因此我们要做的,就是接下来三件事:
我们做交互的底层逻辑,就是去使用这些应用/协议的合约。所以首先要找到合约地址。下面是GMX中,我们需要用的到合约地址,GMX全部地址可以看这个链接。
获得地址后,我们要知道怎么才能和合约进行交互。这里就要用到ABI。ABI → Application Binary Interface,应用二进制接口。**ABI决定了我们如何在合同中调用函数并获得数据。**以太坊智能合约是部署在以太坊区块链上的字节码。一个合约中可能有几个函数。通过ABI,我们就可以指定调用合约中的哪个函数,以及我们所期望返回的数据格式。
abi.json
里面的。逻辑和上次用1inch交易是一样的:
我们需要做一些准备工作:
准备工作做好了,就可以开始撸代码了。首先初始化一些,我们会用到的常量:
接下来就是 批准代币交易,此时我们要批准WETH。合约的方程都是在合约代码里面能看到的。比如approvedPlugins
和 approvePlugin
,就可以在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
函数,实现代码交互了!
杠杆交易就稍微复杂点。同样的逻辑,我们去看官方文档。里面有说如何进行杠杆交易。
这里的话,我是自己在官网上试了一下,我自己开仓做多ETH的话,发现项目调用的是 PositionRouter 这个合约,然后使用的是createIncreasePositionETH
这个函数。输入值破译后如下图:
具体每个参数的解释,可以看官方文档。这里主要讲一下_acceptablePrice
,是指的开仓时接受的最大(多头)或最小(空头)指数价格的美元值。我在Vault.priceFeed
找到了提供价格的合约,发现了提供价格的函数 getPrice
。所以下面写了一个函数,用来获取当前价格。
接下来就是开仓了,首先准备调用 createIncreasePositionETH
需要用到的参数和输入。其中最近这一天, execution fee 从 0.0006e 变成了 0.002e 又变回了0.0006e,感觉是根据arbitrum 网络拥堵情况决定的。
amountIn
和 sizeDelta
是直接传入的输入。
amountIn
是指我们的抵押品的数量(我们这里是ETH的数量)sizeDelta
是指我们想要到达的仓位大小。GMX 规定的是直接 数额 乘以 10^30,遵守就好。可以看到上图,我们是存入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%的滑点。因为是平多仓,所以可接受的价格应该低于当前价格。
接下来就是执行交易了。
前面有提到,GLP
是GMX发行的一个指数,是平台的流动性提供者代币。这里如何 mint GLP 就不继续展开了,大家可以尝试一下,和我交流哈哈。
因为大家的热情,Arbitrum 的 gas fee 被干到了好高,现在Odyssey的任务也暂停了,刚好可以好好学习一下代码交互。
这个教程大概花了我3天左右的时间(=人工交互1000+个号😂),我也是一步一步自己摸索,不断地试错。但我发现其实,底层逻辑都差不多。第一就是明确要实现什么,然后去协议把整个流程走一遍。懂了用户的交互流程后,就可以去看官方的开发者文档,然后找例子。如果例子不够详细,就自己找合约,找官方的github去看解释,或者看别人或自己的交易记录,去看调用的什么合约,用的什么input,最后写写代码就出来了。当然这里面还有很多学问,包括你对项目背后逻辑的理解等。
如果有什么错误,还望大家能指出来。
合约交互的教程,我就停更在这儿了。后面有兴趣再写。希望能对大家有所帮助。Cheers!
下面是一些个人链接,欢迎大家关注。