本文介绍了OpenZeppelin Contracts库中常用的实用工具,包括密码学(ECDSA签名验证、Merkle证明验证),合约自检(ERC165接口检测),数学运算(SafeMath安全计算),支付(PaymentSplitter、PullPayment、Escrow),集合(EnumerableSet、EnumerableMap)以及其他实用工具(Address, Counters)。
你当前阅读的不是此文档的最新版本。5.x 是最新版本。
OpenZeppelin 合约提供了大量可在项目中使用的实用工具。以下是一些更受欢迎的工具。
ECDSA
提供了用于恢复和管理以太坊账户 ECDSA 签名的函数。这些签名通常通过 web3.eth.sign
生成,并且是一个 65 字节的数组(在 Solidity 中是 bytes
类型),排列方式如下:[[v (1)], [r (32)], [s (32)]]
。
可以使用 ECDSA.recover
恢复数据签名者,并比较其地址以验证签名。大多数钱包会对要签名的数据进行哈希处理,并添加前缀 '\x19Ethereum Signed Message:\n',因此在尝试恢复以太坊签名消息哈希的签名者时,你将需要使用 toEthSignedMessageHash
。
using ECDSA for bytes32;
function _verify(bytes32 data, address account) pure returns (bool) {
return keccack256(data)
.toEthSignedMessageHash()
.recover(signature) == account;
}
正确进行签名验证并非易事:请务必完整阅读并理解 ECDSA 的文档。 |
MerkleProof
提供了 verify
,可以证明某个值是 Merkle 树 的一部分。
在 Solidity 中,了解合约是否支持你要使用的接口通常很有帮助。ERC165 是一个有助于进行运行时接口检测的标准。合约提供了用于在合约中实现 ERC165 和查询其他合约的助手:
IERC165
- 这是定义 supportsInterface
的 ERC165 接口。实现 ERC165 时,需要符合此接口。
ERC165
- 如果你想使用合约存储中的查找表来支持接口检测,请继承此合约。你可以使用 _registerInterface(bytes4)
注册接口:查看作为 ERC721 实现一部分的示例用法。
ERC165Checker
- ERC165Checker 简化了检查合约是否支持你关心的接口的过程。
包含 using ERC165Checker for address;
[myAddress._supportsAllInterfaces(bytes4[
](https://docs.openzeppelin.com/contracts/3.x/api/introspection#ERC165Checker-_supportsAllInterfaces-address-bytes4---) )
]
contract MyContract {
using ERC165Checker for address;
bytes4 private InterfaceId_ERC721 = 0x80ac58cd;
/**
* @dev 从此合约向其他人转移 ERC721 token
*/
function transferERC721(
address token,
address to,
uint256 tokenId
)
public
{
require(token.supportsInterface(InterfaceId_ERC721), "IS_NOT_721_TOKEN");
IERC721(token).transferFrom(address(this), to, tokenId);
}
}
OpenZeppelin 合约提供的最受欢迎的数学相关库是 SafeMath
,它提供了可以保护你的合约免受溢出和下溢影响的数学函数。
通过 using SafeMath for uint256;
包含合约,然后调用函数:
myNumber.add(otherNumber)
myNumber.sub(otherNumber)
myNumber.div(otherNumber)
myNumber.mul(otherNumber)
myNumber.mod(otherNumber)
简单!
想要在多人之间分配一些付款吗?也许你有一个应用程序,将艺术品购买的 30% 发送给原始创作者,并将 70% 的利润发送给当前所有者;你可以使用 PaymentSplitter
构建它!
在 Solidity 中,盲目地向帐户汇款存在一些安全问题,因为它允许他们执行任意代码。你可以在 以太坊智能合约最佳实践 网站上阅读有关这些安全问题的更多信息。解决重入和停止问题的方法之一是,不立即将 Ether 发送到需要的帐户,你可以使用 PullPayment
,它提供了一个 _asyncTransfer
函数,用于向某事物汇款并请求他们稍后 withdrawPayments()
它。
如果你想托管一些资金,请查看 Escrow
和 ConditionalEscrow
以管理一些托管 Ether 的发布。
如果你需要比 Solidity 的原生数组和映射更强大的集合支持,请查看 EnumerableSet
和 EnumerableMap
。它们类似于映射,因为它们以恒定时间存储和删除元素,并且不允许重复条目,但它们也支持 枚举,这意味着你可以轻松地查询链上和链下的所有存储条目。
想要检查地址是否是合约? 使用 Address
和 Address.isContract()
。
想要跟踪一些每次需要另一个数字时都会递增 1 的数字?查看 Counters
。这对于很多事情都很有用,例如创建增量标识符,如 ERC721 指南 所示。
- 原文链接: docs.openzeppelin.com/co...
- 登链社区 AI 助手,为大家转译优秀英文文章,如有翻译不通的地方,还请包涵~
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!