PaymentSplitter.sol 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204
  1. // SPDX-License-Identifier: MIT
  2. // OpenZeppelin Contracts v4.4.1 (finance/PaymentSplitter.sol)
  3. pragma solidity ^0.8.0;
  4. import "../token/ERC20/utils/SafeERC20.sol";
  5. import "../utils/Address.sol";
  6. import "../utils/Context.sol";
  7. /**
  8. * @title PaymentSplitter
  9. * @dev This contract allows to split Ether payments among a group of accounts. The sender does not need to be aware
  10. * that the Ether will be split in this way, since it is handled transparently by the contract.
  11. *
  12. * The split can be in equal parts or in any other arbitrary proportion. The way this is specified is by assigning each
  13. * account to a number of shares. Of all the Ether that this contract receives, each account will then be able to claim
  14. * an amount proportional to the percentage of total shares they were assigned.
  15. *
  16. * `PaymentSplitter` follows a _pull payment_ model. This means that payments are not automatically forwarded to the
  17. * accounts but kept in this contract, and the actual transfer is triggered as a separate step by calling the {release}
  18. * function.
  19. *
  20. * NOTE: This contract assumes that ERC20 tokens will behave similarly to native tokens (Ether). Rebasing tokens, and
  21. * tokens that apply fees during transfers, are likely to not be supported as expected. If in doubt, we encourage you
  22. * to run tests before sending real value to this contract.
  23. */
  24. contract PaymentSplitter is Context {
  25. event PayeeAdded(address account, uint256 shares);
  26. event PaymentReleased(address to, uint256 amount);
  27. event ERC20PaymentReleased(IERC20 indexed token, address to, uint256 amount);
  28. event PaymentReceived(address from, uint256 amount);
  29. uint256 private _totalShares;
  30. uint256 private _totalReleased;
  31. mapping(address => uint256) private _shares;
  32. mapping(address => uint256) private _released;
  33. address[] private _payees;
  34. mapping(IERC20 => uint256) private _erc20TotalReleased;
  35. mapping(IERC20 => mapping(address => uint256)) private _erc20Released;
  36. /**
  37. * @dev Creates an instance of `PaymentSplitter` where each account in `payees` is assigned the number of shares at
  38. * the matching position in the `shares` array.
  39. *
  40. * All addresses in `payees` must be non-zero. Both arrays must have the same non-zero length, and there must be no
  41. * duplicates in `payees`.
  42. */
  43. constructor(address[] memory payees, uint256[] memory shares_) payable {
  44. require(payees.length == shares_.length, "PaymentSplitter: payees and shares length mismatch");
  45. require(payees.length > 0, "PaymentSplitter: no payees");
  46. for (uint256 i = 0; i < payees.length; i++) {
  47. _addPayee(payees[i], shares_[i]);
  48. }
  49. }
  50. /**
  51. * @dev The Ether received will be logged with {PaymentReceived} events. Note that these events are not fully
  52. * reliable: it's possible for a contract to receive Ether without triggering this function. This only affects the
  53. * reliability of the events, and not the actual splitting of Ether.
  54. *
  55. * To learn more about this see the Solidity documentation for
  56. * https://solidity.readthedocs.io/en/latest/contracts.html#fallback-function[fallback
  57. * functions].
  58. */
  59. receive() external payable virtual {
  60. emit PaymentReceived(_msgSender(), msg.value);
  61. }
  62. /**
  63. * @dev Getter for the total shares held by payees.
  64. */
  65. function totalShares() public view returns (uint256) {
  66. return _totalShares;
  67. }
  68. /**
  69. * @dev Getter for the total amount of Ether already released.
  70. */
  71. function totalReleased() public view returns (uint256) {
  72. return _totalReleased;
  73. }
  74. /**
  75. * @dev Getter for the total amount of `token` already released. `token` should be the address of an IERC20
  76. * contract.
  77. */
  78. function totalReleased(IERC20 token) public view returns (uint256) {
  79. return _erc20TotalReleased[token];
  80. }
  81. /**
  82. * @dev Getter for the amount of shares held by an account.
  83. */
  84. function shares(address account) public view returns (uint256) {
  85. return _shares[account];
  86. }
  87. /**
  88. * @dev Getter for the amount of Ether already released to a payee.
  89. */
  90. function released(address account) public view returns (uint256) {
  91. return _released[account];
  92. }
  93. /**
  94. * @dev Getter for the amount of `token` tokens already released to a payee. `token` should be the address of an
  95. * IERC20 contract.
  96. */
  97. function released(IERC20 token, address account) public view returns (uint256) {
  98. return _erc20Released[token][account];
  99. }
  100. /**
  101. * @dev Getter for the address of the payee number `index`.
  102. */
  103. function payee(uint256 index) public view returns (address) {
  104. return _payees[index];
  105. }
  106. /**
  107. * @dev Getter for the amount of payee's releasable Ether.
  108. */
  109. function releasable(address account) public view returns (uint256) {
  110. uint256 totalReceived = address(this).balance + totalReleased();
  111. return _pendingPayment(account, totalReceived, released(account));
  112. }
  113. /**
  114. * @dev Getter for the amount of payee's releasable `token` tokens. `token` should be the address of an
  115. * IERC20 contract.
  116. */
  117. function releasable(IERC20 token, address account) public view returns (uint256) {
  118. uint256 totalReceived = token.balanceOf(address(this)) + totalReleased(token);
  119. return _pendingPayment(account, totalReceived, released(token, account));
  120. }
  121. /**
  122. * @dev Triggers a transfer to `account` of the amount of Ether they are owed, according to their percentage of the
  123. * total shares and their previous withdrawals.
  124. */
  125. function release(address payable account) public virtual {
  126. require(_shares[account] > 0, "PaymentSplitter: account has no shares");
  127. uint256 payment = releasable(account);
  128. require(payment != 0, "PaymentSplitter: account is not due payment");
  129. _released[account] += payment;
  130. _totalReleased += payment;
  131. Address.sendValue(account, payment);
  132. emit PaymentReleased(account, payment);
  133. }
  134. /**
  135. * @dev Triggers a transfer to `account` of the amount of `token` tokens they are owed, according to their
  136. * percentage of the total shares and their previous withdrawals. `token` must be the address of an IERC20
  137. * contract.
  138. */
  139. function release(IERC20 token, address account) public virtual {
  140. require(_shares[account] > 0, "PaymentSplitter: account has no shares");
  141. uint256 payment = releasable(token, account);
  142. require(payment != 0, "PaymentSplitter: account is not due payment");
  143. _erc20Released[token][account] += payment;
  144. _erc20TotalReleased[token] += payment;
  145. SafeERC20.safeTransfer(token, account, payment);
  146. emit ERC20PaymentReleased(token, account, payment);
  147. }
  148. /**
  149. * @dev internal logic for computing the pending payment of an `account` given the token historical balances and
  150. * already released amounts.
  151. */
  152. function _pendingPayment(
  153. address account,
  154. uint256 totalReceived,
  155. uint256 alreadyReleased
  156. ) private view returns (uint256) {
  157. return (totalReceived * _shares[account]) / _totalShares - alreadyReleased;
  158. }
  159. /**
  160. * @dev Add a new payee to the contract.
  161. * @param account The address of the payee to add.
  162. * @param shares_ The number of shares owned by the payee.
  163. */
  164. function _addPayee(address account, uint256 shares_) private {
  165. require(account != address(0), "PaymentSplitter: account is the zero address");
  166. require(shares_ > 0, "PaymentSplitter: shares are 0");
  167. require(_shares[account] == 0, "PaymentSplitter: account already has shares");
  168. _payees.push(account);
  169. _shares[account] = shares_;
  170. _totalShares = _totalShares + shares_;
  171. emit PayeeAdded(account, shares_);
  172. }
  173. }