Solidity

如何為非抽象合約做supportsInterface

  • October 17, 2022

我有以下情況。

contract GovernanceERC20 is ERC165Upgradeable, ERC20VotesUpgradeable, {
  
  bytes4 private constant GOVERNANCE_INTERFACE_ID;

  /// @inheritdoc ERC165Upgradeable
   function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
       return
           interfaceId == GOVERNANCE_INTERFACE_ID ||
           interfaceId == type(IERC20Upgradeable).interfaceId ||
           interfaceId == type(IERC20PermitUpgradeable).interfaceId ||
           interfaceId == type(IERC20MetadataUpgradeable).interfaceId ||
           interfaceId == type(ERC20VotesUpgradeable).interfaceId ||
           super.supportsInterface(interfaceId);
   }
  
  function initialize() public view returns(uint) {
       return 10;
  }

  function mint(address to, uint256 amount) external {
       _mint(to, amount);
   }

  function great() public view returns(uint) {
       return 10;
  }
 
}

如您所見,我在想GOVERNANCE_INTERFACE_ID應該是什麼。

方式 1:我不能做GOVERNANCE_INTERFACE_ID = type(GovernanceERC20).interfaceId as GovernanceERC20` 不是抽象的。

方式 2:我不想為GovernanceERC20 .

應該GOVERNANCE_INTERFACE_ID是什麼?

選項 A:

GOVERNANCE_INTERFACE_ID = this.initialize.selector ^ this.great.selector ^ this.mint.selector;

選項 B:

GOVERNANCE_INTERFACE_ID = type(IERC20Upgradeable).interfaceId ^ type(IERC20PermitUpgradeable).interfaceId ^ type(IERC20MetadataUpgradeable).interfaceId ^ type(ERC20VotesUpgradeable).interfaceId ^ this.initialize.selector ^ this.great.selector ^ this.mint.selector;

嚴格來說,只要它不與其他標識符衝突,它並不重要。

您可能知道,EIP-165指定瞭如何確定合約來實現介面。它有一個例子:return i.hello.selector ^ i.world.selector;. 所以基本上將其功能的選擇器異或在一起。有一個EIP-881包含更多細節,但尚未最終確定。

至於您的選項A和B,選項A更符合介面中ID的計算方式:介面不關心其他介面實現了什麼,ID只說明該特定介面支持什麼。因此,檢查多個supportsInterfaceID 以查看實現支持的所有功能通常很有用。從這個意義上說,我會選擇選項 A。

我不確定您為什麼不想只為您的額外功能添加一個介面,但我仍然會以與從介面相同的方式計算 ID。所以選項A。

引用自:https://ethereum.stackexchange.com/questions/137519