智能合约模拟调用的具体应用在golang查询uniswap v3智能合约上某代币的价格
一、最初的实现思路
合约的方法如果是public view的,那么通过golang代码可以直接调用,步骤大致为:
1、使用合约的ABI生成.go文件接口
2、使用以太坊节点链接初始化以太坊客户端;
3、以以太坊客户端和uniswap合约地址为参数,实例化uniswap合约
4、直接调用uniswap的“查询价格”的方法,传入代币地址和数量等参数,获取价格。
二、遇到的问题
上述思路在使用uniswap v2时是奏效的,但v3的合约代码中找不到某个方法是public view的供查询价格。
而看文档的说明,可以调用quoter合约的“quoteExactInputSingle”方法查询价格。
看合约的源码,发现该方法的调用会上链,也就是需要消耗gas。这说明代币的兑换实质发生了,而我们的需求则只是查询价格而非交易。
三、智能合约的模拟调用
在找不到其他更合适方法且无法理解quoter合约的时候,同事提出了原理和解决方案。我们可以运用智能合约模拟调用的特性,来实现只查询价格,而不改变链状态。
那么,什么是合约的模拟调用?
假设合约中有状态变量number,有方法addOne,每一次调用addOne都会给number加一,也就是改变了链上的数据状态。
我们想知道下次调用addOne会使number变为几,而不真的改变number,我们就要用“模拟调用”。
假设number目前是5,具体的实现,在js代码中是这样的:
const number= await contract.addOne.call();
//输出6,但链上仍为5
关键就在于调用了addOne方法后,又加上了.call()
这就是模拟调用。
如果不加.call,则输出6,且链上也改为了6.
四、golang是如何实现的
知道了原理,那么在golang中应该如何实现呢?
回到第一部分,有个步骤是生成.go文件。
.go文件生成后,在文件中会有UniswapRaw这样的结构体。
这就是模拟调用应该使用的结构体。
步骤是:
1、使用合约的ABI生成.go文件接口
2、使用以太坊节点链接初始化以太坊客户端;
3、以以太坊客户端和uniswap_quoter合约地址为参数,实例化uniswap_quoter合约
4、以uniswap_quoter对象为参数,实例化其对应的Raw对象rawCaller
5、声明一个空的输出变量 var out []interface{}
构造一个callOpts对象
准备业务入参params
6、调用rawCaller.Call(callOpts,out,params)
7、方法调用后,结果会写入out,而链上状态没有改变。
代码大致如下:
client := utils.GetChainClient()
uniswap, _ := uniswap_factory.NewUniswapV3QuoterV2(common.HexToAddress(uniswapAddress), client)
callOpt := &bind.CallOpts{
From: common.Address{},
Context: context.Background(),
}
token1 := common.HexToAddress("0x...")
token2 = common.HexToAddress("0x...")
fee := big.NewInt(3000)
amountIn := utils.FloatStringToBigInt("1.00", 18)
sqrtPriceLimitX96 := big.NewInt(0)
var out []interface{}
rawCaller := &uniswap_factory.UniswapV3QuoterV2Raw{Contract: uniswap}
err := rawCaller.Call(callOpt, &out,"quoteExactInputSingle",
uniswap_factory.IQuoterV2QuoteExactInputSingleParams{
TokenIn: token1,
TokenOut: token2,
AmountIn: amountIn,
Fee: fee,
SqrtPriceLimitX96: sqrtPriceLimitX96,
})
if err != nil {
logger.GetLogger().Errorf("get currency last price error %s", err.Error())
}else{
price := utils.ConvertDecimal(out[0].(*big.Int), consts.Erc20Decimal)
fmt.Println("price get :", price)
}
这篇好文章是转载于:学新通技术网
- 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
- 本站站名: 学新通技术网
- 本文地址: /boutique/detail/tanhgfaagk
-
photoshop保存的图片太大微信发不了怎么办
PHP中文网 06-15 -
Android 11 保存文件到外部存储,并分享文件
Luke 10-12 -
word里面弄一个表格后上面的标题会跑到下面怎么办
PHP中文网 06-20 -
《学习通》视频自动暂停处理方法
HelloWorld317 07-05 -
photoshop扩展功能面板显示灰色怎么办
PHP中文网 06-14 -
微信公众号没有声音提示怎么办
PHP中文网 03-31 -
excel下划线不显示怎么办
PHP中文网 06-23 -
excel打印预览压线压字怎么办
PHP中文网 06-22 -
怎样阻止微信小程序自动打开
PHP中文网 06-13 -
TikTok加速器哪个好免费的TK加速器推荐
TK小达人 10-01