@@ -3,9 +3,18 @@ pragma solidity ^0.5.0;
3
3
import "./escrow/Escrow.sol " ;
4
4
5
5
/**
6
- * @title PullPayment
7
- * @dev Base contract supporting async send for pull payments. Inherit from this
8
- * contract and use {_asyncTransfer} instead of send or transfer.
6
+ * @dev Simple implementation of a
7
+ * https://consensys.github.io/smart-contract-best-practices/recommendations/#favor-pull-over-push-for-external-calls[pull-payment]
8
+ * strategy, where the paying contract doesn't interact directly with the
9
+ * receiver account, which must withdraw its payments itself.
10
+ *
11
+ * Pull-payments are often considered the best practice when it comes to sending
12
+ * Ether, security-wise. It prevents recipients from blocking execution, and
13
+ * eliminates reentrancy concerns.
14
+ *
15
+ * To use, derive from the `PullPayment` contract, and use {_asyncTransfer}
16
+ * instead of Solidity's `transfer` function. Payees can query their due
17
+ * payments with {payments}, and retrieve them with {withdrawPayments}.
9
18
*/
10
19
contract PullPayment {
11
20
Escrow private _escrow;
@@ -15,15 +24,20 @@ contract PullPayment {
15
24
}
16
25
17
26
/**
18
- * @dev Withdraw accumulated balance.
19
- * @param payee Whose balance will be withdrawn.
27
+ * @dev Withdraw accumulated payments.
28
+ * @param payee Whose payments will be withdrawn.
29
+ *
30
+ * Note that _any_ account can call this function, not just the `payee`.
31
+ * This means that contracts unaware of the `PullPayment` protocol can still
32
+ * receive funds this way, by having a separate account call
33
+ * {withdrawPayments}.
20
34
*/
21
35
function withdrawPayments (address payable payee ) public {
22
36
_escrow.withdraw (payee);
23
37
}
24
38
25
39
/**
26
- * @dev Returns the credit owed to an address.
40
+ * @dev Returns the payments owed to an address.
27
41
* @param dest The creditor's address.
28
42
*/
29
43
function payments (address dest ) public view returns (uint256 ) {
@@ -34,6 +48,9 @@ contract PullPayment {
34
48
* @dev Called by the payer to store the sent amount as credit to be pulled.
35
49
* @param dest The destination address of the funds.
36
50
* @param amount The amount to transfer.
51
+ *
52
+ * Funds sent in this way are stored in an intermediate {Escrow} contract, so
53
+ * there is no danger of them being spent before withdrawal.
37
54
*/
38
55
function _asyncTransfer (address dest , uint256 amount ) internal {
39
56
_escrow.deposit.value (amount)(dest);
0 commit comments