为互连智能合约Connected Contracts使用Axelar SDK
Axelar的通用消息传递(GMP)允许智能合约安全地跨链通信。这使开发者能够在Moonbeam上构建跨链互连应用,直接获取来自波卡、以太坊、Avalanche、Cosmos及以外的功能。本文将介绍Axelar打包的JavaScript SDK工具包,其中包括协助开发者实现跨链愿景的工具。
Axelar SDK允许开发者预估费用、追踪和恢复交易,以及轻松转账。我们将通过展示部署可以跨链铸造的NFT来介绍SDK所提供的工具。在开始之前,请先阅读近期发布的使用Axelar的跨链消息介绍。
Axelar合约概况
Axelar是一条连接不同区块链并传递安全跨链通信的区块链。每个Axelar网络的验证人在链上运行Axelar支持的轻节点。这个动态验证人通过监控每条链的Axelar网关合约来达成共识,以确认消息从一条链传送至另一条链。Axelar网关合约是我们在后续demo中交互的两个Axelar合约的其中一个。
另一个我们将使用的合约是Axelar Gas Receiver微服务。当您使用Axelar网关发送跨链交易时,IAxelarGasReceiver将允许您为目标链上的后续交易支付费用。虽然非必要,但这允许终端用户只发送一笔交易来自动更新目标链,并以他们所持有的源链Token来支付交易费用。
CrossChainNFT合约
我们将编写一个只能铸造NFT的简单合约,来查看是否收到指定跨链消息。
铸造NFT将需要用Token付款,即包装的DEV(Moonbase Alpha的原生Token)。像DEV这样的原生资产的包装Token将为发送给它的每个DEV铸造ERC-20 WDEV Token,并提供一个DEV替换一个WDEV的选项。需要使用WDEV而非原生DEV,因为Axelar要求发送的所有Token为ERC-20。
因此,要在跨链消息中铸造Token,需要收到至少0.05 WDEV。
我们把相同的合约放到两条链上,因此可以发送和接收消息。从更高层次来看,合约可以做以下两件事:
- 通过Axelar的网关向WDEV跨链发送编码的地址消息,可以选择在目标链上支付gas费
- 从Axelar接收编码的地址消息,并仅在其收到至少0.05 WDEV后执行
您将使用Hardhat项目来代替Remix,但是在设置之前,我们先来看一下合约的几个部分。
合约可以由Axelar网关执行,如此处我们可以使用IAxelarExecutable。此父合约有两个可以覆盖的函数_execute和_executeWithToken,允许开发者在合约从Axelar网关收到合约调用时更改逻辑。两个函数拥有相同的输入值,但_executeWithToken还包含Token的Symbol和数量,用于跨链传输。
最后一个是铸造函数,其中需要三个输入值:目标地址、目标链和要传送的WDEV数量。请注意此铸造函数由初始链(Moonbase Alpha)调用,并在不同的目标链铸造NFT。
逻辑本身有三个步骤。第一步,需要从调用者处获得WDEV。调用者将必须先批准NFT合约才能转移其WDEV。随后,NFT合约批准网关来转移从调用者处获得的WDEV,因为网关合约将尝试在最后一步的时候从NFT合约转移Token。
接下来,在目标链支付gas费,我们使用IAxelarGasService合约。此合约有很多不同的配置来支付gas费,比如支付执行费用与executeWithToken或使用ERC-20 token作为支付费用与使用原生资产。如果您计划后续编写自己的合约需要注意这一点。
在本示例中,因为初始链为Moonbase Alpha,则原生资产为DEV。我们可以使用原生DEV,根据Moonbase Alpha的原生资产和目标链上的原生资产的转化率在目标链上支付gas费用。因为我们正在传送的合约调用包含一个Token并计划用DEV在目标链支付gas费,我们将使用payNativeGasForContractCallWithToken函数。
最后,我们使用callContractWithToken来调用网关以传送我们的跨链消息。请注意我们发送的负载(通用数据可以在跨链调用中传送)仅仅只是调用者的地址。此数据将需要通过目标合约来编码。
现在,让我们来看一下目标链上发生了什么。
因为我们计划将Token作为铸造NFT的费用,因此我们将覆盖IAxelarExecutable中的_executeWithToken。
在_executeWithToken的实现中,我们首先要确保由Axelar提供的tokenSymbol是“WDEV”。然后,我们预计需要0.05 WDEV支付费用,如果其他Token或任何少于0.05 WDEV将自动归还。接下来,我们编码负载以获得初始链调用者的地址,从而我们能够将NFT铸造到此地址。这样就完成铸造了!
设置Repo
我们为此博客专门设置了一个Github repository。请确保您已复制此Repo。
要设置所有的依赖项,您可以在复制的文件夹中运行以下命令:
“`
npm install
“`
显而易见,我们已经安装了Hardhat、OpenZeppelin合约、一些Axelar合约和Axelar SDK。
Repo包含了两个Solidity文件,第一个文件是CrossChainNFT,第二个是Axelar库StringAddressUtils.sol,此文件尚未安装npm包,但仍需要Hardhat实现。
Repo脚本文件中还包含4个Hardhat脚本。
- axelarStatus.js:一个Hardhat任务,允许您查阅Axelar交易相关信息
- deploy.js:将CrossChainNFT部署至Hardhat提供的网络
- gatewayGasReceiver.js:为Axelar网关返回硬编码的值和gas服务合约
- mint.js:铸造CrossChainNFT(只在Moonbase Alpha上运行)
在我们开始主要部分之前,您将需要准备一个拥有私钥和一定数量DEV的账户来部署合约和签署未来所有的交易。将其放在Repo主目录下的secrets.json文件内。格式应如下所示:
“`
{
“privateKey”: “YOUR_PRIVATE_KEY”
}
“`
如果一切无误,您将能够正确地编译:
“`
npx hardhat compile
“`
在Moonbeam上部署跨链合约
此demo主要是使用脚本,因此最好能够查看这些脚本,您可以从deploy.js开始使用,这与Ethers.js部署合约示例类似。
gatewayGasReceiver.js在此Repo中存储了很多合约地址,这对部署非常有用。您可能不需要更改任何硬编码的地址。
尝试将您的合约部署至初始链:
“`
npx hardhat run scripts/deploy.js –network moonbase
“`
您应该看到地址已部署并显示在控制台。请确保复制此地址,这将用于下一个脚本交互。
您也需要将其部署至目标链。选择哪个目标链部署取决于您,但您需要其原生资产来部署。我在下方列举了一些可用的网络和获取其原生资产的Faucet:
同样也确保复制目标链的合约!
查看铸造脚本
铸造合约将需要Axelar的SDK。
在脚本上方,Ethers.js在Hardhat的脚本中进行初始化。Axelar SDK也同样会进行初始化。SDK中有多个Axelar API可以使用,但是在本示例中,我们将仅使用AxelarQueryAPI,因其包含了跨链gas费支付所需的所有gas预估功能。
之后还有一些常量供您更改。此操作过程使用Fantom作为目标链,但您可以使用任何您部署的链。请注意,即使您使用的是测试网环境,链的名称仍是其对应的主网名称,这就是为什么初始链显示的是“MOONBEAM”而非“MOONBASE”。
接下来,我们必须用包装的DEV来跨链传送。首先,我们必须包装我们的DEV并在目标链批准合约以获取一些WDEV。此步骤为必要步骤,因为初始链的合约必须发送一些WDEV以支付在目标链上铸造NFT的费用。
请注意,我们使用IAxelarGateway合约来查找地址,而非硬编码WDEV合约地址。我们也可以在智能合约本身中完成此步骤,但是我将在此处展示如何使用Ethers.js完成此步骤。
我们要签署两笔交易:第一笔是包装0.13 WDEV,然后批准CrossChainNFT合约传送WDEV。
您可能在想为什么我们要包装0.13 WDEV,而铸造的价格仅为0.05。截至本文撰写时,Axelar在网络之间转移Token时会收取少量费用(在本示例中为0.08 WDEV),具体费用可在网站上计算获得。这由网关自动完成,但在未来可能委托theIAxelarGasService合约来完成。
现在我们可以预估要发送给mintXCNFT函数的DEV数量,以支付目标链上的gas费。这便是Axelar SDK发挥作用的地方。
我们必须预估在目标链上所需的gas数量,因为很难预估一个只能由特定合约调用的函数。在本示例中,我们预估我们将花费不超过400,000的gas费。在真实的生产环境中,您可能希望对您要花费的gas数量进行基准测试。但是,如果您实际预估超出很多,将由Axelar的gas服务方进行退还。
由Axelar SDK提供的estimateGasFee函数将在初始链的原生资产和目标链的原生资产之间转换,以找到合适数量发送至目标链。
您可能在想为什么我们会使用“GLMR”而非“DEV”。这与Axelar使用主网名称来替代测试网名称类似,由于我们使用的是测试网环境,因此Axelar将用“GLMR”来代替“DEV”。
从SDK调用此函数将返回一串字符串,代表需要支付的DEV(以WEI为单位),如“241760932800000”。这不太容易理解,因此我们使用Ethers.js将其转换成可读性更高的版本并在之后显示在控制台。
最后,我们将调用mintXCNFT合约函。这里重要的一点是,我们发送的gasFee不是作为gas限制,而是作为价值。Ethers.js能够计算初始链发送的gas数量,但是要计算目标链支付的费用,我们必须用Axelar SDK计算并将其作为值发送至IAxelarGasReceiver合约。
这就是整个脚本。在我们运行脚本前,请再次检查确保脚本上方的4个常量(ORIGIN_CHAIN, DESTINATION_CHAIN, ORIGIN_CHAIN_ADDRESS, DESTINATION_CHAIN_ADDRESS)设置无误!
铸造NFT的命令如下所示:
“`
npx hardhat run scripts/mint.js –network moonbase
“`
控制台输出应如下所示:
“`
Wrap transaction hash: 0x3ddb9d8334444dffb3a16ca2ddd61f5f32b12ce0df5cdc916b7465f6b67f22b8
Approve transaction hash: 0x5b05e781aa8c4aafe12f62a61b5f99b010cf70caf0f6ce0912c640348bde11ad
Awaiting transaction confirmations…
Cross-Chain Gas Fee: 241760932800000 Wei / 0.0002417609328 Ether
Minting transaction hash: 0x148031bce691b0025928b5e5f911a82fd27f224d7d14cd3f428381553d2bb2c1
“`
此处最重要的数据是铸造交易,这可用于追踪您的交易状态,请确保您已记录此数据。如果您没有保留此数据,您可以在Axelar的测试网浏览器查看所有近期交易。
查看Axelar交易状态
Axelar有一个测试网浏览器,您刚刚完成交互的成功交易应如下所示:
但最好尝试使用SDK查看您的交易状态,因为它提供了有关交易和任何可能性错误的更多信息。为此,我编写了一个Hardhat任务以供大家使用。您可以在axelarStatus.js查看代码,我们也将在下方展示。
代码的主要内容在这5行中。首先,我们初始化我们将要使用的SDK模型AxelarGMPRecoveryAPI。不像我们在铸造脚本中所使用的AxelarQueryAPI,AxelarGMPRecoveryAPI将帮助追踪和恢复滞留的交易。
我们接下来要做的就是查询交易状态,SDK会为我们处理。
您可以在Axelar的文档网站获取更多关于AxelarGMPRecoveryAPI的信息。这包含防止交易出错的额外功能,尤其是没有足够gas费与跨链交易一同传送。
可以运行以下命令来运行脚本,其中“YOUR_TRANSACTION_HASH”是您发送跨链消息的初始链中的交易哈希:
“`
npx hardhat axelarStatus –tx YOUR_TRANSACTION_HASH
“`
如果您运行Hardhat脚本,您将在您的控制台看到下方所示页面(因原图过大只截取部分)。您可能想要查看现在的状态,Axelar的文档网站上有一整个可能的列表供您查看。您正在寻找destination_executed以表明其已经正确接收和执行,但如果您仍在早期您将看到source_gateway_called或destination_gateway_approved。
您可以在Axelar的文档网站学习更多调试合约的细节,其中包含了特定的错误信息以及如何使用Tenderly等工具应付逻辑错误。
深入了解互连智能合约
您已经了解如何使用Axelar构建属于自己的互连智能合约了!了解Axelar的更多信息,请点击Axelar网站;阅读关于Moonbeam如何成为区块链互操作性的领导者,请点击Moonbeam的Connected Contracts页面。
关于Moonbeam
Moonbeam是一个智能合约平台,用于构建跨链互连应用程序,能够访问任何链上的用户、资产和服务。通过将来自以太坊、Cosmos、波卡等功能整合到一个平台中,Moonbeam解决了当今用户体验碎片化的问题,解锁了真正的互操作性,并为下一代应用程序奠定基础。Moonbeam平台使用集成的跨链信息传递,允许开发者创建访问多个远程区块链服务的智能合约。通过此方式结合Moonbeam的开发者友好型EVM平台、各类工具支持和Substrate架构,为构建互连应用程序提供理想化的开发环境。