/**
 * @title PaymentSplitter
 * This contract allows the splitting of Filecoin payments among a group of accounts. The sender does not need to be aware
 * that the FIL will be split in this way, since it is handled transparently by the contract.
 *
 * The split can be in equal parts or in any other arbitrary proportion. The way this is specified is by assigning each
 * account to a number of shares. Of all the FIL that this contract receives, each account will then be able to claim
 * an amount proportional to the percentage of total shares they were assigned. The distribution of shares is set at the
 * time of contract deployment and can't be updated thereafter.
 *
 * `PaymentSplitter` follows a _pull payment_ model. This means that payments are not automatically forwarded to the
 * accounts but kept in this contract, and the actual transfer is triggered as a separate step by calling the {release}
 * function.
 *
 */
contract PaymentSplitter {
		// Emitted events 
		event PayeeAdded(address account, uint256 shares);
    event PaymentReleased(address to, uint256 amount);
    event PaymentReceived(address from, uint256 amount);
		
		// Running logs of the total shares to dispense and the current amount released. 
    uint256 private _totalShares;
    uint256 private _totalReleased;

	  // Maps of payees to shares owed and shares already released. 
    mapping(address => uint256) private _shares;
    mapping(address => uint256) private _released;
    address[] private _payees;
    /**
     * @dev Creates an instance of `PaymentSplitter` where each account in `payees` is assigned the number of shares at
     * the matching position in the `shares` array. Instantiates _shares, _payees, _totalShares.  
     *
     * All addresses in `payees` must be non-zero. Both arrays must have the same non-zero length, and there must be no
     * duplicates in `payees`.
     */
    constructor(address[] memory payees, uint256[] memory shares_) payable {...}

    /**
     * @dev The FIL received will be logged with {PaymentReceived} events. Note that these events are not fully
     * reliable: it's possible for a contract to receive FIL without triggering this function. This only affects the
     * reliability of the events, and not the actual splitting of FIL.
     */
    receive() external payable virtual {...}

    /**
     * @dev Getter for the total shares held by payees (_totalShares).
     */
    function totalShares() public view returns (uint256) {...}

    /**
     * @dev Getter for the total amount of FIL already released (_totalReleased).
     */
    function totalReleased() public view returns (uint256) {...}

    /**
     * @dev Getter for the amount of shares held by an account.
     */
    function shares(address account) public view returns (uint256) {...}

    /**
     * @dev Getter for the amount of FIL already released to a payee.
     */
    function released(address account) public view returns (uint256) {...}

    /**
     * @dev Getter for the address of the payee number `index`.
     */
    function payee(uint256 index) public view returns (address) {...}

    /**
     * @dev Getter for the amount of payee's releasable FIL.
     */
    function releasable(address account) public view returns (uint256) {...}

    /**
     * @dev Triggers a transfer to `account` of the amount of FIL they are owed, according to their percentage of the
     * total shares and their previous withdrawals.
     */
    function release(address payable account) public virtual {...}

    /**
     * @dev internal logic for computing the pending payment of an `account` given the token historical balances and
     * already released amounts.
     */
    function _pendingPayment(
        address account,
        uint256 totalReceived,
        uint256 alreadyReleased
    ) private view returns (uint256) {...}

    /**
     * @dev Add a new payee to the contract.
     * @param account The address of the payee to add.
     * @param shares_ The number of shares owned by the payee.
     */
    function _addPayee(address account, uint256 shares_) private {...}