Skip to content

在Moonbeam上与XC-20资产交互

概览

正如XC-20资产概览页面中所述,XC-20资产是Moonbeam上的独特资产类别。尽管它们是Substrate原生资产,但它们也具有ERC-20接口,并且可以像任何其他ERC-20资产一般进行交互。此外,ERC-20 Permit接口可用于所有外部XC-20资产。

本教程涵盖XC-20资产的Solidity接口,包含标准ERC-20接口和ERC-20 Permit接口,以及如何使用这些接口与外部XC-20资产交互。

XC-20资产Solidity接口

两种XC-20资产类别皆具有标准ERC-20接口。除此之外,所有外部XC-20资产皆拥有ERC-20 Permit接口。以下两个部分教程分别描述了接口的内容。

ERC-20 Solidity接口

如同先前提及的,您可以通过一个ERC-20接口与XC-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) - 注册通过时发出

ERC-20 Permit Solidity接口

外部XC-20资产同样拥有ERC-20 Permit接口。在Moonbeam上的Permit.sol接口跟随EIP-2612标准,也就是使用了permit 函数拓展ERC-20接口。Permit为能够用于变动一个账户ERC-20余额的签署信息。请注意,本地XC-20资产同样具有Permit接口,但这对他们来说并不是适用于XCM所需的条件。

标准ERC-20 approve函数在设计时已被限制,因allowance仅能够由交易的传送者修改,也就是msg.sender。您能够在OpenZeppelin的ERC-20接口实现中查看,其通过msgSender函数设置owner并最终设置为msg.sender

用户可以签署一条消息,而不是签署approve交易,并且该签名可用于调用permit函数来修改allowance。因此,它允许Gasless Token转账。此外,用户不再需要发送两笔交易来批准和转移Token。要查看permit函数的范例,您可以查看OpenZeppelin对ERC-20 Permit扩展程序的实现

Permit.sol包含以下函数:

  • permit(address owner, address spender, uint256, value, uint256, deadline, uint8 v, bytes32 r, bytes32 s) - 使用一个批准permit,任何人皆可以调用
  • nonces(address owner) - 根据给定所有者返回当前随机数
  • 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 - 网络的链ID
  • verifyingContract - XC-20地址

注意事项

在Runtime 1600版本升级前,name栏位并不跟随EIP-2612实现。

您可以在Moonbeam的EIP-2612实现中查看域名分隔器的计算,以及在OpenZeppelin的EIP712合约中查看完整的范例。

除了域名分隔器之外,hashStruct保证签名只能用于具有给定函数参数的permit函数。它使用给定的随机数来确保签名不会受到重放攻击。哈希结构的计算可以参见Moonbeam的EIP-2612实现,其中展示了OpenZeppelin的ERC20Permit合约的完整范例。

域名分隔器和哈希结构能够用于构建完全编码消息的最终哈希。您可以在OpenZeppelin的EIP712合约查看完整范例。

通过最终哈希和vr以及s数值,签名将能够被验证和恢复。如果成功通过验证,随机数将会增加1且余额将会更新。

使用一个ERC-20接口与外部XC-20资产交互

本部分教程将会展现该如何使用Remix通过ERC-20接口与XC-20资产交互。因为本地XC-20资产为一般ERC-20资产的表现形式,此部分教程将会专注于外部XC-20资产。

要与外部XC-20资产交互,您需要计算您希望交互的XC-20资产得预编译地址。接着,您可以与ERC-20接口交互,正如与其他ERC-20接口交互一样。

您可以调节此部分教程中针对Permit.sol接口的指令。

查看先决条件

要通过ERC-20接口批准一个外部XC-20资产得花费或是转账,您将需要:

计算外部XC-20资产预编译地址

在您通过ERC-20接口与一个外部XC-20资产交互之前,您需要通过资产ID生成外部XC-20资产的预编译地址。

外部XC-20资产预编译地址可以通过以下方式计算:

address = '0xFFFFFFFF...' + DecimalToHex(AssetId)

根据上述计算,第一步是获取资产ID的u128表示形式并将其转换为十六进制值。您可以使用您选择的搜索引擎查找用于将十进制转换为十六进制值的简单工具。对于资产ID42259045809535163221576417993425387648,十六进制值为1FCACBD218EDC0EBA20FC2308C778080

外部XC-20资产的预编译仅会落在0xFFFFFFFF000000000000000000000000000000000xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF之间。

由于以太坊地址有40个字符长,因此您需要从最初的8个F开始,然后在十六进制值前面加上0,直到地址有40个字符。

已经计算出的十六进制值有32个字符长,因此在十六进制值前面加上8个F将为您提供与XC-20资产预编译交互所需的40个字符的地址。对于此范例来说,完整地址为0xFFFFFFFF1FCACBD218EDC0EBA20FC2308C778080

现在您已经计算出外部XC-20资产预编译地址,您可以使用该地址与XC-20资产进行交互,就像与Remix中的任何其他ERC-20资产进行交互一样。

添加并编译接口

您现可以使用Remix与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: January 25, 2024
| Created: April 14, 2023