contract DividendTokenERC667 is ERC667, Ownable
{
    using SafeMath for uint256;

    // How dividends work:
    //
    // - A "point" is a fraction of a Wei (1e-32), it's used to reduce rounding errors.
    //
    // - totalPointsPerToken represents how many points each token is entitled to
    //   from all the dividends ever received. Each time a new deposit is made, it
    //   is incremented by the points oweable per token at the time of deposit:
    //     (depositAmtInWei * POINTS_PER_WEI) / totalSupply
    //
    // - Each account has a `creditedPoints` and `lastPointsPerToken`
    //   - lastPointsPerToken:
    //       The value of totalPointsPerToken the last time `creditedPoints` was changed.
    //   - creditedPoints:
    //       How many points have been credited to the user. This is incremented by:
    //         (`totalPointsPerToken` - `lastPointsPerToken` * balance) via
    //         `.updateCreditedPoints(account)`. This occurs anytime the balance changes
    //         (transfer, mint, burn).
    //
    // - .collectOwedDividends() calls .updateCreditedPoints(account), converts points
    //   to wei and pays account, then resets creditedPoints[account] to 0.
    //
    // - "Credit" goes to Nick Johnson for the concept.
    //
    uint constant POINTS_PER_WEI = 1e32;
    uint public dividendsTotal;
    uint public dividendsCollected;
    uint public totalPointsPerToken;
    mapping (address => uint) public creditedPoints;
    mapping (address => uint) public lastPointsPerToken;

    // Events
    event CollectedDividends(uint time, address indexed account, uint amount);
    event DividendReceived(uint time, address indexed sender, uint amount);

    constructor(uint256 _totalSupply, address _custom_owner)
    public
    ERC667("Noteshares Token", "NST")
    Ownable(_custom_owner)
    {
        totalSupply = _totalSupply;
    }

    // Upon receiving payment, increment lastPointsPerToken.
    function receivePayment()
    internal
    {
        if (msg.value == 0) return;
        // POINTS_PER_WEI is 1e32.
        // So, no multiplication overflow unless msg.value > 1e45 wei (1e27 ETH)
        totalPointsPerToken = totalPointsPerToken.add((msg.value.mul(POINTS_PER_WEI)).div(totalSupply));
        dividendsTotal = dividendsTotal.add(msg.value);
        emit DividendReceived(now, msg.sender, msg.value);
    }
    /*************************************************************/
    /********** PUBLIC FUNCTIONS *********************************/
    /*************************************************************/

    // Normal ERC20 transfer, except before transferring
    //  it credits points for both the sender and receiver.
    function transfer(address _to, uint _value)
    public
    returns (bool success)
    {
        // ensure tokens are not frozen.
        _updateCreditedPoints(msg.sender);
        _updateCreditedPoints(_to);
        return ERC20.transfer(_to, _value);
    }

    // Normal ERC20 transferFrom, except before transferring
    //  it credits points for both the sender and receiver.
    function transferFrom(address _from, address _to, uint256 _value)
    public
    returns (bool success)
    {
        _updateCreditedPoints(_from);
        _updateCreditedPoints(_to);
        return ERC20.transferFrom(_from, _to, _value);
    }

    // Normal ERC667 transferAndCall, except before transferring
    //  it credits points for both the sender and receiver.
    function transferAndCall(address _to, uint _value, bytes _data)
    public
    returns (bool success)
    {
        _updateCreditedPoints(msg.sender);
        _updateCreditedPoints(_to);
        return ERC667.transferAndCall(_to, _value, _data);
    }

    // Updates creditedPoints, sends all wei to the owner
    function collectOwedDividends()
    internal
    returns (uint _amount)
    {
        // update creditedPoints, store amount, and zero it.
        _updateCreditedPoints(msg.sender);
        _amount = creditedPoints[msg.sender].div(POINTS_PER_WEI);
        creditedPoints[msg.sender] = 0;
        dividendsCollected = dividendsCollected.add(_amount);
        emit CollectedDividends(now, msg.sender, _amount);
        require(msg.sender.call.value(_amount)());
    }


    /*************************************************************/
    /********** PRIVATE METHODS / VIEWS **************************/
    /*************************************************************/
    // Credits _account with whatever dividend points they haven't yet been credited.
    //  This needs to be called before any user's balance changes to ensure their
    //  "lastPointsPerToken" credits their current balance, and not an altered one.
    function _updateCreditedPoints(address _account)
    private
    {
        creditedPoints[_account] = creditedPoints[_account].add(_getUncreditedPoints(_account));
        lastPointsPerToken[_account] = totalPointsPerToken;
    }

    // For a given account, returns how many Wei they haven't yet been credited.
    function _getUncreditedPoints(address _account)
    private
    view
    returns (uint _amount)
    {
        uint _pointsPerToken = totalPointsPerToken.sub(lastPointsPerToken[_account]);
        // The upper bound on this number is:
        //   ((1e32 * TOTAL_DIVIDEND_AMT) / totalSupply) * balances[_account]
        // Since totalSupply >= balances[_account], this will overflow only if
        //   TOTAL_DIVIDEND_AMT is around 1e45 wei. Not ever going to happen.
        return _pointsPerToken.mul(balanceOf[_account]);
    }


    /*************************************************************/
    /********* CONSTANTS *****************************************/
    /*************************************************************/
    // Returns how many wei a call to .collectOwedDividends() would transfer.
    function getOwedDividends(address _account)
    public
    constant
    returns (uint _amount)
    {
        return (_getUncreditedPoints(_account).add(creditedPoints[_account])).div(POINTS_PER_WEI);
    }
}
/*********************************************************
 ******************* DIVIDEND TOKEN ***********************
 **********************************************************
 
 UI: https://www.pennyether.com/status/tokens
 
 An ERC20 token that can accept Ether and distribute it
 perfectly to all Token Holders relative to each account's
 balance at the time the dividend is received.
 
 The Token is owned by the creator, and can be frozen,
 minted, and burned by the owner.
 
 Notes:
 - Accounts can view or receive dividends owed at any time
 - Dividends received are immediately credited to all
 current Token Holders and can be redeemed at any time.
 - Per above, upon transfers, dividends are not
 transferred. They are kept by the original sender, and
 not credited to the receiver.
 - Uses "pull" instead of "push". Token holders must pull
 their own dividends.
 
 */
function receivePayment()
internal
{
    if (msg.value == 0) return;
    // POINTS_PER_WEI is 1e32.
    // So, no multiplication overflow unless msg.value > 1e45 wei (1e27 ETH)
    totalPointsPerToken = totalPointsPerToken.add((msg.value.mul(POINTS_PER_WEI)).div(totalSupply));
    dividendsTotal = dividendsTotal.add(msg.value);
    emit DividendReceived(now, msg.sender, msg.value);
}

// Upon receiving payment, increment lastPointsPerToken.