本文档介绍了OpenZeppelin Contracts库中与合约自省相关的接口和合约,包括IERC165、ERC165、ERC165Checker、IERC1820Registry、IERC1820Implementer和ERC1820Implementer。这些工具允许合约声明并查询其他合约实现的接口,以防止错误并实现复杂的交互。
你当前阅读的不是此文档的最新版本。5.x 是当前版本。
最好在 https://docs.openzeppelin.com/contracts/api/introspection 查看此文档 |
这组接口和合约处理合约的类型内省,即检查可以在其上调用哪些函数。这通常被称为合约的 interface。
以太坊合约没有 interface 的原生概念,因此应用程序通常必须简单地信任它们不会进行不正确的调用。对于受信任的设置,这不是问题,但通常需要与未知和不受信任的第三方地址进行交互。甚至可能没有任何直接调用它们!(例如,ERC20
代币可能会被发送到缺少将其转移出去的方式的合约,从而永远锁定它们)。在这些情况下,合约 声明 其 interface 可以非常有用地防止错误。
有两种主要方法可以解决这个问题。
本地,合约实现 IERC165
并声明一个 interface,第二个合约通过 ERC165Checker
直接查询它。
全局,全局和唯一的注册表(IERC1820Registry
)用于注册特定 interface(IERC1820Implementer
)的实现者。然后查询注册表,这允许更复杂的设置,例如为外部拥有的帐户实现 interface 的合约。
请注意,在所有情况下,帐户只是 声明 它们的 interface,但它们不需要实际实现它们。因此,该机制可用于防止错误并允许复杂的交互(请参阅 ERC777
),但不能依赖它来保证安全性。
IERC165
ERC165 标准的 interface,如 EIP 中定义。
实现者可以声明对合约 interface 的支持,然后可以由其他人查询(ERC165Checker
)。
有关实现,请参见 ERC165
。
函数
supportsInterface(bytes4 interfaceId) → bool
external如果此合约实现了由 interfaceId
定义的 interface,则返回 true。请参阅相应的
EIP section
以了解有关如何创建这些 id 的更多信息。
此函数调用必须使用少于 30 000 的 gas。
ERC165
IERC165
interface 的实现。
合约可以从中继承并调用 _registerInterface
来声明
它们对 interface 的支持。
函数
constructor()
internalsupportsInterface(bytes4 interfaceId) → bool
public时间复杂度 O(1),保证始终使用少于 30 000 的 gas。
_registerInterface(bytes4 interfaceId)
internal将合约注册为由 interfaceId
定义的 interface 的实现者。对实际 ERC165 interface 的支持是自动的,
不需要注册其 interface id。
要求:
interfaceId
不能是 ERC165 无效 interface(0xffffffff
)。ERC165Checker
用于查询通过 IERC165
声明的 interface 支持的库。
请注意,这些函数返回查询的实际结果:如果不支持 interface,它们不会 revert
。由调用者决定
在这种情况下该怎么做。
函数
supportsERC165(address account) → bool
internal如果 account
支持 IERC165
interface,则返回 true。
supportsInterface(address account, bytes4 interfaceId) → bool
internal如果 account
支持由 interfaceId
定义的 interface,则返回 true。对 IERC165
本身的支持会自动查询。
getSupportedInterfaces(address account, bytes4[] interfaceIds) → bool[]
internal返回一个布尔数组,其中每个值对应于传入的 interface 以及它们是否受支持。这允许 你可以批量检查合约的 interface,在你期望某些 interface 可能不受支持的情况下。
自 v3.4 起可用。
supportsAllInterfaces(address account, bytes4[] interfaceIds) → bool
internal如果 account
支持 interfaceIds
中定义的所有 interface,则返回 true。对 IERC165
本身的支持会自动查询。
批量查询可以通过跳过重复检查来节省 gas
IERC165
支持。
IERC1820Registry
全局 ERC1820 注册表的 interface,如 EIP 中定义。帐户可以在此注册表中注册 interface 的实现者,以及查询支持。
实现者可以由多个帐户共享,并且还可以为每个帐户实现多个 interface。合约可以为自己实现 interface,但外部拥有的帐户 (EOA) 必须将其委托给 合约。
IERC165
interface 也可以通过注册表查询。
有关深入的解释和源代码分析,请参见 EIP 文本。
函数
事件
setManager(address account, address newManager)
external将 newManager
设置为 account
的管理器。帐户的管理器能够为其设置 interface 实现者。
默认情况下,每个帐户都是自己的管理器。在 newManager
中传递值 0x0
将管理器重置为此初始状态。
发出一个 ManagerChanged
事件。
要求:
account
的当前管理器。getManager(address account) → address
external返回 account
的管理器。
参见 setManager
。
setInterfaceImplementer(address account, bytes32 _interfaceHash, address implementer)
external将 implementer
合约设置为 account
的 interfaceHash
的实现者。
account
为零地址是调用者地址的别名。零地址也可以在 implementer
中使用以删除旧的地址。
参见 interfaceHash
以了解如何创建它们。
发出一个 InterfaceImplementerSet
事件。
要求:
调用者必须是 account
的当前管理器。
interfaceHash
不得为 IERC165
interface id(即,它不得
以 28 个零结尾)。
除非 implementer
是调用者,否则 implementer
必须实现 IERC1820Implementer
并在查询支持时返回 true。参见
IERC1820Implementer.canImplementInterfaceForAddress
。
getInterfaceImplementer(address account, bytes32 _interfaceHash) → address
external返回 account
的 interfaceHash
的实现者。如果未注册任何此类
实现者,则返回零地址。
如果 interfaceHash
是 IERC165
interface id(即,它以 28 结尾
零),将查询 account
以获取对其的支持。
account
为零地址是调用者地址的别名。
interfaceHash(string interfaceName) → bytes32
external返回 interfaceName
的 interface 哈希,如相应的
EIP 的 section。
updateERC165Cache(address account, bytes4 interfaceId)
externalimplementsERC165Interface(address account, bytes4 interfaceId) → bool
externalimplementsERC165InterfaceNoCache(address account, bytes4 interfaceId) → bool
externalInterfaceImplementerSet(address account, bytes32 interfaceHash, address implementer)
eventManagerChanged(address account, address newManager)
eventIERC1820Implementer
ERC1820 实现者的 interface,如
EIP 中定义。
由将注册为
IERC1820Registry
中的实现者的合约使用。
函数
canImplementInterfaceForAddress(bytes32 interfaceHash, address account) → bytes32
external如果此合约
对 account
实现了 interfaceHash
,则返回一个特殊值(ERC1820_ACCEPT_MAGIC
)。
参见 IERC1820Registry.setInterfaceImplementer
。
ERC1820Implementer
IERC1820Implementer
interface 的实现。
合约可以从中继承并调用 _registerInterfaceForAddress
来
声明他们愿意成为实现者。
然后应该调用 IERC1820Registry.setInterfaceImplementer
以完成注册。
函数
canImplementInterfaceForAddress(bytes32 interfaceHash, address account) → bytes32
public_registerInterfaceForAddress(bytes32 interfaceHash, address account)
internal将合约声明为愿意成为
account
的 interfaceHash
的实现者。
参见 IERC1820Registry.setInterfaceImplementer
和
IERC1820Registry.interfaceHash
。
- 原文链接: docs.openzeppelin.com/co...
- 登链社区 AI 助手,为大家转译优秀英文文章,如有翻译不通的地方,还请包涵~
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!