本文档介绍了OpenZeppelin Contracts库中与支付相关的实用工具,包括PaymentSplitter
,用于将以太币支付分配给多个账户,以及PullPayment
,它实现了一种安全的资金发送方式,接收者需要主动提取资金。此外,还介绍了Escrow合约,用于在满足条件前持有资金。
你当前阅读的不是此文档的最新版本。5.x 是最新版本。
|---|---| | | 建议在 https://docs.openzeppelin.com/contracts/api/payment 查看此文档 |
与发送和接收付款相关的实用程序。示例包括 PullPayment
,它在向第三方发送资金时实现了最佳的安全实践,以及 PaymentSplitter
用于接收多个受益人之间的传入付款。
|---|---| | | 当与不受信任的第三方之间转移资金时,始终存在重入的安全风险。如果你想了解更多关于此的信息以及保护免受其侵害的方法,请查看我们的博客文章 伊斯坦布尔之后的重入。 |
PaymentSplitter
此合约允许在一组帐户之间分配以太币付款。发送者无需知道 以太币将以这种方式分配,因为它由合约透明地处理。
分配可以是等份,也可以是任何其他任意比例。指定此方式的方法是将每个 帐户分配给一定数量的份额。在此合约收到的所有以太币中,每个帐户都能够提取 与其分配的总份额百分比成比例的金额。
PaymentSplitter
遵循提取付款模型。这意味着付款不会自动转发到
帐户,而是保留在此合约中,并且通过调用 release
来触发实际转移。
函数。
函数
事件
constructor(address[] payees, uint256[] shares_)
public创建 PaymentSplitter
的实例,其中 payees
中的每个帐户都分配了
shares
数组中匹配位置的份额数量。
payees
中的所有地址都必须为非零。两个数组必须具有相同的非零长度,并且 payees
中不得有重复项。
receive()
external收到的以太币将使用 PaymentReceived
事件记录。请注意,这些事件并非完全
可靠:合约有可能在不触发此函数的情况下收到以太币。这只会影响
事件的可靠性,而不是以太币的实际分配。
要了解更多关于此的信息,请参阅 Solidity 文档中的 回退\ 函数。
totalShares() → uint256
public获取收款人持有的总份额。
totalReleased() → uint256
public获取已释放的以太币总额。
shares(address account) → uint256
public获取帐户持有的份额数量。
released(address account) → uint256
public获取已释放给收款人的以太币数量。
payee(uint256 index) → address
public获取收款人编号 index
的地址。
release(address payable account)
public根据 account
的股份总额百分比及其之前的提取,触发向 account
转移欠其的以太币金额。
PayeeAdded(address account, uint256 shares)
eventPaymentReleased(address to, uint256 amount)
eventPaymentReceived(address from, uint256 amount)
eventPullPayment
提取付款 策略的简单实现,其中付款合约不直接与 收款人帐户交互,收款人帐户必须自行提取其付款。
在安全方面,提取付款通常被认为是发送 以太币的最佳实践。它可以防止收款人阻止执行,并消除重入问题。
|---|---| | | 如果你想了解更多关于重入以及替代方法的信息<br>保护免受其侵害,请查看我们的博客文章<br>伊斯坦布尔之后的重入。 |
要使用,请从 PullPayment
合约派生,并使用 _asyncTransfer
而不是 Solidity 的 transfer
函数。收款人可以使用 payments
查询其应付款项,并使用 withdrawPayments
检索它们。
函数
constructor()
internalwithdrawPayments(address payable payee)
public提取累积的付款,将所有 gas 转发给收款人。
请注意,任何帐户都可以调用此函数,而不仅仅是 payee
。
这意味着不了解 PullPayment
协议的合约仍然可以
通过让一个单独的帐户调用
withdrawPayments
来接收资金。
|---|---|
| | 转发所有 gas 会打开重入漏洞的大门。<br>确保你信任收款人,或者<br>要么遵循检查-效果-交互模式,要么使用 ReentrancyGuard
。 |
payments(address dest) → uint256
public返回欠某个地址的付款。
_asyncTransfer(address dest, uint256 amount)
internal由付款人调用以存储发送的金额作为要提取的信用额度。
以这种方式发送的资金存储在中间的 Escrow
合约中,因此
没有在提取之前花费它们的危险。
Escrow
基本托管合约,持有指定给收款人的资金,直到他们 提取它们。
预期用法:此合约(以及派生的托管合约)应该是一个
独立的合约,仅与实例化它的合约交互。
这样,可以保证所有以太币都将按照
Escrow
规则处理,并且无需检查继承树中的 payable 函数或
转移。使用托管作为其
付款方法的合约应该是其所有者,并提供重定向到
托管的存款和提取的公共方法。
函数
可拥有
事件
可拥有
depositsOf(address payee) → uint256
publicdeposit(address payee)
public存储发送的金额作为要提取的信用额度。
withdraw(address payable payee)
public提取收款人的累积余额,将所有 gas 转发给 收款人。
|---|---|
| | 转发所有 gas 会打开重入漏洞的大门。<br>确保你信任收款人,或者<br>要么遵循检查-效果-交互模式,要么使用 ReentrancyGuard
。 |
Deposited(address payee, uint256 weiAmount)
eventWithdrawn(address payee, uint256 weiAmount)
eventConditionalEscrow
仅当满足条件时才允许提取的基础抽象托管。
预期用法:请参阅 Escrow
。此处适用相同的使用指南。
函数
托管
可拥有
事件
托管
可拥有
withdrawalAllowed(address payee) → bool
public返回是否允许某个地址提取其资金。要由派生合约实现。
withdraw(address payable payee)
publicRefundEscrow
为受益人持有资金,由多个
各方存入的托管。
预期用法:请参阅 Escrow
。此处适用相同的使用指南。
所有者帐户(即实例化此
合约的合约)可能会存入资金,关闭存款期,并允许
受益人提取或退款给存款人。与 RefundEscrow
的所有交互
都将通过所有者合约进行。
函数
ConditionalEscrow
托管
可拥有
事件
托管
可拥有
constructor(address payable beneficiary_)
public构造函数。
state() → enum RefundEscrow.State
publicbeneficiary() → address payable
publicdeposit(address refundee)
public存储以后可能被退还的资金。
close()
public允许受益人提取其资金,拒绝 进一步的存款。
enableRefunds()
public允许进行退款,拒绝 进一步的存款。
beneficiaryWithdraw()
public提取受益人的资金。
withdrawalAllowed(address) → bool
public返回是否允许退款人提取其存款(获得退款)。重写后的函数接收一个 “payee”参数,但我们在此处忽略它,因为该条件是全局的,而不是每个收款人的。
RefundsClosed()
eventRefundsEnabled()
event
- 原文链接: docs.openzeppelin.com/co...
- 登链社区 AI 助手,为大家转译优秀英文文章,如有翻译不通的地方,还请包涵~
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!