SplitPayment.sol 2.6 KB

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