PaymentSplitterUpgradeable.sol 8.0 KB

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