本文档介绍了OpenZeppelin Contracts库中的实用工具合约和库,用于提高智能合约的安全性、处理新型数据类型以及安全地使用底层原语。包括安全工具(如Pausable和ReentrancyGuard),以及用于处理地址、数组和字符串的库。此外,还介绍了用于处理计数器、可枚举映射和集合的实用工具,以及安全使用CREATE2操作码的工具。
你当前阅读的不是此文档的最新版本。5.x 是当前版本。
| 在 https://docs.openzeppelin.com/contracts/api/utils 查看此文档效果更佳 |
包含实用函数的各种合约和库,你可以使用它们来提高安全性、处理新的数据类型或安全地使用底层原语。
安全工具包括:
Pausable: 提供了一种简单的方法来暂停合约中的活动(通常是为了应对外部威胁)。
ReentrancyGuard: 保护你免受重入调用。
Address、Arrays 和 Strings 库提供了更多与这些原生数据类型相关的操作,而 SafeCast 增加了在不同的有符号和无符号数字类型之间安全转换的方法。
对于新的数据类型:
Counters: 一种获取只能递增或递减的计数器的简单方法。对于 ID 生成、计数合约活动等非常有用。
EnumerableMap: 类似于 Solidity 的 mapping 类型,但具有键值枚举:这将让你知道映射有多少条目,并遍历它们(mapping 无法做到)。
EnumerableSet: 类似于 EnumerableMap,但用于集合。可用于存储特权帐户、已颁发的 ID 等。
因为 Solidity 不支持泛型类型,EnumerableMap 与 EnumerableSet 被专门用于有限数量的键值类型。<br>从 v3.0 开始,EnumerableMap 支持 uint256 → address ( UintToAddressMap),EnumerableSet 支持 address 和 uint256 ( AddressSet 和 UintSet)。 |
最后,Create2 包含安全使用 CREATE2 EVM 操作码的所有必要实用工具,而无需处理底层汇编。
Pausable合约模块,允许子项实现紧急停止机制,该机制可以由授权帐户触发。
此模块通过继承使用。它将提供修饰符 whenNotPaused 和 whenPaused,这些修饰符可以应用于合约的函数。请注意,仅仅包含此模块不会使它们可暂停,只有在修饰符就位后才会可暂停。
修饰符
函数
事件
whenNotPaused() 修饰符修饰符,使函数仅在合约未暂停时可调用。
要求:
whenPaused() 修饰符修饰符,使函数仅在合约暂停时可调用。
要求:
constructor() 内部函数以未暂停状态初始化合约。
paused() → bool 公共函数如果合约已暂停,则返回 true,否则返回 false。
_pause() 内部函数触发停止状态。
要求:
_unpause() 内部函数返回正常状态。
要求:
Paused(address account) 事件当暂停由 account 触发时发出。
Unpaused(address account) 事件当暂停由 account 解除时发出。
ReentrancyGuard合约模块,有助于防止对函数的重入调用。
继承自 ReentrancyGuard 将使 nonReentrant 修饰符可用,该修饰符可应用于函数以确保没有对它们的嵌套(重入)调用。
请注意,由于存在单个 nonReentrant 保护,因此标记为 nonReentrant 的函数可能不会相互调用。可以通过使这些函数成为 private,然后向它们添加 external nonReentrant 入口点来解决此问题。
| 如果你想了解更多关于重入以及防止重入的替代方法,请查看我们的博文 伊斯坦布尔之后的重入。 |
修饰符
函数
nonReentrant() 修饰符防止合约直接或间接地调用自身。
不支持从另一个 nonReentrant 函数调用 nonReentrant 函数。可以通过使 nonReentrant 函数为 external,并使其调用执行实际工作的 private 函数来防止这种情况发生。
constructor() 内部函数Address与地址类型相关的函数的集合
函数
isContract(address account) → bool 内部函数如果 account 是合约,则返回 true。
假设此函数返回 false 的地址是外部拥有的帐户 (EOA) 而不是合约是不安全的。<br>其中,isContract 将为以下类型的地址返回 false:<br>- 外部拥有的帐户<br> <br>- 正在构造的合约<br> <br>- 将创建合约的地址<br> <br>- 曾经存在合约但已被销毁的地址 |
sendValue(address payable recipient, uint256 amount) 内部函数Solidity 的 transfer 的替代方案:将 amount wei 发送到 recipient,转发所有可用的 gas 并在出错时恢复。
EIP1884 增加了某些操作码的 gas 成本,可能会使合约超过 transfer 施加的 2300 gas 限制,从而使它们无法通过 transfer 接收资金。sendValue 消除了此限制。
了解更多。
因为控制权已转移到 recipient,因此必须小心不要创建重入漏洞。考虑使用 ReentrancyGuard 或 checks-effects-interactions 模式。 |
functionCall(address target, bytes data) → bytes 内部函数使用底层 call 执行 Solidity 函数调用。plain`call` 是函数调用的不安全替代方案:请改用此函数。
如果 target 恢复并带有恢复原因,则此函数会将其弹出(类似于常规的 Solidity 函数调用)。
返回原始返回的数据。要转换为预期的返回值,请使用 abi.decode。
要求:
target 必须是合约。
使用 data 调用 target 不得恢复。
自 v3.1 起可用。
functionCall(address target, bytes data, string errorMessage) → bytes 内部函数与 functionCall 相同,但 errorMessage 作为 target 恢复时的回退恢复原因。
自 v3.1 起可用。
functionCallWithValue(address target, bytes data, uint256 value) → bytes 内部函数与 functionCall 相同,但也向 target 转移 value wei。
要求:
调用合约必须具有至少 value 的 ETH 余额。
调用的 Solidity 函数必须是 payable。
自 v3.1 起可用。
functionCallWithValue(address target, bytes data, uint256 value, string errorMessage) → bytes 内部函数与 functionCallWithValue 相同,但 errorMessage 作为 target 恢复时的回退恢复原因。
自 v3.1 起可用。
functionStaticCall(address target, bytes data) → bytes 内部函数与 functionCall 相同,但执行静态调用。
自 v3.3 起可用。
functionStaticCall(address target, bytes data, string errorMessage) → bytes 内部函数与 functionCall 相同,但执行静态调用。
自 v3.3 起可用。
functionDelegateCall(address target, bytes data) → bytes 内部函数与 functionCall 相同,但执行委托调用。
自 v3.4 起可用。
functionDelegateCall(address target, bytes data, string errorMessage) → bytes 内部函数与 functionCall 相同,但执行委托调用。
自 v3.4 起可用。
Arrays与数组类型相关的函数的集合。
函数
findUpperBound(uint256[] array, uint256 element) → uint256 内部函数搜索已排序的 array 并返回包含大于或等于 element 的值的第一个索引。如果不存在此类索引(即,数组中的所有值都严格小于 element),则返回数组长度。时间复杂度 O(log n)。
array 预计按升序排序,且不包含重复元素。
Counters提供只能递增或递减 1 的计数器。这可以用于例如跟踪映射中的元素数量、颁发 ERC721 id 或计数请求 id。
包含 using Counters for Counters.Counter;
由于不可能通过递增 1 使 256 位整数溢出,因此 increment 可以跳过 SafeMath 溢出检查,从而节省 gas。但这确实假设了正确的使用,即永远不会直接访问底层的 _value。
函数
current(struct Counters.Counter counter) → uint256 内部函数increment(struct Counters.Counter counter) 内部函数decrement(struct Counters.Counter counter) 内部函数Create2帮助程序,使 CREATE2 EVM 操作码的使用更容易、更安全。
CREATE2 可用于提前计算智能合约的部署地址,从而实现有趣的新机制,称为“反事实交互”。
有关更多信息,请参见 EIP。
函数
deploy(uint256 amount, bytes32 salt, bytes bytecode) → address 内部函数使用 CREATE2 部署合约。可以通过 computeAddress 提前知道合约的部署地址。
合约的字节码可以从 Solidity 中通过 type(contractName).creationCode 获得。
要求:
bytecode 不得为空。
salt 必须尚未被用于 bytecode。
工厂必须具有至少 amount 的余额。
如果 amount 为非零值,则 bytecode 必须具有 payable 构造函数。
computeAddress(bytes32 salt, bytes32 bytecodeHash) → address 内部函数返回如果通过 deploy 部署合约,该合约将存储的地址。bytecodeHash 或 salt 的任何更改都将导致新的目标地址。
computeAddress(bytes32 salt, bytes32 bytecodeHash, address deployer) → address 内部函数返回如果从位于 deployer 的合约通过 deploy 部署合约,该合约将存储的地址。如果 deployer 是此合约的地址,则返回与 computeAddress 相同的值。
EnumerableMap用于管理 Solidity 的可枚举变体的库
mapping
类型。
映射具有以下属性:
条目的添加、删除和存在检查以恒定时间 (O(1)) 完成。
条目的枚举以 O(n) 完成。不保证排序。
contract Example {
// 添加库方法
using EnumerableMap for EnumerableMap.UintToAddressMap;
// 声明一个集合状态变量
EnumerableMap.UintToAddressMap private myMap;
}
从 v3.0.0 开始,仅支持 uint256 → address ( UintToAddressMap) 类型的映射。
函数
set(struct EnumerableMap.UintToAddressMap map, uint256 key, address value) → bool 内部函数向映射添加键值对,或更新现有键的值。O(1)。
如果键已添加到映射,即它尚未存在,则返回 true。
remove(struct EnumerableMap.UintToAddressMap map, uint256 key) → bool 内部函数从集合中删除一个值。O(1)。
如果键已从映射中删除,即它存在,则返回 true。
contains(struct EnumerableMap.UintToAddressMap map, uint256 key) → bool 内部函数如果键在映射中,则返回 true。O(1)。
length(struct EnumerableMap.UintToAddressMap map) → uint256 内部函数返回映射中的元素数。O(1)。
at(struct EnumerableMap.UintToAddressMap map, uint256 index) → uint256, address 内部函数返回存储在集合中位置 index 处的元素。O(1)。
请注意,不保证数组内值的排序,并且当添加或删除更多值时,它可能会更改。
要求:
index 必须严格小于 length。tryGet(struct EnumerableMap.UintToAddressMap map, uint256 key) → bool, address 内部函数尝试返回与 key 关联的值。O(1)。
如果 key 不在映射中,则不会恢复。
自 v3.4 起可用。
get(struct EnumerableMap.UintToAddressMap map, uint256 key) → address 内部函数返回与 key 关联的值。O(1)。
要求:
key 必须在映射中。get(struct EnumerableMap.UintToAddressMap map, uint256 key, string errorMessage) → address 内部函数与 get 相同,当 key 不在映射中时,使用自定义错误消息。
此函数已弃用,因为它需要不必要地为错误消息分配内存。对于自定义恢复原因,请使用 tryGet。 |
EnumerableSet用于管理原始类型的集合的库。
集合具有以下属性:
元素的添加、删除和存在检查以恒定时间 (O(1)) 完成。
元素的枚举以 O(n) 完成。不保证排序。
contract Example {
// 添加库方法
using EnumerableSet for EnumerableSet.AddressSet;
// 声明一个集合状态变量
EnumerableSet.AddressSet private mySet;
}
截至 v3.3.0,支持 bytes32 ( Bytes32Set)、address ( AddressSet) 和 uint256 ( UintSet) 类型的集合。
函数
add(struct EnumerableSet.Bytes32Set set, bytes32 value) → bool 内部函数将一个值添加到一个集合中。O(1)。
如果该值已添加到集合中,即它尚未存在,则返回 true。
remove(struct EnumerableSet.Bytes32Set set, bytes32 value) → bool 内部函数从集合中删除一个值。O(1)。
如果该值已从集合中删除,即它存在,则返回 true。
contains(struct EnumerableSet.Bytes32Set set, bytes32 value) → bool 内部函数如果该值在集合中,则返回 true。O(1)。
length(struct EnumerableSet.Bytes32Set set) → uint256 内部函数返回集合中的值的数量。O(1)。
at(struct EnumerableSet.Bytes32Set set, uint256 index) → bytes32 内部函数返回存储在集合中位置 index 处的值。O(1)。
请注意,不保证数组内值的排序,并且当添加或删除更多值时,它可能会更改。
要求:
index 必须严格小于 length。add(struct EnumerableSet.AddressSet set, address value) → bool 内部函数将一个值添加到一个集合中。O(1)。
如果该值已添加到集合中,即它尚未存在,则返回 true。
remove(struct EnumerableSet.AddressSet set, address value) → bool 内部函数从集合中删除一个值。O(1)。
如果该值已从集合中删除,即它存在,则返回 true。
contains(struct EnumerableSet.AddressSet set, address value) → bool 内部函数如果该值在集合中,则返回 true。O(1)。
length(struct EnumerableSet.AddressSet set) → uint256 内部函数返回集合中的值的数量。O(1)。
at(struct EnumerableSet.AddressSet set, uint256 index) → address 内部函数返回存储在集合中位置 index 处的值。O(1)。
请注意,不保证数组内值的排序,并且当添加或删除更多值时,它可能会更改。
要求:
index 必须严格小于 length。add(struct EnumerableSet.UintSet set, uint256 value) → bool 内部函数将一个值添加到一个集合中。O(1)。
如果该值已添加到集合中,即它尚未存在,则返回 true。
remove(struct EnumerableSet.UintSet set, uint256 value) → bool 内部函数从集合中删除一个值。O(1)。
如果该值已从集合中删除,即它存在,则返回 true。
contains(struct EnumerableSet.UintSet set, uint256 value) → bool 内部函数如果该值在集合中,则返回 true。O(1)。
length(struct EnumerableSet.UintSet set) → uint256 内部函数返回集合上的值的数量。O(1)。
at(struct EnumerableSet.UintSet set, uint256 index) → uint256 内部函数返回存储在集合中位置 index 处的值。O(1)。
请注意,不保证数组内值的排序,并且当添加或删除更多值时,它可能会更改。
要求:
index 必须严格小于 length。SafeCast带有添加的溢出检查的 Solidity 的 uintXX/intXX 强制转换运算符的包装器。
在 Solidity 中,从 uint256/int256 向下转换不会在溢出时恢复。这很容易导致不需要的利用或错误,因为开发人员通常假设溢出会引发错误。SafeCast 通过在此类操作溢出时恢复事务来恢复这种直觉。
使用此库而不是未检查的操作可以消除一整类错误,因此建议始终使用它。
可以与 SafeMath 和 SignedSafeMath 组合以将其扩展到更小的类型,方法是在 uint256 和 int256 上执行所有数学运算,然后向下转换。
函数
toUint128(uint256 value) → uint128 内部函数从 uint256 返回向下转换的 uint128,在溢出时- 输入必须符合 32 位
toUint16(uint256 value) → uint16 internal从 uint256 返回降转型后的 uint16,在溢出时恢复(当输入大于最大的 uint16 时)。
对应于 Solidity 的 uint16 运算符。
要求:
toUint8(uint256 value) → uint8 internal从 uint256 返回降转型后的 uint8,在溢出时恢复(当输入大于最大的 uint8 时)。
对应于 Solidity 的 uint8 运算符。
要求:
toUint256(int256 value) → uint256 internal将有符号 int256 转换为无符号 uint256。
要求:
toInt128(int256 value) → int128 internal从 int256 返回降转型后的 int128,在溢出时恢复(当输入小于最小的 int128 或大于最大的 int128 时)。
对应于 Solidity 的 int128 运算符。
要求:
可用版本:v3.1
toInt64(int256 value) → int64 internal从 int256 返回降转型后的 int64,在溢出时恢复(当输入小于最小的 int64 或大于最大的 int64 时)。
对应于 Solidity 的 int64 运算符。
要求:
可用版本:v3.1
toInt32(int256 value) → int32 internal从 int256 返回降转型后的 int32,在溢出时恢复(当输入小于最小的 int32 或大于最大的 int32 时)。
对应于 Solidity 的 int32 运算符。
要求:
可用版本:v3.1
toInt16(int256 value) → int16 internal从 int256 返回降转型后的 int16,在溢出时恢复(当输入小于最小的 int16 或大于最大的 int16 时)。
对应于 Solidity 的 int16 运算符。
要求:
可用版本:v3.1
toInt8(int256 value) → int8 internal从 int256 返回降转型后的 int8,在溢出时恢复(当输入小于最小的 int8 或大于最大的 int8 时)。
对应于 Solidity 的 int8 运算符。
要求:
可用版本:v3.1
toInt256(uint256 value) → int256 internal将无符号 uint256 转换为有符号 int256。
要求:
Strings字符串操作。
函数
toString(uint256 value) → string internal将 uint256 转换为其 ASCII string 表示形式。
- 原文链接: docs.openzeppelin.com/co...
- 登链社区 AI 助手,为大家转译优秀英文文章,如有翻译不通的地方,还请包涵~
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!