PaymentSplitter.sol 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  1. pragma solidity ^0.4.24;
  2. import "../math/SafeMath.sol";
  3. /**
  4. * @title PaymentSplitter
  5. * @dev This contract can be used when payments need to be received by a group
  6. * of people and split proportionately to some number of shares they own.
  7. */
  8. contract PaymentSplitter {
  9. using SafeMath for uint256;
  10. event PayeeAdded(address account, uint256 shares);
  11. event PaymentReleased(address to, uint256 amount);
  12. event PaymentReceived(address from, uint256 amount);
  13. uint256 private _totalShares;
  14. uint256 private _totalReleased;
  15. mapping(address => uint256) private _shares;
  16. mapping(address => uint256) private _released;
  17. address[] private _payees;
  18. /**
  19. * @dev Constructor
  20. */
  21. constructor(address[] payees, uint256[] shares) public payable {
  22. require(payees.length == shares.length);
  23. require(payees.length > 0);
  24. for (uint256 i = 0; i < payees.length; i++) {
  25. _addPayee(payees[i], shares[i]);
  26. }
  27. }
  28. /**
  29. * @dev payable fallback
  30. */
  31. function () external payable {
  32. emit PaymentReceived(msg.sender, msg.value);
  33. }
  34. /**
  35. * @return the total shares of the contract.
  36. */
  37. function totalShares() public view returns(uint256) {
  38. return _totalShares;
  39. }
  40. /**
  41. * @return the total amount already released.
  42. */
  43. function totalReleased() public view returns(uint256) {
  44. return _totalReleased;
  45. }
  46. /**
  47. * @return the shares of an account.
  48. */
  49. function shares(address account) public view returns(uint256) {
  50. return _shares[account];
  51. }
  52. /**
  53. * @return the amount already released to an account.
  54. */
  55. function released(address account) public view returns(uint256) {
  56. return _released[account];
  57. }
  58. /**
  59. * @return the address of a payee.
  60. */
  61. function payee(uint256 index) public view returns(address) {
  62. return _payees[index];
  63. }
  64. /**
  65. * @dev Release one of the payee's proportional payment.
  66. * @param account Whose payments will be released.
  67. */
  68. function release(address account) public {
  69. require(_shares[account] > 0);
  70. uint256 totalReceived = address(this).balance.add(_totalReleased);
  71. uint256 payment = totalReceived.mul(
  72. _shares[account]).div(
  73. _totalShares).sub(
  74. _released[account]
  75. );
  76. require(payment != 0);
  77. _released[account] = _released[account].add(payment);
  78. _totalReleased = _totalReleased.add(payment);
  79. account.transfer(payment);
  80. emit PaymentReleased(account, payment);
  81. }
  82. /**
  83. * @dev Add a new payee to the contract.
  84. * @param account The address of the payee to add.
  85. * @param shares_ The number of shares owned by the payee.
  86. */
  87. function _addPayee(address account, uint256 shares_) private {
  88. require(account != address(0));
  89. require(shares_ > 0);
  90. require(_shares[account] == 0);
  91. _payees.push(account);
  92. _shares[account] = shares_;
  93. _totalShares = _totalShares.add(shares_);
  94. emit PayeeAdded(account, shares_);
  95. }
  96. }