123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148 |
- pragma solidity ^0.4.15;
- import '../ReentrancyGuard.sol';
- import '../math/SafeMath.sol';
- /**
- * @title SplitPayment
- * @dev Base contract supporting the distribution of funds send to this contract to multiple payees.
- */
- contract SplitPayment is ReentrancyGuard {
- using SafeMath for uint256;
- struct Payee {
- address addr;
- uint256 shares;
- }
- uint256 public totalShares = 0;
- uint256 public maxPayees = 0;
- mapping(address => uint256) payeeIndex;
- Payee[] payees;
- /**
- * @dev Constructor
- * @param _maxPayees Total number of payees allowed. Zero for no limit.
- */
- function SplitPayment(uint256 _maxPayees) {
- maxPayees = _maxPayees;
- }
- /**
- * @dev Modifier that throws if you want to distribute funds and you are not a payee.
- */
- modifier canDistribute() {
- require(isPayee(msg.sender));
- _;
- }
- /**
- * @dev Modifier that throws if not allowed to update payees.
- * Override from child contract with your own requirements for access control.
- */
- modifier canUpdate() {
- _;
- }
- /**
- * @dev Add a new payee to the contract.
- * @param _payee The address of the payee to add.
- * @param _shares The number of shares owned by the payee.
- */
- function addPayee(address _payee, uint256 _shares) public canUpdate {
- require(_payee != address(0));
- require(_shares > 0);
- require(!isPayee(_payee));
- require(maxPayees == 0 || payees.length.add(1) <= maxPayees);
- payees.push(Payee(_payee, _shares));
- payeeIndex[_payee] = payees.length;
- totalShares = totalShares.add(_shares);
- }
- /**
- * @dev Add multiple payees to the contract.
- * @param _payees An array of addresses of payees to add.
- * @param _shares An array of the shares corresponding to each payee in the _payees array.
- */
- function addPayeeMany(address[] _payees, uint256[] _shares) public canUpdate {
- require(_payees.length == _shares.length);
- require(maxPayees == 0 || payees.length.add(_payees.length) <= maxPayees);
- for (uint256 i = 0; i < _payees.length; i++) {
- addPayee(_payees[i], _shares[i]);
- }
- }
- /**
- * @dev Return true if the payee is in the contract.
- * @param _payee The address of the payee to check.
- */
- function isPayee(address _payee) public constant returns (bool) {
- return payeeIndex[_payee] > 0;
- }
- /**
- * @dev Return the number of payees in the contract.
- */
- function getPayeeCount() public constant returns (uint256) {
- return payees.length;
- }
- /**
- * @dev Return the address of the payee and its shares.
- * Throws if the payee is not in the contract.
- * @param _payee The address of the payee to get.
- */
- function getPayee(address _payee) public constant returns (address, uint256) {
- require(isPayee(_payee));
- return getPayeeAtIndex(payeeIndex[_payee] - 1);
- }
- /**
- * @dev Return the address of the payee and its shares by index.
- * Allows iterating through the payee list from a client by knowing the payee count.
- * @param _idx The index of the payee in the internal list.
- */
- function getPayeeAtIndex(uint256 _idx) public constant returns (address, uint256) {
- require(_idx < payees.length);
- return (payees[_idx].addr, payees[_idx].shares);
- }
- /**
- * @dev Perform the payment to a payee.
- * This can be overriden to provide different transfer mechanisms.
- * @param _payee The address of the payee to be paid.
- * @param _amount The amount for the payment.
- */
- function pay(address _payee, uint256 _amount) internal {
- _payee.transfer(_amount);
- }
- /**
- * @dev Return the total amount of funds available for distribution.
- */
- function toDistribute() internal returns (uint256) {
- return this.balance;
- }
- /**
- * @dev Send payments to the registered payees according to their shares and the total
- * amount of funds to distribute.
- */
- function distributeFunds() public canDistribute nonReentrant {
- uint256 amountDistribute = toDistribute();
- assert(amountDistribute > 0);
- Payee memory payee;
- for (uint256 i = 0; i < payees.length; i++) {
- payee = payees[i];
- uint256 amount = amountDistribute.mul(payee.shares).div(totalShares);
- pay(payee.addr, amount);
- }
- }
- }
|