Payment
Outdated Version
This document is better viewed at https://docs.openzeppelin.com/contracts/api/payment
Utilities related to sending and receiving payments. Examples are PullPayment, which implements the best security practices when sending funds to third parties, and PaymentSplitter to receive incoming payments among a number of beneficiaries.
When transferring funds to and from untrusted third parties, there is always a security risk of reentrancy. If you would like to learn more about this and ways to protect against it, check out our blog post Reentrancy After Istanbul.
Utilities
PaymentSplitter
This contract allows to split Ether payments among a group of accounts. The sender does not need to be aware that the Ether will be split in this way, since it is handled transparently by the contract.
The split can be in equal parts or in any other arbitrary proportion. The way this is specified is by assigning each account to a number of shares. Of all the Ether that this contract receives, each account will then be able to claim an amount proportional to the percentage of total shares they were assigned.
PaymentSplitter
follows a pull payment model. This means that payments are not automatically forwarded to the
accounts but kept in this contract, and the actual transfer is triggered as a separate step by calling the release
function.
Functions
constructor(payees, shares_)
receive()
totalShares()
totalReleased()
shares(account)
released(account)
payee(index)
release(account)
Events
constructor(address[] payees, uint256[] shares_) *public*
Creates an instance of PaymentSplitter
where each account in payees
is assigned the number of shares at
the matching position in the shares
array.
All addresses in payees
must be non-zero. Both arrays must have the same non-zero length, and there must be no
duplicates in payees
.
receive() *external*
The Ether received will be logged with PaymentReceived events. Note that these events are not fully reliable: it’s possible for a contract to receive Ether without triggering this function. This only affects the reliability of the events, and not the actual splitting of Ether.
To learn more about this see the Solidity documentation for https://solidity.readthedocs.io/en/latest/contracts.html#fallback-function[fallback functions].
totalShares() → uint256 *public*
Getter for the total shares held by payees.
totalReleased() → uint256 *public*
Getter for the total amount of Ether already released.
shares(address account) → uint256 *public*
Getter for the amount of shares held by an account.
released(address account) → uint256 *public*
Getter for the amount of Ether already released to a payee.
payee(uint256 index) → address *public*
Getter for the address of the payee number index
.
release(address payable account) *public*
Triggers a transfer to account
of the amount of Ether they are owed, according to their percentage of the
total shares and their previous withdrawals.
PayeeAdded(address account, uint256 shares) *event*
PaymentReleased(address to, uint256 amount) *event*
PaymentReceived(address from, uint256 amount) *event*
PullPayment
Simple implementation of a pull-payment strategy, where the paying contract doesn’t interact directly with the receiver account, which must withdraw its payments itself.
Pull-payments are often considered the best practice when it comes to sending Ether, security-wise. It prevents recipients from blocking execution, and eliminates reentrancy concerns.
If you would like to learn more about reentrancy and alternative ways to protect against it, check out our blog post Reentrancy After Istanbul.
To use, derive from the PullPayment
contract, and use _asyncTransfer
instead of Solidity’s transfer
function. Payees can query their due
payments with payments, and retrieve them with withdrawPayments.
Functions
constructor() *internal*
withdrawPayments(address payable payee) *public*
Withdraw accumulated payments, forwarding all gas to the recipient.
Note that any account can call this function, not just the payee
.
This means that contracts unaware of the PullPayment
protocol can still
receive funds this way, by having a separate account call
withdrawPayments.
Forwarding all gas opens the door to reentrancy vulnerabilities. Make sure you trust the recipient, or are either following the checks-effects-interactions pattern or using ReentrancyGuard.
payments(address dest) → uint256 *public*
Returns the payments owed to an address.
_asyncTransfer(address dest, uint256 amount) *internal*
Called by the payer to store the sent amount as credit to be pulled. Funds sent in this way are stored in an intermediate Escrow contract, so there is no danger of them being spent before withdrawal.
Escrow
Escrow
Base escrow contract, holds funds designated for a payee until they withdraw them.
Intended usage: This contract (and derived escrow contracts) should be a
standalone contract, that only interacts with the contract that instantiated
it. That way, it is guaranteed that all Ether will be handled according to
the Escrow
rules, and there is no need to check for payable functions or
transfers in the inheritance tree. The contract that uses the escrow as its
payment method should be its owner, and provide public methods redirecting
to the escrow’s deposit and withdraw.
Functions
Ownable
Events
Ownable
depositsOf(address payee) → uint256 *public*
deposit(address payee) *public*
Stores the sent amount as credit to be withdrawn.
withdraw(address payable payee) *public*
Withdraw accumulated balance for a payee, forwarding all gas to the recipient.
Forwarding all gas opens the door to reentrancy vulnerabilities. Make sure you trust the recipient, or are either following the checks-effects-interactions pattern or using ReentrancyGuard.
Deposited(address payee, uint256 weiAmount) *event*
Withdrawn(address payee, uint256 weiAmount) *event*
ConditionalEscrow
Base abstract escrow to only allow withdrawal if a condition is met. Intended usage: See Escrow. Same usage guidelines apply here.
Functions
Escrow
Ownable
Events
Escrow
Ownable
withdrawalAllowed(address payee) → bool *public*
Returns whether an address is allowed to withdraw their funds. To be implemented by derived contracts.
withdraw(address payable payee) *public*
RefundEscrow
Escrow that holds funds for a beneficiary, deposited from multiple
parties.
Intended usage: See Escrow. Same usage guidelines apply here.
The owner account (that is, the contract that instantiates this
contract) may deposit, close the deposit period, and allow for either
withdrawal by the beneficiary, or refunds to the depositors. All interactions
with RefundEscrow
will be made through the owner contract.
Functions
constructor(beneficiary_)
state()
beneficiary()
deposit(refundee)
close()
enableRefunds()
beneficiaryWithdraw()
withdrawalAllowed(_)
ConditionalEscrow
Escrow
Ownable
Events
Escrow
Ownable
constructor(address payable beneficiary_) *public*
Constructor.
state() → enum RefundEscrow.State *public*
beneficiary() → address payable *public*
deposit(address refundee) *public*
Stores funds that may later be refunded.
close() *public*
Allows for the beneficiary to withdraw their funds, rejecting further deposits.
enableRefunds() *public*
Allows for refunds to take place, rejecting further deposits.
beneficiaryWithdraw() *public*
Withdraws the beneficiary’s funds.
withdrawalAllowed(address) → bool *public*
Returns whether refundees can withdraw their deposits (be refunded). The overridden function receives a 'payee' argument, but we ignore it here since the condition is global, not per-payee.