Skip to content

XC-20概况

Cross-Chain Assets Precompiled Contracts Banner

概览

跨共识信息格式(XCM)定义了两条互操作的区块链之间传递信息的方式。此格式为Moonbeam/Moonriver与中继链或是其他波卡/Kusama生态内平行链之间打开了传递信息和资产的大门。

Substrate资产具有原生可互操作性。然而,开发者需要使用Substrate API与其交互。而这使开发者的体验感降低,尤其是来自以太坊生态的开发者。因此,为了协助开发者上手波卡和Kusama提供的原生互操作性,Moonbeam引入了XC-20概念。

XC-20为Moonbeam上独特的资产类别,其结合了Substrate资产的优点(原生可互操作性)但又使开发者能够通过预编译合约(以太坊API)使用熟悉的ERC-20接口与之交互。除此之外,开发者能够使用常用以太坊开发框架或dApp集成XC-20资产。

Moonbeam XC-20 XCM Integration With Polkadot

XC-20类型

目前有两种XC-20类型:外部XC-20可铸造XC-20

外部XC-20是从其他平行链或中继链转移到Moonbeam的原生跨链资产。因此,实际的Token存在于每条链的Moonbeam主权账户中。所有的外部XC-20资产使用_xc_作为其名称的前缀与其他资产类别进行区分。

可铸造XC-20也是跨链资产,但其可以直接在Moonbeam上铸造和销毁,也可以转移至其他平行链。由于可铸造XC-20是在Moonbeam上创建,不是其他平行链或中继链的原生资产,因此资产的名称、符号和小数点都是完全可配置的。正是如此,无需在这类资产的名称或符号前加_xc_作为前缀。

两种XC-20类型的核心都是Substrate资产,在底层通过Substrate API进行交互。然而,Moonbeam提供了ERC-20接口与这些资产进行交互,因此无需Substrate基本知识也可直接操作。从用户角度来看,两种类型的XC-20都以相同的方式进行交互,唯一的区别在于可铸造XC-20包含了ERC-20接口的扩展,具有一些管理资产的额外功能,例如制造和销毁。

XC-20的跨链转移是通过X-Tokens pallet来完成的。转移外部XC-20资产和可铸造XC-20资产的操作说明根据特定资产的多位置会有些许不同。

XC-20与ERC-20

尽管XC-20和ERC-20有很多相似之处,但仍需要注意两者之间的差异。

首先,XC-20是基于Substrate的资产,因此,它们也受到治理等Substrate功能的直接影响。此外,通过Substrate API完成的XC-20交易不会在基于EVM的区块浏览器中可见,例如Moonscan。只有通过以太坊API完成的交易才能通过此类浏览器看到。

尽管如此,XC-20可以通过ERC-20接口进行交互,因此它们具有可以从Substrate和Ethereum API交互的特性。这为开发者在使用这类资产时提供了更大的灵活性,并允许与基于EVM的智能合约(如DEX、借贷平台等)无缝集成。

ERC-20接口

Moonbeam上的ERC20.sol接口遵循EIP-20 Token标准,这是智能合约中Token的标准API接口。此标准定义了一个Token合约必须实现与应用程序互操作所需的函数和动作。

该接口包括以下函数:

  • name() - 只读函数,用于返回Token名称
  • symbol() - 只读函数,用于返回Token符号
  • decimals() - 只读函数,用于返回Token小数位数
  • totalSupply() - 只读函数,用于返回现有的Token总数
  • balanceOf(address who) - 只读函数,用于返回指定地址的余额
  • allowance(address owner, address spender) - 只读函数,用于检查和返回所有者允许给支出者的Token数量
  • transfer(address to, uint256 value) - 转移一定Token数量至特定地址,若交易成功则返回True
  • approve(address spender, uint256 value) - 批准指定地址代表msg.sender支出特定的Token数量。若成功则返回True
  • transferFrom(address from, address to, uint256 value) - 从一个指定地址转移Token至另一个指定地址,若成功则返回True

注意事项

ERC-20标准没有明确多次调用approve的具体影响,但是使用此功能多次更改额度可能会开启攻击向量。为避免不正确或意外的交易排序,您可以先将spender额度减少至0,然后再设置一个预期的额度。更多关于攻击向量的详情,请参阅ERC-20 API: An Attack Vector on Approve/TransferFrom Methods

该接口也包含以下必要事件:

  • Transfer(address indexed from, address indexed to, uint256 value) - 执行交易时发出
  • Approval(address indexed owner, address indexed spender, uint256 value) - 注册通过时发出

可铸造XC-20还包括仅允许Token合约或指定账户的所有者调用的附加功能。请查看Mintable XC-20页面获取关于附加功能和可用指定角色的更多信息。

ERC-20 Permit接口

Moonbeam上的Permit.sol接口遵循EIP-2612标准,使用permit函数扩展了ERC-20接口。Permit是可用于更改帐户的ERC-20限额的签名消息。

标准的ERC-20 approve函数在其设计中受到限制,因为allowance仅能由交易的发送者msg.sender进行修改。您可在OpenZeppelin的ERC-20接口的实现中找到,通过msgSender函数设置owner,最终将其设置为msg.sender

用户可以签署信息而非签署approve交易,该签名可以用于调用permit函数以修改allowance。如此一来,仅需少量gas即可进行Token转移。另外,用户也无需发送两次交易来批准和转移Token。关于permit函数的示例,请查看OpenZeppelin的ERC-20 Permit扩展的实现

The Permit.sol接口包含以下函数:

  • permit(address owner, address spender, uint256, value, uint256, deadline, uint8 v, bytes32 r, bytes32 s) —— 任何人均可调用批准permit
  • nonces(address owner) —— 反馈给定所有者当前的nonce
  • DOMAIN_SEPARATOR() —— 返回用于避免重放攻击的EIP-712域分隔符。这遵循EIP-2612实现

DOMAIN_SEPARATOR()是在EIP-712标准中定义,计算如下:

keccak256(PERMIT_DOMAIN, name, version, chain_id, address)

哈希的参数可以分解为:

  • PERMIT_DOMAIN —— EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)keccak256
  • name —— 一种Token名称,但包含以下注意事项:
    • 如果Token的定义了名称,则域名的nameXC20: <name>,其中<name>是Token名称
    • 如果Token的未定义名称,则域名的nameXC20: No name
  • version —— 签名域的版本,在本示例中,version设置为 1
  • chainId —— 网络的chain ID
  • verifyingContract —— XC-20地址

注意事项

在之前的Runtime 1600升级中,name字段未遵循标准的EIP-2612实现。

域分隔符的计算可以在Moonbeam的EIP-2612实现中看到,在OpenZeppelin的EIP712合约中显示了一个实际的示例。

除了域分隔符,hashStruct保证签名只能用于给定函数参数的permit函数。这使用了一个给定数值确保签名不会受到重放攻击。哈希结构的计算可以在Moonbeam的EIP-2612实现中看到,在OpenZeppelin的ERC20Permit合约中显示了一个实际的示例。

域分隔符和哈希结构可以用于构建最终哈希的完全编码消息。在OpenZeppelin的EIP712合约中显示了一个实际的示例。

使用最终哈希以及vrs数值,通过ECRECOVER预编译可以验证和恢复签名。如果验证成功,nonce和限额将会更新。

使用Remix与预编译交互

无论是外部资产还是铸造资产,其交互的方式是一样的。但是,如果您是可铸造Token合约或具有特定功能的指定账户的所有者,还有一些额外的函数可供您交互。更多信息,请查看Mintable XC-20页面的与可铸造XC-20特定函数交互部分。

查看先决条件

要通过XC-20预编译批准花费或转移XC-20,您将需要准备以下内容:

此教程将涵盖如何与ERC20.sol接口交互。您可以修改以下操作说明并使用Permit.sol接口。

添加&编译接口

您可以使用Remix与XC-20预编译交互,首先您需要将ERC-20接口添加至Remix:

  1. 获取ERC20.sol的复制文档
  2. 将文档内容粘贴至名为IERC20.sol的Remix文档

Load the interface in Remix

当您成功在Remix读取ERC-20接口后,您将需要编译:

  1. 点击(从上至下的)第二个Compile标签
  2. 编译IERC20.sol文档

Compiling IERC20.sol

当接口已成功被编译后,您将会在Compile标签旁看到绿色的打勾符号。

访问预编译

您将使用获得的XC-20预编译地址访问接口,而非部署ERC-20预编译:

  1. 在Remix内的Compile标签下点击Deploy and Run标签。请注意,预编译合约已被部署
  2. 确保已在ENVIRONMENT下拉菜单中选择Injected Web3。当您已经选择Injected Web3,MetaMask将会跳出弹窗要求将您的账户连接至Remix
  3. 确认ACCOUNT下显示的为正确账户
  4. 确认已在CONTRACT下拉菜单中选择IERC20 - IERC20.sol。由于此为预编译合约,您不需要部署任何代码。同时,我们将会在At Address字段内显示预编译地址
  5. 提供在计算外部XC-20预编译地址计算可铸造XC-20预编译地址操作说明计算得到的XC-20预编译地址。在本示例中为0xFFFFFFFF1FCACBD218EDC0EBA20FC2308C778080,然后点击At Address

Access the address

注意事项

如果您希望确保运行顺利,您可以使用您的搜寻引擎查询校验工具以校验您的XC-20预编译地址。当地址校验成功,您可以将其用在At Address字段中。

XC-20的IERC20预编译将会在Deployed Contracts列表下显示。现在您可以使用任何ERC-20函数以获得XC-20的信息或是转移XC-20。

Interact with the precompile functions

如果您想更深入学习每个函数,您可以查看ERC-20预编译教程并加以修改来适用XC-20预编译交互。

Last update: December 28, 2022
| Created: January 4, 2022