qidao123.com技术社区-IT企服评测·应用市场

 找回密码
 立即注册

ERC-6909 最小多代币标准

[复制链接]
发表于 2025-3-21 16:50:14 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

×
ERC-6909 Token标准是 ERC-1155 Token标准的一种简化替代方案。
ERC-1155 标准引入了一种多Token接口,使得单个智能合约可以或许联合可替代的和不可替代的Token(即,​ERC20 和 ERC721)。
ERC-1155 办理了多个挑战,比方低落摆设本钱、最小化以太坊区块链上的冗余字节码,以及简化多Token交易的Token批准流程。
然而,由于每次转账都强制要求回调、强制包罗批量转账,以及缺乏对单操纵员批准方案的细粒度控制,它引入了一些膨胀和气体低效问题。ERC-6909 通过消除合约级回调和批量转账,并用混合(限额-操纵员)权限方案替代单操纵员的凭据方案,从而办理了这些缺点,以实现颗粒化的Token管理。
留意: 以下部分假设读者对 ERC-1155 标准及其概念有肯定的相识。如果你不认识,请在继续之前阅读相干内容。
ERC-6909 和 ERC-1155 标准的对比

ERC-6909 移除转账的回调要求

ERC-1155 规范要求 safeTransferFrom 和 safeBatchTransferFrom 检查吸收账户是否为合约。如果是,则必须在吸收合约账户上调用 ERC1155TokenReceiver 接口函数(onERC1155Received,onERC1155BatchReceived)以检查其是否接受转账。
这些回调在某些情况下是有用的。然而,对于盼望不使用这种行为的吸收方,它们是不必要的外部调用。回调影响吸收合约账户的Gas本钱和代码巨细,因为它们必要实现多个回调(即,通过 onERC1155Received,onERC1155BatchReceived)并返回把戏的 4 字节值以吸收Token。相比之下,ERC-6909 的实现者可以自定义他们的回调架构。
ERC-6909 省略了批量转账逻辑

尽管批量转账有时是有益的,但在 ERC-6909 标准中故意省略,以答应开辟者根据特定执行环境实验批量转账逻辑。开辟者可以根据本身的必要实现批量转账,而无需仅仅为了遵循标准而添加额外的批量转账函数。
下面展示的 safeBatchTransferFrom 函数在 ERC-1155 标准中执行批量转账。然而,其强制的包罗为不必要它们的应用程序增加了膨胀:
  1. // ERC-1155
  2. function safeBatchTransferFrom(
  3.     address _from,
  4.     address _to,
  5.     uint256[] calldata _ids,
  6.     uint256[] calldata _values,
  7.     bytes calldata _data
  8. ) external;
复制代码
​以下是 ERC-6909 transferFrom 函数。我们可以看到批量特性和 _data 参数已被删除。
  1. // ERC-6909
  2. function transferFrom(
  3.     address sender,
  4.     address receiver,
  5.     uint256 id,
  6.     uint256 amount
  7. ) public returns (bool) {
  8.     if (sender != msg.sender && !isOperator[sender][msg.sender]) {
  9.         uint256 senderAllowance = allowance[sender][msg.sender][id];
  10.         if (senderAllowance < amount) revert InsufficientPermission();
  11.         if (senderAllowance != type(uint256).max) {
  12.             allowance[sender][msg.sender][id] = senderAllowance - amount;
  13.         }
  14.     }
  15.     if (balanceOf[sender][id] < amount) revert InsufficientBalance();
  16.     balanceOf[sender][id] -= amount;
  17.     balanceOf[receiver][id] += amount;
  18.     emit Transfer(msg.sender, sender, receiver, id, amount);
  19.     return true;
  20. }
复制代码
ERC-6909 同时支持全局批准和细粒度限额

  1. // 在 ERC-1155 →
  2. function setApprovalForAll(
  3.     address _operator,
  4.     bool _approved
  5. ) external;
复制代码
上面展示的 setApprovalForAll 函数是 ERC-1155 中的全局操纵员模子,答应一个账户授权另一个账户管理(作为操纵员)其所有Token ID 的操纵。一旦被授权,操纵员可以随意转移授权账户拥有的任何数量的任何Token ID。
固然这种方法简化了委托,但缺乏细粒度控制:


  • 没有办法授予特定于单个Token ID 或数量的权限。
  • 这种全有或全无的方法不适合必要受控权限的场景。
为引入细粒度控制,ERC-6909 混合操纵员权限方案包罗以下内容:


  • 来自 ERC-1155 的操纵员模子,
  • 和受 ERC-20 启发的限额模子。
ERC-6909 中的操纵员模子

在下面的 ERC-6909 setOperator 函数中,spender 变量被设置为操纵员,并被授权无条件的权限,以转移账户所拥有的所有Token ID 而没有限额限定。
  1. function setOperator(address spender, bool approved) public returns (bool) {
  2.     isOperator[msg.sender][spender] = approved;
  3.     emit OperatorSet(msg.sender, spender, approved);
  4.    return true;
  5. }
复制代码
ERC-6909 中的限额模子

限额模子引入了一种特定于Token和数量的控制系统,其中一个账户可以为特定Token ID 设置有限的限额。
比方,Alice 可以答应 Bob 转移 100 个 ID 为 42 的Token,而不授予对其他Token ID 或不受限定的数量的访问权限,使用下一个展示的 ERC-6909 中的 approve 函数。
  1. function approve(address spender, uint256 id, uint256 amount) public returns (bool) {
  2.     allowance[msg.sender][spender][id] = amount;
  3.     emit Approval(msg.sender, spender, id, amount);
  4.     return true;
  5. }
复制代码
在 approve 中的 spender 变量是被授权代表Token所有者转移特定金额的特定Token ID 的账户。
比方,Token所有者可以答应 spender 转移 <= 100 个特定Token ID。大概,他们还可以通过将限额设置为 type(uint256).max 来为特定Token ID 授予无穷定的批准。
ERC-6909 并没有指定是否应扣减设置为 type(uint256).max 的限额。相反,这种行为留给实现者的自由裁量权,类似于 ERC-20。
焦点数据布局

ERC-6909 实现使用三个映射来更新账户余额和批准状态。
balanceOf:ID 的所有者余额

balanceOf 映射跟踪特定Token ID 由地址 (owner) 持有的余额。映射中的 owner => (id => amount) 布局表示单个所有者可以持有多个Token,并通过各自的 ID 跟踪别的额。
  1. mapping(address owner => mapping(uint256 id => uint256 amount)) public balanceOf;
复制代码
allowance:ID 的支出者限额

答应映射定义支出者在所有者的授权下可以转移多少特定Token(ID)。它促进了对Token支出的细粒度控制。
  1. mapping(address owner => mapping(address spender => mapping(uint256 id => uint256 amount))) public allowance;
复制代码
比方,allowance[0xDEF...][0x123...][5] 将返回所有者 0xDEF... 答应支出者 0x123... 转移的Token(ID 为 5)的数量。
isOperator:操纵员批准状态

  1. mapping(address owner => mapping(address operator => bool isOperator)) public isOperator;
复制代码
该映射跟踪支出者是否被批准作为拥有地址的所有Token的操纵员。比方,isOperator[0x123...][0xABC...] 返回 true 如果地址 0xABC... 被答应支出地址 0x123... 所拥有的Token;否则返回 false。
焦点 ERC-6909 功能及其数据参数

转账函数

该规范并未遵循 ERC-721 和 ERC-1155 中的“安全转账机制”,因为由于其向恣意合约的外部调用被认为是误导性的。ERC-6909 使用 transfer 和 transferFrom 函数,详情如下。
转账:

ERC-6909 的 transfer 函数表现得与 ERC-20 的 transfer 类似,只不过它实用于特定的Token ID。该函数接受吸收地址、Token的 ID 和要转移的金额作为输入参数,并使用 balanceOf 映射更新余额。与 ERC-20 转账函数类似,成功执行事件时返回 true 是必要的。
  1. // ERC-20 接口转账函数
  2. function transfer(address _to, uint256 _value) public returns (bool)
  3.     // ERC-6909 转账函数参考实现
  4.     // @notice 将数量 id 从调用者转移至接收者。
  5.     // @param receiver 接收者的地址。
  6.     // @param id Token的 ID。
  7.     // @param amount Token的数量。
  8.     function transfer(address receiver, uint256 id, uint256 amount) public returns (bool) {
  9.         if (balanceOf[msg.sender][id] < amount) revert InsufficientBalance(msg.sender, id);
  10.         balanceOf[msg.sender][id] -= amount;
  11.         balanceOf[receiver][id] += amount;
  12.         emit Transfer(msg.sender, msg.sender, receiver, id, amount);
  13.         return true;
  14.     }
复制代码
transferFrom:

ERC-6909 的 transferFrom 函数与 ERC-20 的不同之处在于它要求提供一个Token ID。别的,它还检查操纵员的批准以及限额。
该函数起首检查 if (sender != msg.sender && !isOperator[sender][msg.sender]),确保调用者 (msg.sender) 是:


  • 所有者(sender),大概
  • 已批准的操纵员(isOperator[sender][msg.sender] == true)。
如果 msg.sender 不是所有者也不是已批准的操纵员,函数将检查调用者是否具有 足够的限额 以进行转移。如果有限额但未设置为无穷定(type(uint256).max),则从限额中扣除转移的 amount。
别的,标准规定如果调用者是操纵员或 sender,则该函数不应扣减调用者对于Token id 的 allowance 中的 amount。
  1. // ERC-6909 transferFrom
  2. function transferFrom(address sender, address receiver, uint256 id, uint256 amount) public returns (bool) {
  3.     if (sender != msg.sender && !isOperator[sender][msg.sender]) {
  4.         uint256 senderAllowance = allowance[sender][msg.sender][id];
  5.         if (senderAllowance < amount) revert InsufficientPermission();
  6.         if (senderAllowance != type(uint256).max) {
  7.             allowance[sender][msg.sender][id] = senderAllowance - amount;
  8.         }
  9.     }
  10.     if (balanceOf[sender][id] < amount) revert InsufficientBalance();
  11.     balanceOf[sender][id] -= amount;
  12.     balanceOf[receiver][id] += amount;
  13.     emit Transfer(msg.sender, sender, receiver, id, amount);
  14.     return true;
  15. }
复制代码
approve:

approve 函数答应调用者(msg.sender)向支出者授予特定Token(ID)的特定限额。这会更新限额映射以反映新的限额并发出 Approval 事件。
  1. function approve(address spender, uint256 id, uint256 amount) public returns (bool) {
  2.     allowance[msg.sender][spender][id] = amount;
  3.     emit Approval(msg.sender, spender, id, amount);
  4.     return true;
  5. }
复制代码
setOperator:

setOperator 函数答应调用者(msg.sender)通过将批准参数设置为 true 或 false 来授予或撤销特定地址(spender)的操纵员权限。该函数会相应地更新 isOperator 映射,并发出 OperatorSet 事件,以关照外部监听器有关更改的情况。
  1. function setOperator(address spender, bool approved) public returns (bool) {
  2.     isOperator[msg.sender][spender] = approved;
  3.     emit OperatorSet(msg.sender, spender, approved);
  4.     return true;
  5. }
复制代码
ERC-6909 中的事件与日志日志

ERC-6909 定义了关键事件,以跟踪多Token合约中的Token转移、批准及操纵员权限。
1. 转移事件:

  1. /// @notice 转移发生时发出的事件。
  2. event Transfer(address caller, address indexed sender, address indexed receiver, uint256 indexed id, uint256 amount);
复制代码
ERC-6909 中的 Transfer 事件用于跟踪Token的移动,必须在以下条件下发出:


  • 转移Token id 的 amount 从一个账户到另一个账户时,将记录 sender、receiver、token ID 和转移的 amount。
  • 当创建新Token时,事件必须以 sender 为零地址(0x0)发出。
  • 当Token被烧毁时,事件必须以吸收方为零地址(0x0)发出,以表示Token被移除。
2. OperatorSet 事件:

  1. /// @notice 操作员被设置时发出的事件。
  2. event OperatorSet(address indexed owner, address indexed spender, bool approved);
复制代码
OperatorSet 事件每当所有者分配或撤销另一个地址的操纵员权限时都会发出。事件记录所有者的地址、支出者的地址以及更新的批准状态(true 表示授予,false 表示撤销)。
3. Approval 事件:

  1. /// @notice 批准发生时发出的事件。
  2. event Approval(address indexed owner, address indexed spender, uint256 indexed id, uint256 amount);
复制代码
当所有者设置或更新支出者转移特定金额的特定Token ID 的批定时,必须发出 Approval 事件。事件记录 owner、spender、Token id 和批准的 amount。
如今我们已经探讨了 ERC-6909 与 ERC-1155 之间的差异,以及 ERC-6909 中的焦点方法和事件,让我们看看标准的一些实际应用。
Uniswap v4 PoolManager 怎样实现 ERC-6909。

在 Uniswap v3 中,工厂/池模子通过使用 UniswapV3Factory 合约为每个池摆设一个单独的合约来创建新的Token对。这种方法增加了Gas本钱,因为每个新池都必要新的合约摆设。
与此相比,Uniswap v4 引入了一个单例合约(PoolManager.sol),该合约将所有流动性池管理作为其内部状态的一部分,而不是要求单独的合约摆设。这一设计显著低落了池创建的Gas本钱。
别的,以前版本中涉及 多个 Uniswap 池 的交易必要跨多个合约的Token转移和冗余状态更新。在 Uniswap v4 中,PoolManager 合约可以会合持有用户的 ERC-6909 表示的 ERC-20 Token,而不必要在池中往返转移 ERC-20 Token。
比方,如果用户为Token A 提供流动性,他们厥后可以选择提取其股份并吸收Token A 作为转移到其钱包的 ERC-20。然而,如果他们选择不提取Token,那么 Uniswap v4 的 PoolManager 可以 铸造其Token余额的 ERC-6909 表示,而无需从合约转移 ERC-20 Token——节省了跨合约调用。这些 ERC-6909 余额答应用户在协议中交易或互动,而无需在钱包之间移动Token。
这意味着当用户厥后将Token A 兑换为Token B 时,Uniswap 只是更新他们在池中的 ERC-6909 余额
留意:ERC-6909 在 Uniswap v4 中不作为 LP 代币使用。
ERC-6909 元数据在单例 DeFi 架构和 NFT 系列中的思量

以下是 IERC6909Metadata 接口,它定义了如何将 ERC-6909 标准和单独Token相干联的元数据,比方名称、符号和小数,其函数可以根据 id 的不同发展,答应 ERC-6909 中不同的Token具有不同的名称、符号和小数。
  1. /// @notice 包含单个Token元数据的合同。
  2. interface IERC6909Metadata is IERC6909 {
  3.     /// @notice 给定Token的名称。
  4.     /// @param id Token的 id。
  5.     /// @return name Token的名字。
  6.     function name(uint256 id) external view returns (string memory);
  7.     /// @notice 给定Token的 символ。
  8.     /// @param id Token的 id。
  9.     /// @return symbol Token的符号。
  10.     function symbol(uint256 id) external view returns (string memory);
  11.     /// @notice 给定Token的小数位数。
  12.     /// @param id Token的 id。
  13.     /// @return decimals Token的小数位数。
  14.     function decimals(uint256 id) external view returns (uint8);
  15. }
复制代码
对于 DeFi 协议,我们可能有多个 LP 代币,而且我们可能盼望将其标准化为都具有类似的小数,比方 18。然而,我们可能盼望名称和符号可以或许反映池中持有的不同资产。
相比之下,对于 NFT,decimals 值应始终设置为 1,因为 NFT 是不可分割的。
在典型的 NFT 系列(比方 ERC-721)中,所有Token共享类似的名字和符号,以表示整个系列(比方 "CryptoPunks" 和符号 "UNK")。ERC-6909 使我们可以或许遵循 ERC-712 规范,其中所有 NFT 在同一系列中共享类似的元数据。
ERC-6909 非同质化Token的实现示例。

ERC-6909 规范并没有明白规定支持非同质化Token的独特方法。但是,可以使用 ERC-1155 规范中形貌的 ID 位拆分技能在 ERC-6909 中实现非同质化Token。这种方法使用 位移和加法运算 将集合 ID 和项目 ID 编码在一个 uint256 Token ID 中。
  1. function getTokenId(uint256 collectionId, uint256 itemId) public pure returns (uint256) {
  2.     return (collectionId << 128) + itemId;
  3. }
复制代码
下面的 ERC6909MultiCollectionNFT 合约是一个使用 getTokenId 根据 collectionId 和 itemId 生成Token ID 的非同质化Token(NFT)实现示例。
mintNFT 函数确保每个 tokenId 只能被铸造一次,无论地址如何。它使用 mintedTokens 映射跟踪 NFT tokenId 是否已被全球铸造。
由于在 mintNFT 中将 amount 变量设置为 1,因此函数中的 _mint(to, tokenId, amount) 调用将对 tokenId 铸造一份。在任何情况下,如果 amount > 1,Token将变为可替代,而不是非同质化。
  1. // SPDX-License-Identifier: MIT
  2. pragma solidity ^0.8.20;
  3. import "./ERC6909.sol";
  4. contract ERC6909MultiCollectionNFT is ERC6909 {
  5.     struct NFT {
  6.         string uri;
  7.     }
  8.     mapping(uint256 => NFT) private _tokens;
  9.     mapping(uint256 => string) private _collectionURIs;
  10.     mapping(uint256 => bool) public mintedTokens;
  11.     event MintedNFT(address indexed to, uint256 indexed collectionId, uint256 indexed itemId, uint256 tokenId, string uri);
  12.     // 通过连接 collectionId 和 itemId 计算 Token ID
  13.     function getTokenId(uint256 collectionId, uint256 itemId) public pure returns (uint256) {
  14.         return (collectionId << 128) + itemId;
  15.     }
  16.     function _mint(address to, uint256 tokenId, uint256 amount) internal {
  17.         balanceOf[to][tokenId] += amount;
  18.         emit Transfer(msg.sender, address(0), to, tokenId, amount);
  19.     }
  20.     function mintNFT(address to, uint256 collectionId, uint256 itemId, string memory uri) external {
  21.         uint256 amount = 1;
  22.         uint256 tokenId = getTokenId(collectionId, itemId);
  23.         require(!mintedTokens[tokenId], "ERC6909MultiCollectionNFT: Token already minted");
  24.         require(amount == 1, "ERC6909MultiCollectionNFT: Token copies must be 1");
  25.         _tokens[tokenId] = NFT(uri);
  26.         mintedTokens[tokenId] = true; // 标记为已铸造
  27.         _mint(to, tokenId, amount); // amount 被定义为 1。
  28.         emit MintedNFT(to, collectionId, itemId, tokenId, uri);
  29.     }
  30.     function nftBalanceOf(address owner, uint256 tokenId) public view returns (uint256) {
  31.         return balanceOf[owner][tokenId];
  32.     }
  33. }
复制代码
请记住,上面 mintNFT 中的 _mint 调用将余额映射更新为 1,因为这些铸造的Token完满是非同质化的。因此,在此合约中,如果 owner 地址确实铸造了 tokenId,nftBalanceOf 函数预计总是返回 1。
为了转移Token的所有权,下面的 nftTransfer 函数确保只有 NFT 所有者可以通过验证别的额启动转移,才气答应唯一存在的单元转移。
  1. function nftTransfer(address to, uint256 tokenId) external {
  2.     require(balanceOf[tokenId][msg.sender] == 1, "ERC6909MultiCollectionNFT: This should be non-fungible.");
  3.     require(to != address(0), "ERC6909MultiCollectionNFT: transfer to zero address");
  4.     transfer(to, tokenId, 1);
  5.     // 在此情况下,数量等于 1。
  6.     emit Transfer(msg.sender, address(0), to, tokenId, 1);
  7. }
复制代码
ERC-6909 内容 URI 扩展与元数据 URI JSON 模式

为了标准化 ERC-6909 中的元数据访问,可选的 IERC6909ContentURI 接口为检索合约和Token条理的元数据定义了两个 URI 函数(contractURI 和 tokenURI)。ERC-6909 标准并不强制Token必要关联 URI 元数据。然而,如果实现中包罗这些 URI 函数,返回的 URI 应该指向遵循 ERC-6909 元数据 URI JSON 架构的 JSON 文件。
  1. pragma solidity ^0.8.19;
  2. import "./IERC6909.sol";
  3. /// @title ERC6909 内容 URI 接口
  4. interface IERC6909ContentURI is IERC6909 {
  5.     /// @notice 合同级别 URI
  6.     /// @return uri 合同级别的 URI。
  7.     function contractURI() external view returns (string memory);
  8.     /// @notice Token级别 URI
  9.     /// @param id Token的 ID。
  10.     /// @return uri Token级别的 URI。
  11.     function tokenURI(uint256 id) external view returns (string memory);
  12. }
复制代码
如上所示,ERC-6909 IERC6909ContentURI 接口定义了两个可选的 URI 函数,即 contractURI 和 tokenURI;每个函数都有其相应的 URI JSON 模式。contractURI 函数(不带参数)返回指向合约级别元数据的单个 URI,而 tokenURI() 返回每个Token ID 特定的 URI。
以下是根据 ERC-6909 标准构造合约 URI JSON 架构的示例。
  1. {
  2.   "title": "Contract Metadata",
  3.   "type": "object",
  4.   "properties": {
  5.     "name": {
  6.       "type": "string",
  7.       "description": "The name of the contract."
  8.     },
  9.     "description": {
  10.       "type": "string",
  11.       "description": "The description of the contract."
  12.     },
  13.     "image_url": {
  14.       "type": "string",
  15.       "format": "uri",
  16.       "description": "The URL of the image representing the contract."
  17.     },
  18.     "banner_image_url": {
  19.       "type": "string",
  20.       "format": "uri",
  21.       "description": "The URL of the banner image of the contract."
  22.     },
  23.     "external_link": {
  24.       "type": "string",
  25.       "format": "uri",
  26.       "description": "The external link of the contract."
  27.     },
  28.     "editors": {
  29.       "type": "array",
  30.       "items": {
  31.         "type": "string",
  32.         "description": "An Ethereum address representing an authorized editor of the contract."
  33.       },
  34.       "description": "An array of Ethereum addresses representing editors (authorized editors) of the contract."
  35.     },
  36.     "animation_url": {
  37.       "type": "string",
  38.       "description": "An animation URL for the contract."
  39.     }
  40.   },
  41.   "required": ["name"]
  42. }
复制代码
tokenURI 函数则接受一个 uint256 参数 id,并返回该Token的 URI。如果Token id 不存在,该函数可以回滚。与合约级别的 URI 一样,客户在与合约交互时 必须 替换 URI 中每处 {id} 的出现为实际的Token ID,以访问与该Token相干的精确元数据。
以下是 tokenURI 函数的实现,返回遵循占位符格式的 静态 URI 模板
  1. // SPDX-License-Identifier: MIT
  2. pragma solidity ^0.8.19;
  3. import "./ERC6909.sol";
  4. import "./interfaces/IERC6909ContentURI.sol";
  5. contract ERC6909ContentURI is ERC6909, IERC6909ContentURI {
  6.     /// @notice 合同级 URI。
  7.     string public contractURI;
  8.     /// @notice 每个 id 的 URI。
  9.     /// @return Token的 URI。
  10.     function tokenURI(uint256) public pure override returns (string memory) {
  11.         return "<baseuri>/{id}";
  12.     }
  13. }
复制代码
以下是根据 ERC-6909 标准构造 URI JSON 架构的示例。
  1. {
  2.   "title": "Asset Metadata",
  3.   "type": "object",
  4.   "properties": {
  5.     "name": {
  6.       "type": "string",
  7.       "description": "Identifies the token"
  8.     },
  9.     "description": {
  10.       "type": "string",
  11.       "description": "Describes the token"
  12.     },
  13.     "image": {
  14.       "type": "string",
  15.       "description": "A URI pointing to an image resource."
  16.     },
  17.     "animation_url": {
  18.       "type": "string",
  19.       "description": "An animation URL for the token."
  20.     }
  21.   },
  22.   "required": ["name", "description", "image"]
  23. }
复制代码
ERC-6909 规范中的限额和操纵员歧义。

思量一个场景,其中一个账户(A)授予另一个账户(B)操纵员权限,并为 B 设置可转移特定金额的Token的限额。
如果 B 代表 A 发起转移,则实现必须确定检查的精确顺序以及限额如何与操纵员权限互动。
歧义涉及检查的顺序。合约应该:

  • 起首检查限额,如果不足则回滚,即使 B 具有操纵员权限。
  • 起首检查操纵员权限,无论限额如何都答应转移。
在下面的 allowanceFirst 合约中,如果账户 B 具有操纵员权限,但限额不足,限额检查将失败,从而导致事件回滚。这可能是反直观的,因为操纵员权限通常意味着无穷定访问,用户可能会期望事件成功。
相反,在 operatorFirst 合约中,如果实现起首检查操纵员权限,将绕过限额检查,事件将基于操纵员的无穷定访问而成功。
  1. contract operatorFirst {
  2. function transferFrom(address sender, address receiver, uint256 id, uint256 amount) public {
  3.     // 首先检查 `isOperator`
  4.     if (msg.sender != sender && !isOperator[sender][msg.sender]) {
  5.         require(allowance[sender][msg.sender][id] >= amount, "insufficient allowance");
  6.         allowance[sender][msg.sender][id] -= amount;
  7.     }
  8.     // -- 剪切 --
  9.     }
  10. }
  11. contract allowanceFirst{
  12.     function transferFrom(address sender, address receiver, uint256 id, uint256 amount) public {
  13.      // 首先检查限额是否充足
  14.     if (msg.sender != sender && allowance[sender][msg.sender][id] < amount) {
  15.         require(isOperator[sender][msg.sender], "insufficient allowance");
  16.     }
  17.     // 错误:当限额不足时,由于算术下溢而发生恐慌,无论调用者是否具有操作员权限。
  18.     allowance[sender][msg.sender][id] -= amount;
  19.     // -- 剪切 --
  20. }
  21. }
复制代码
该标准故意将权限检查的决定留给实现者,这给实现者提供灵活性。在一个账户同时拥有操纵员权限和不足的限额时,转账行为取决于检查的顺序。
结论

ERC-6909 标准通过移除转账函数中的批量和强制回调,显著提高了 ERC-1155 的效率。去除批量处置惩罚答应逐个案例优化,特殊是对于汇总或气体敏感的环境。
它还通过混合操纵员权限方案引入了可扩展的Token批准控制,更多信息,,https://t.me/+_QibemQqIIg1OTY1。

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
继续阅读请点击广告
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|手机版|qidao123.com技术社区-IT企服评测▪应用市场 ( 浙ICP备20004199|浙ICP备20004199号 )|网站地图

GMT+8, 2025-8-11 10:06 , Processed in 0.085211 second(s), 31 queries .

Powered by Discuz! X3.5 Licensed

© 2001-2025 Discuz! Team.

快速回复 返回顶部 返回列表