# 空头科学家 -- GMX 交互 **Published by:** [June](https://paragraph.com/@june023/) **Published on:** 2022-06-29 **URL:** https://paragraph.com/@june023/gmx ## Content 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任务下面进入正题,三个任务都要做:在 https://gmx.io/trade 开一个杠杆交易的头寸在https://gmx.io/trade 上做交易在 https://gmx.io/buy 网站上进行 Mint GLP首先我们来理一下逻辑。我们之前通过HOP把ETH 从polygon 跨链到了 Arbiturm。所以我们现在账户上,只有eth资产。因此我们要做的,就是接下来三件事:通过swap,把 ETH 换成 USDCyield protocol 需要 USDC,可以换 50 u。用 USDC 比用 ETH 购买GLP更加便宜,可以再多换点。开一个杠杆交易的头寸,过一段时间,把它平掉用USDC购买 GLPContract ABI我们做交互的底层逻辑,就是去使用这些应用/协议的合约。所以首先要找到合约地址。下面是GMX中,我们需要用的到合约地址,GMX全部地址可以看这个链接。Router: 0xaBBc5F99639c9B6bCb58544ddf04EFA6802F4064Reader: 0x22199a49A999c351eF7927602CFB187ec3cae489PositionRouter: 0x3D6bA331e3D9702C5e8A8d254e5d8a285F223abaVault: 0x489ee077994B6658eAfA855C308275EAd8097C4AVaultPriceFeed: 0xa18bb1003686d0854ef989bb936211c59eb6e363获得地址后,我们要知道怎么才能和合约进行交互。这里就要用到ABI。ABI → Application Binary Interface,应用二进制接口。**ABI决定了我们如何在合同中调用函数并获得数据。**以太坊智能合约是部署在以太坊区块链上的字节码。一个合约中可能有几个函数。通过ABI,我们就可以指定调用合约中的哪个函数,以及我们所期望返回的数据格式。怎么获得 contract abi找到合约地址,例如,Router: 0xaBBc5F99639c9B6bCb58544ddf04EFA6802F4064把合约代码复制到remix里面,选择合适的compiler。点击编译(compile)然后复制abi 到 想要的文件夹里面。我们这里是放在abi.json里面的。发现 开源合约在 arbiscan.io 最下面直接就有 abi,可以忽略 2了。SWAP逻辑和上次用1inch交易是一样的:连接钱包批准使用代币发送交易我们需要做一些准备工作:去Alchemy注册个账号,申请一个免费的Arbitrum的api_key。不懂的去谷歌上搜一搜教程,应该挺多的。找到我们要用到的合约地址,复制ABI,并分别存成各自的文件。 上面讲过了。准备工作做好了,就可以开始撸代码了。首先初始化一些,我们会用到的常量:由于我们是用ETH换取USDC,所以 tokenIn 是 WETH, tokenOut 是 USDC。初始化常量接下来就是 批准代币交易,此时我们要批准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 函数,实现代码交互了!杠杆交易杠杆交易就稍微复杂点。同样的逻辑,我们去看官方文档。里面有说如何进行杠杆交易。https://gmxio.gitbook.io/gmx/contracts这里的话,我是自己在官网上试了一下,我自己开仓做多ETH的话,发现项目调用的是 PositionRouter 这个合约,然后使用的是createIncreasePositionETH 这个函数。输入值破译后如下图:具体每个参数的解释,可以看官方文档。这里主要讲一下_acceptablePrice,是指的开仓时接受的最大(多头)或最小(空头)指数价格的美元值。我在Vault.priceFeed找到了提供价格的合约,发现了提供价格的函数 getPrice。所以下面写了一个函数,用来获取当前价格。接下来就是开仓了,首先准备调用 createIncreasePositionETH 需要用到的参数和输入。其中最近这一天, execution fee 从 0.0006e 变成了 0.002e 又变回了0.0006e,感觉是根据arbitrum 网络拥堵情况决定的。GMX是真的鸡贼,把amountIn 和 sizeDelta 是直接传入的输入。amountIn 是指我们的抵押品的数量(我们这里是ETH的数量)sizeDelta 是指我们想要到达的仓位大小。GMX 规定的是直接 数额 乘以 10^30,遵守就好。最小抵押品的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这个教程大概花了我3天左右的时间(=人工交互1000+个号😂),我也是一步一步自己摸索,不断地试错。但我发现其实,底层逻辑都差不多。第一就是明确要实现什么,然后去协议把整个流程走一遍。懂了用户的交互流程后,就可以去看官方的开发者文档,然后找例子。如果例子不够详细,就自己找合约,找官方的github去看解释,或者看别人或自己的交易记录,去看调用的什么合约,用的什么input,最后写写代码就出来了。当然这里面还有很多学问,包括你对项目背后逻辑的理解等。 如果有什么错误,还望大家能指出来。 合约交互的教程,我就停更在这儿了。后面有兴趣再写。希望能对大家有所帮助。Cheers!项目代码https://github.com/June911/GMX_Interact参考链接https://ethereum.stackexchange.com/questions/234/what-is-an-abi-and-why-is-it-needed-to-interact-with-contracts 下面是一些个人链接,欢迎大家关注。 https://twitter.com/june023_eth https://github.com/June911 ## Publication Information - [June](https://paragraph.com/@june023/): Publication homepage - [All Posts](https://paragraph.com/@june023/): More posts from this publication - [RSS Feed](https://api.paragraph.com/blogs/rss/@june023): Subscribe to updates - [Twitter](https://twitter.com/june023_eth): Follow on Twitter