Skip to content

Moonbeam上的XCM费用

概览

XCM旨在成为共识系统之间沟通的语言。传送XCM消息包含一系列在原链和目标链上执行的指令。XCM指令的集合将执行如Token转账等不同的动作。要处理和执行每个XCM指令,基本上皆需支付一定数量的相关费用。

然而,XCM技术被设计为通用、可扩展且高效,因此才能够在发展的生态当中保持可用和潜力。正因如此,其通用性适用于包含XCM执行费用支付的概念。在以太坊中,费用包含在交易协议之中,而在波卡生态当中,每条平行链皆有能够定义XCM支付该如何处理的能力。

本教程将会包含费用支付,如谁该负责支付XCM执行费用、该如何支付以及如何在Moonbeam上计算费用。

注意事项

以下信息仅供参考。权重(weight)和extrinsic基础成本自撰写本文时可能已发生变化。请确保检查实际值,切勿将以下信息用于生产环境应用程序。

费用支付

一般来说,费用支付的过程如下:

  1. 提供所需资产
  2. 必须协商资产交换计算时间(或权重)
  3. 在提供的权重限制或资金足够执行的情况下,XCM将会如指令描述运行

每条链皆能够配置XCM费用的组成,以及使用哪些Token支付(不论是原生或是外部资产)。举例来说,波卡和Kusama上的费用可分别由DOT和KSM支付给区块的验证人。在Moonbeam和Moonriver,XCM执行费用能够使用原生储备资产(分别为GLMR和MOVR)支付,但用户也能够使用源自其他链的资产支付,其费用将会被传送至财政库中。

您可以想像以下情景:Alice在波卡上拥有一定数量的DOT,她想要传送至Moonbeam给Alith。Alice因此传送了一个包含一系列XCM指令的XCM消息,将从Alice波卡上的账户拿取一定量的DOT并将铸造相同数量的xcDOT至Alith的账户。部分指令将会在波卡上执行,而其他部分指令将会在Moonbeam上执行。

那究竟Alice是如何在Moonbeam完成支付,执行她的指令完成其请求?她的请求将会通过一系列包含在XCM消息中的XCM指令完成,允许其在扣除相关XCM执行费用后购买执行时间。此处的执行时间将会用于发行和转移xcDOT,xcDOT为DOT在Moonbeam上的表现形式。这代表当Alice传送一些DOT至Alith在Moonbeam上的账户时,她将会在扣除XCM执行费用后获得与原先DOT数量比例为1:1的xcDOT。请注意在此情境中,XCM的执行费用以xcDOT支付。

Alice请求的资产转移过程如下:

  1. 资产将会传送Moonbeam在波卡上的账户(主权账户),并在收到资产后传送XCM消息至Moonbeam
  2. 传送至Moonbeam的XCM消息将会:
    1. 铸造相关资产在Moonbeam的表现形式
    2. 购买相应执行时间
    3. 使用执行时间在扣除执行费用后将资产在Moonbeam上的表现形式存入目标账户

XCM指令

一个XCM消息由一系列的XCM指令组成,而不同的XCM指令组合将会导向不同的执行动作。

举例来说,如果想将DOT转移至Moonbeam,可以使用以下XCM指令:

  1. TransferReserveAsset - 在Polkadot上执行,将资产从初始账户转移并存入目标账户。在这个例子中,目标账户是Moonbeam在Polkadot上的Sovereign账户。然后它将发送一条XCM信息至目标链,也就是Moonbeam。消息中包含了将要执行的的XCM指令
  2. ReserveAssetDeposited - 在Moonbeam上执行,将Sovereign账户收到资产的本地表示存储在临时保管寄存中,这是一个在Cross-Consensus Virtual Machine (XCVM) 中的临时地址。
  3. ClearOrigin - 在Moonbeam上执行。用于确保之后的XCM指令不使用XCM发送者的权限
  4. BuyExecution - 在Moonbeam上执行。使用保管的资产支付执行费用。具体费用根据目标链定义,在这个例子中目标为Moonbeam
  5. DepositAsset - 在Moonbeam上执行。将资产从保管中移除并且发送至Moonbeam上的目标账户

学习更多关于如何使用搭建XCM指令来传输本地资产至目标链,比如将Dot发送至Moonbeam,您可以参考X-Tokens Open Runtime Module Library作为例子。您可能需要transfer_self_reserve_asset这个函数。在这个函数中,您会发现它调用了TransferReserveAsset函数并且使用了assets, dest, 与 xcm三个参数。其中xcm参数包括了BuyExecutionDepositAsset指令。您可以访问Polkadot的Github库,在那您可以找到TransferReserveAsset这个指令。这条XCM消息结合了ReserveAssetDeposited指令,ClearOrigin指令与xcm参数,xcm参数包括BuyExecutionDepositAsset指令。

使用以下指令将xcDOT从Moonbeam发送回Polkadot:

  1. WithdrawAsset - 在Moonbeam上执行。移除资产并将其存入保管寄存中
  2. InitiateReserveWithdraw - 在Moonbeam上执行。将资产从保管寄存中移除(本质上它会被burn掉)并发送一条XCM消息至目标链。XCM消息以WithdrawAsset指令开始
  3. WithdrawAsset - 在Polkadot上执行。移除资产并将其存入保管寄存
  4. ClearOrigin - 在Polkadot上执行。用于确保之后的XCM指令不使用XCM发送者的权限
  5. BuyExecution - 在Polkadot上执行。使用保管的资产支付执行费用。具体费用根据目标链定义,在这个例子中目标为Polkadot
  6. DepositAsset - 在Polkadot上执行。将资产从保管中移除并且发送至Polkadot上的目标账户

学习更多关于如何使用搭建XCM指令来传输本地资产至目标链,比如将xcDOT发送至Polkadot,您可以参考X-Tokens Open Runtime Module Library作为例子。您可能需要transfer_to_reserve这个函数。在这个函数中,您会发现它调用了WithdrawAsset函数,然后调用InitiateReserveWithdraw并且使用了assets, dest, 与 xcm三个参数。其中xcm参数包括了BuyExecutionDepositAsset指令。您可以访问Polkadot的Github库,在那您可以找到InitiateReserveWithdraw instruction这个指令。这条XCM消息结合了WithdrawAsset指令,ClearOrigin指令与xcm参数,xcm参数包括BuyExecutionDepositAsset指令。

中继链XCM费用计算

Substrate已推出一个权重系统,决定一个函数的权重,也就是从计算成本的角度决定一个extrinsic的昂贵程度。一个权重单位被定义为一皮秒的执行时间。当在支付费用时,除了如网络拥塞的情况外,用户将会根据所调用函数的权重支付交易费用。

以下部分将会解释如何在波卡和Kusama计算XCM费用。请注意,Kusama特别使用基准化的数据决定XCM指令的总权重花费,因部分XCM指令可能包含数据库的读写,这将增加调用的权重。

目前在波卡和Kusama中有两个可用数据库,RocksDB(预设)和ParityDB,两者皆在每个网络具有不同的相关权重花费。

Polkadot

在波卡系统里,权重(weight)的价格包含了数据库的读写以及特定指令本身的权重。波卡为不同指令以及数据库的读写操作设定了它们的基准权重。以下是数据库操作权重计算的细则:

数据库
RocksDB (default) 20,499,000 83,471,000
ParityDB 11,826,000 38,052,000

现在您了解Polkadot上数据库读写的权重花费,您可以使用指令的基础权重花费计算总花费。

例如,WithdrawAsset 指令具有25,567,000基础权重,且执行一个数据库读取和一个数据库写入。因此,WithdrawAsset指令的总权重花费将用以下方式计算:

25567000 + 20499000 + 83471000 = 129537000

BuyExecution指令具有3,153,000基础权重,且不包含任何数据库读写。因此,BuyExecution 指令的总权重花费为3,153,000

在Polkadot上,基准化的基础权重分为两类:可替代的和通用的。可替代的权重为用于转移资产的XCM指令,而通用的基础权重用于其他类型指令。您可以在Polkadot Runtime代码中查看可替代资产通用资产的权重。

在了解指令的权重花费架构后,您可以以KSM为单位计算指令花费。

在Polkadot中,ExtrinsicBaseWeight被设置为124,706,000,为一分的十分之一。一分为10^10 / 100

因此您可以使用以下公式计算一个XCM指令的执行费用:

XCM-DOT-Cost = XCMInstrWeight * DOTWeightToFeeCoefficient

DOTWeightToFeeCoefficient为常量(为一分),并可以通过以下计算获得:

DOTWeightToFeeCoefficient = 10^10 / ( 10 * 100 * DOTExtrinsicBaseWeight )

使用实际数值:

DOTWeightToFeeCoefficient = 10^10 / ( 10 * 100 * 126045000 )

所以,DOTWeightToFeeCoefficient0.0793367448 Planck-DOT相同,现在您可以开始以KSM为单位计算最终费用,使用DOTWeightToFeeCoefficient作为常量和TotalWeight(129,537,000)作为变量:

XCM-Planck-DOT-Cost = TotalWeight * DOTWeightToFeeCoefficient
XCM-DOT-Cost = XCM-Planck-DOT-Cost / DOTDecimalConversion

因此,以下为WithdrawAsset的实际计算方式:

XCM-Planck-DOT-Cost = 129537000 * 0.0793367448 
XCM-DOT-Cost = 10277043.9112 / 10^10

总花费为0.0010277044 DOT

作为范例,您可以使用以下权重和指令花费计算传送一条XCM消息以在Kusama网络上转移xcKSM至KSM的总花费:

指令 重量 成本
WithdrawAsset 129,537,000 0.0010277044 DOT
ClearOrigin 3,010,000 0.0000238803 DOT
BuyExecution 3,153,000 0.0000250149 DOT
DepositAsset 129,786,000 0.0010296799 DOT
总量 265,486,000 0.0021062795 DOT

Kusama

Kusama上的总权重花费包括:给定指令本身花费和数据库读写的费用。尚未对数据库读写操作进行基准测试,而对指令权重进行了基准测试。以下为数据库执行权重花费的细节:

数据库
RocksDB (default) 25,000,000 100,000,000
ParityDB 8,000,000 50,000,000

现在您了解Kusama上数据库读写的权重花费,您可以使用指令的基础权重花费计算总花费。

例如,WithdrawAsset 指令具有24,720,000基础权重,且执行一个数据库读取和一个数据库写入。因此,WithdrawAsset指令的总权重花费将用以下方式计算:

24720000 + 25000000 + 100000000 = 149720000

BuyExecution指令具有2,714,000基础权重,且不包含任何数据库读写。因此,BuyExecution 指令的总权重花费为2,714,000

在Kusama上,基准化的基础权重分为两类:可替代的和通用的。可替代的权重为用于转移资产的XCM指令,而通用的基础权重用于其他类型指令。您可以在Kusama Runtime代码中查看可替代资产通用资产的权重。

在了解指令的权重花费架构后,您可以以KSM为单位计算指令花费。

在Kusama中,ExtrinsicBaseWeight被设置为124,706,000,为一分的十分之一。一分为10^12 / 30,000

因此您可以使用以下公式计算一个XCM指令的执行费用:

XCM-KSM-Cost = XCMInstrWeight * KSMWeightToFeeCoefficient

KSMWeightToFeeCoefficient为常量(为一分),并可以通过以下计算获得:

KSMWeightToFeeCoefficient = 10^12 / ( 10 * 3000 * KSMExtrinsicBaseWeight )

使用实际数值:

KSMWeightToFeeCoefficient = 10^12 / ( 10 * 3000 * 124706000 )

所以,KSMWeightToFeeCoefficient0.267295345319 Planck-KSM相同,现在您可以开始以KSM为单位计算最终费用,使用KSMWeightToFeeCoefficient作为常量和TotalWeight(149,720,000)作为变量:

XCM-Planck-KSM-Cost = TotalWeight * KSMWeightToFeeCoefficient
XCM-KSM-Cost = XCM-Planck-KSM-Cost / KSMDecimalConversion

因此,以下为WithdrawAsset的实际计算方式:

XCM-Planck-KSM-Cost = 149720000 * 0.267295345319 
XCM-KSM-Cost = 40019459.1011 / 10^12

总花费为0.000040019459 KSM

作为范例,您可以使用以下权重和指令花费计算传送一条XCM消息以在Kusama网络上转移xcKSM至KSM的总花费:

指令 重量 成本
WithdrawAsset 149,720,000 0.000040019459 KSM
ClearOrigin 2,614,000 0.000000698710 KSM
BuyExecution 2,714,000 0.000000725440 KSM
DepositAsset 150,904,000 0.000040335936 KSM
总量 305,952,000 0.000081779545 KSM

基于Moonbeam网络的XCM费用计算

Substrate已推出一个权重系统,决定一个函数的权重,也就是从计算成本的角度决定一个extrinsic的昂贵程度。一个权重单位被定义为一皮秒的执行时间。当在支付费用时,用户将会根据所调用函数的权重支付交易费用,接着每个平行链皆可以决定如何将权重转换至费用,举例而言,计算交易大小或是存储花费的额外费用。

Moonbeam对通用XCM指令进行了基准测试,而可替代的XCM指令仍然使用每条指令的固定权重。 因此,基准测试过的XCM指令的总权重成本除了给定指令所需的权重之外还考虑了数据库读/写的次数。 数据库操作的权重成本明细如下:

数据库
RocksDB (default) 25,000,000 100,000,000

现在您知道了Moonbase Alpha的数据库读取和写入的权重成本,您可以使用指令和额外的数据库读取/写入(如果适用)的基本权重来计算可替代和通用XCM指令的权重成本。

例如,WithdrawAsset指令是可替代XCM指令集的一部分。因此,它没有进行基准测试,WithdrawAsset指令的总权重成本为200,000,000

BuyExecution指令有一个181,080,000的基础权重,并执行四次数据库读取(assetManager pallet以获得 unitsPerSecond)。因此,BuyExecution指令的总权重成本计算如下:

181080000 + 4 * 25000000 = 281080000

您可以在下表中找到所有XCM指令的所有权重值:

基准测试过的指令 无基准测试的指令
通用XCM指令 可替代XCM指令

以下部分教程将会包含如何在基于Moonbeam的网络计算XCM费用,有两个主要的应用场景:

  • 以储备Token支付费用(如GLMR、MOVR或DEV等原生Token)
  • 使用外部资产(XC-20s)支付费用

储备资产的费用计算

对于每个XCM指令,权重单位将会被转换为余额单位作为费用计算的一部分。每个基于Moonbeam网络单个权重单位的Wei数量分别如下:

Moonbeam Moonriver Moonbase Alpha
5,000,000 50,000 50,000

这意味着以Moonbeam为例,计算一个XCM指令以储备资产作为费用的公式如下:

XCM-Wei-Cost = XCMInstrWeight * WeiPerWeight
XCM-GLMR-Cost = XCM-Wei-Cost / 10^18

因此,实际计算如下:

XCM-Wei-Cost = 200000000 * 5000000
XCM-GLMR-Cost = 1000000000000000 / 10^18

最后,在Moonbeam上一的XCM指令的总费用为0.001 GLMR

外部资产的费用计算

考虑Alice在Moonbeam上向Alith的账户发送DOT的场景,费用从Alith收到的xcDOT金额中收取。要确定支付多少费用,Moonbeam使用了一个名为UnitsPerSecond的概念,代表网络在XCM执行时间内每秒收取的Token单位(包含小数)。 Moonbeam(可能还有其他平行链)将使用此概念来确定使用与其储备不同的资产执行XCM的费用。

此外,在Moonbeam上执行XCM可以由原本资产来源链的多种资产(XC-20s)支付。举例来说,在撰写本文时,从Kusama Asset Hub (Statemine)发送的XCM消息{target=_blank}可以用xcKSM、xcRMRK 或xcUSDT支付。只要该资产在Moonbeam/Moonriver中设置了UnitsPerSecond,它就可以用于为来自该特定链的XCM消息支付XCM执行费用。

要找出给定的资产是否在UnitsPerSecond列表中,您可以使用assetManager.assetTypeUnitsPerSecond函数并输入想要查看的资产的multilocation。

如果您不确定其multilocation,您可以使用assetManager.assetIdType函数检索。

举例来说,您可以导向至Polkadot.js App的Moonbeam页面,并在Developer下拉选单中选取Chain State。接着,您可以跟随以下步骤操作:

  1. selected state query下拉选单中,选取assetManager
  2. 选取assetIdType extrinsic
  3. Option下方输入资产ID或是关闭include option以移除所有资产的信息。在本教程中将会获得xcUNIT的信息,其资产ID为42259045809535163221576417993425387648
  4. 点击+按钮提交查询

Get the xcDOT asset multilocation

您可以使用查询结果,并将其用于查询assetTypeUnitesPerSecond extrinsic:

  1. 确保已选取assetManager
  2. 选取assetTypeUnitesPerSecond extrinsic
  3. MoonbeamRuntimeXcmConfigAssetType选取Xcm
  4. parents一栏输入1
  5. interior选取Here
  6. 点击+提交查询

xcDOT的UnitsPerSecond数值为33,068,783,068

Get the xcDOT units per second value

请记得,权重的单位定义为执行时间的一皮秒,以下为定义执行时间的公式:

ExecutionTime = (Weight / Picosecond) * NumberOfInstructions
指令 重量
ReserveAssetDeposited 200,000,000
ClearOrigin 5,194,000
BuyExecution 281,080,000
DepositAsset 200,000,000
TOTAL 686,274,000

要定义Alice转移DOT至Moonbeam的执行时间(包含4个XCM指令),您可以使用以下计算方式:

ExecutionTime = 686274000 / 10^12

这代表4个XCM指令需花费0.000686274秒的区块执行时间。

要计算以xcDOT为单位的总花费,您将需要资产的单位位数作为查询,以xcDOT为例,其资产单位为10个位数。您可以通过检索资产元数据查询资产的单位位数。

区块执行的公式可以用于决定Alice转移DOT至Alith在Moonbeam上账户所需的花费,以下为总花费的计算公式:

XCM-Cost = ( UnitsPerSecond / DecimalConversion ) * ExecutionTime

转移花费的计算公式如下:

XCM-Cost = ( 33068783068 / 10^10 ) * 0.000686274

Alice转移DOT至Alith账户的总花费为0.0022694246 xcDOT

XCM Transactor费用

XCM Transactor Pallet构建了一个能够在其他生态链上远程交易的XCM消息。开发者有种方法通过pallet远程交易:transactThroughSigned extrinsic,调用者在目标链上的账户为一个multilocation原生的账户,且必须要拥有足够支付XCM执行费用,加上其他用于远程执行函数调度的费用

一般而言,XCM指令通常包含以下远程执行:

  • 首个指令将处理原链上的Token。这可以为将Token转移至某个主权账户,或是销毁相关的XC-20资产,让其可以被用于目标链。这些指令将会在原链上执行
  • DescendOrigin - 使用指令中提供的multilocation来改变起点因为来源不再是主权账户,而是multilocation衍生账户
  • WithdrawAsset - 在目标链上执行。移除资产并将其放于待使用
  • BuyExecution - 在目标链上执行,将会把保存资产拿出以支付执行费用,支付的费用由目标链决定
  • Transact - 在目标链执行,自给定的原链调用编码的调用数据

通过签署费用交易

通过multilocation衍生账户进行交易时,交易费用由发出调用的同一账户支付,其为目标链中的multilocation衍生帐户。因此,multilocation衍生帐户必须持有必要的资金来支付整个执行费用。请注意,支付费用的目标Token不需要在原链中注册为XC-20。

您可以想像以下情景:Alice想要使用通过签名函数的交易从Moonbase Alpha在另一条链(平行链 ID 888,在Moonbase Alpha中继链生态系统中)进行远程交易。要估计Alice的multilocation衍生账户执行远程调用所需的Token数量,您需要检查在目标链的特定交易信息。为此,请前往Polkadot.js Apps的链状态页面并设置以下选项:

  1. 选取xcmTransactor pallet
  2. 选取transactInfoWithWeightLimit方法
  3. 为目标链设置multilocation,根据您希望查询的交易信息。在此范例中,您可以将parents设置为1
  4. interior中选取X1
  5. X1一栏中选取Parachain
  6. Parachain设置为888
  7. 点击 +

Get the Transact Through Derivative Weight Info for another Parachain

在获得的回应中,您可以看到transactExtraWeightSigned400,000,000。这是在该特定目标链中执行此远程调用的4个XCM指令所需的权重。接下来,您需要找到目标链每执行XCM权重收取的费用。通常,您会查看该特定链的UnitsPerSecond。但在这种情况下并不会销毁XC-20 Token。因此,UnitsPerSecond可以作为参考,但不能保证估算的Token数量是正确的。要获取UnitsPerSecond作为参考值,在同一个Polkadot.js Apps页面,设置以下选项:

  1. 选取xcmTransactor pallet
  2. 选取destinationAssetFeePerSecond方法
  3. 为目标链设置multilocation,根据您希望查询的交易信息。在此范例中,您可以将parents设置为1
  4. interior中选取X2
  5. X1一栏中选取Parachain
  6. Parachain设置为888
  7. X2一栏选取PalletInstance
  8. PalletInstance设置为3
  9. 点击 +

Get the Units Per Second for Transact Through Derivative for another Parachain

请注意,此UnitsPerSecond中继链XCM费用计算部分中的预估成本有关,如果目标是另一个平行链,将与权重单位的Wei数值部分中显示的成本有关。您需要找到正确的数值,以确保multilocation衍生账户持有的Token数量是正确的。如同先前,计算相关的XCM执行费用与transactExtraWeight乘以UnitsPerSecond一样简单明了(用于估算):

XCM-Wei-Token-Cost = transactExtraWeight * UnitsPerSecond
XCM-Token-Cost = XCM-Wei-Token-Cost / DecimalConversion

因此,实际一个通过衍生调用的XCM Transactor交易费用的实际计算如下:

XCM-Wei-Token-Cost = 400000000 * 50000000000000000
XCM-Token-Cost = 20000000000000 / 10^18

通过签名进行交易的费用为0.00002 TOKEN请注意,这不包括远程执行调用的费用,仅包括XCM执行费用。

Last update: February 14, 2024
| Created: August 8, 2022