Alert Source Discuss
⚠️ Draft Standards Track: ERC

ERC-7604: ERC-1155 许可授权

ERC-1155 代币的许可授权

Authors calvbore (@calvbore), emiliolanzalaco (@emiliolanzalaco)
Created 2024-01-27
Discussion Link https://ethereum-magicians.org/t/proposal-for-a-new-eip-erc-2612-style-permits-for-erc1155-nfts/15504
Requires EIP-165, EIP-712, EIP-1155, EIP-1271, EIP-2098, EIP-5216

摘要

对于 ERC-20ERC-721 来说,“许可”授权流程都是对其各自 ERC 之下代币现有用户体验的重大改进。本 ERC 将“许可”模式扩展到 ERC-1155 代币,并大量借鉴了 ERC-4494ERC-2612

ERC-1155 代币的结构需要一个新的 ERC 来解释代币标准对代币 ID 和余额的使用(这也是本 ERC 需要 ERC-5216 的原因)。

动机

ERC-4494ERC-2612 中概述的许可结构允许通过签名消息来创建授权,但仅适用于其各自的底层代币(ERC-721ERC-20)。

规范

本文档中的关键词“必须”、“禁止”、“需要”、“应该”、“不应该”、“推荐”、“不推荐”、“可以”和“可选”应按照 RFC 2119 和 RFC 8174 中的描述进行解释。

必须将三个新函数添加到 ERC-1155 和 ERC-5216。

interface IERC1155Permit {
	function permit(address owner, address operator, uint256 tokenId, uint256 value, uint256 deadline, bytes memory sig) external;
	function nonces(address owner, uint256 tokenId) external view returns (uint256);
	function DOMAIN_SEPARATOR() external view returns (bytes32);
}

其语义如下:

对于所有地址 ownerspender,uint256 的 tokenIdvaluedeadlinenonce,字节 sig,调用 permit(owner, spender, tokenId, value, deadline, sig) 必须将 allowance(owner, spender, tokenId) 设置为 value,将 nonces(owner, tokenId) 递增 1,并发出由 ERC-5216 定义的相应 Approval 事件,当且仅当满足以下条件时:

  • 当前区块时间小于或等于 deadline
  • owner 不是零地址
  • nonces[owner][tokenId](状态更新之前)等于 nonce
  • sig 是来自 owner 的消息的有效 secp256k1ERC-2098ERC-1271 签名:
    keccak256(abi.encodePacked(
     hex"1901",
     DOMAIN_SEPARATOR,
     keccak256(abi.encode(
              keccak256("Permit(address owner,address spender,uint256 tokenId,uint256 value,uint256 nonce,uint256 deadline)"),
              owner,
              spender,
              tokenId,
              value,
              nonce,
              deadline))
    ));
    

如果任何这些条件未满足,则 permit 调用必须回退。

其中 DOMAIN_SEPARATOR 必须按照 EIP-712 进行定义。DOMAIN_SEPARATOR 应该对于合约和链是唯一的,以防止来自其他域的重放攻击,并满足 EIP-712 的要求,但在其他方面不受约束。DOMAIN_SEPARATOR 的常见选择是:

DOMAIN_SEPARATOR = keccak256(
    abi.encode(
        keccak256('EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)'),
        keccak256(bytes(name)),
        keccak256(bytes(version)),
        chainid,
        address(this)
));

换句话说,该消息是以下 EIP-712 类型结构:

{
  "types": {
    "EIP712Domain": [
      {
        "name": "name",
        "type": "string"
      },
      {
        "name": "version",
        "type": "string"
      },
      {
        "name": "chainId",
        "type": "uint256"
      },
      {
        "name": "verifyingContract",
        "type": "address"
      }
    ],
    "Permit": [
	  {
	    "name": "owner".
	    "type": "address"
	  },
      {
        "name": "spender",
        "type": "address"
      },
      {
        "name": "tokenId",
        "type": "uint256"
      },
      {
        "name": "value",
        "type": "uint256"
      },
      {
        "name": "nonce",
        "type": "uint256"
      },
      {
        "name": "deadline",
        "type": "uint256"
      }
    ],
    "primaryType": "Permit",
    "domain": {
      "name": erc1155name,
      "version": version,
      "chainId": chainid,
      "verifyingContract": tokenAddress
  },
  "message": {
    "owner": owner,
    "spender": spender,
    "tokenId": tokenId,
    "value": value,
    "nonce": nonce,
    "deadline": deadline
  }
}}

permit 函数必须检查签名者不是零地址。

请注意,在此定义中的任何地方,我们都没有引用 msg.senderpermit 函数的调用者可以是任何地址。

此 EIP 需要 ERC-165ERC-1155 中已经需要 ERC-165,但此处进一步需要它,以便注册此 ERC 的接口。这样做可以轻松验证 NFT 合约是否已实现此 ERC,从而使它们能够相应地进行交互。此 ERC 的 ERC-165 接口是 0x7409106d。实现此 ERC 的合约在用 0x7409106d 调用时,必须使 supportsInterface 函数返回 true

理由

permit 函数足以使 safeTransferFrom 交易无需额外交易即可进行。

该格式避免了对未知代码的任何调用。

给出 nonces 映射是为了防止重放攻击。

许可的一个常见用例是,中继者代表所有者提交许可。在这种情况下,中继方实际上被赋予了一个自由选项来提交或暂缓许可。如果这是一个令人担忧的原因,所有者可以通过将截止时间设置为不久的将来值来限制许可的有效时间。deadline 参数可以设置为 uint(-1) 以创建实际上永不过期的许可。同样,value 参数可以设置为 uint(-1) 以创建具有实际无限额度的许可。

包含 EIP-712 类型消息是因为它在 ERC-4494ERC-2612 中的使用,而后者又引用了许多钱包提供商的广泛采用。

此 ERC 侧重于 valuetokenId 都被批准,ERC-4494 仅侧重于 tokenId,而 ERC-2612 主要侧重于 value。ERC-1155 本身不支持按金额批准,因此此 ERC 需要 ERC-5216,否则 permit 将授予对帐户整个 tokenId 余额的批准。

ERC-2612 将签名拆分为其 v,r,s 组件,而此 ERC 选择采用可变长度的 bytes 数组,以便支持 ERC-2098 签名,这些签名可能不容易从 r,s,v 组件(65 字节)中分离或重建。

向后兼容性

未发现向后兼容性问题。

安全注意事项

以下注意事项已从 ERC-4494 复制。

在创建转移函数时应格外小心,其中 permit 和转移函数可以在一个函数中使用,以确保无效的许可不能以任何方式使用。这对于自动化 NFT 平台尤其重要,在这些平台上,粗心的实施可能会导致大量用户资产的泄露。

其余注意事项已从 ERC-2612 复制并进行了少量改编,并且在此同样适用:

尽管 Permit 的签名者可能心中有一个特定的参与者来提交他们的交易,但另一个参与者始终可以抢先进行此交易并在预期参与者之前调用 permit。但是,对于 Permit 签名者来说,最终结果是相同的。

由于 ecrecover 预编译会静默失败,并且在给定格式错误的消息时仅将零地址作为 signer 返回,因此重要的是要确保 ownerOf(tokenId) != address(0),以避免 permit 创建对任何没有设置批准的 tokenId 的批准。

签名的 Permit 消息是可审查的。中继方始终可以选择在收到 Permit 后不提交它,从而暂缓提交它的选项。deadline 参数是对这种情况的一种缓解措施。如果签名方持有 ETH,他们也可以自己提交 Permit,这可能会使先前签名的 Permit 无效。

标准的 ERC-20 批准竞争条件也适用于 permit

如果 DOMAIN_SEPARATOR 包含 chainId 并且是在合约部署时定义的,而不是为每个签名重建的,则存在在未来链分裂的情况下可能在链之间进行重放攻击的风险。

版权

版权和相关权利通过 CC0 放弃。

Citation

Please cite this document as:

calvbore (@calvbore), emiliolanzalaco (@emiliolanzalaco), "ERC-7604: ERC-1155 许可授权 [DRAFT]," Ethereum Improvement Proposals, no. 7604, January 2024. [Online serial]. Available: https://eips.ethereum.org/EIPS/eip-7604.