contract MiniMeIrrevocableVestedToken is MiniMeToken {

    using SafeMath for uint256;

    uint256 MAX_GRANTS_PER_ADDRESS = 20;
    // Keep the struct at 2 stores (1 slot for value + 64 * 3 (dates) + 20 (address) = 2 slots
    // (2nd slot is 212 bytes, lower than 256))
    struct TokenGrant {
    address granter;    // 20 bytes
    uint256 value;         // 32 bytes
    uint64 cliff;
    uint64 vesting;
    uint64 start;        // 3 * 8 = 24 bytes
    bool revokable;
    bool burnsOnRevoke;    // 2 * 1 = 2 bits? or 2 bytes?
    } // total 78 bytes = 3 sstore per operation (32 per sstore)

    mapping (address => TokenGrant[]) public grants;

    event NewTokenGrant(address indexed from, address indexed to, uint256 value, uint64 start, uint64 cliff, uint64 vesting, uint256 grantId);

    mapping (address => bool) canCreateGrants;
    address vestingWhitelister;

    modifier canTransfer(address _sender, uint _value) {
    require(_value <= spendableBalanceOf(_sender));
    _;
    }

    modifier onlyVestingWhitelister {
    require(msg.sender == vestingWhitelister);
    _;
    }

    function MiniMeIrrevocableVestedToken (
        address _tokenFactory,
        address _parentToken,
        uint _parentSnapShotBlock,
        string _tokenName,
        uint8 _decimalUnits,
        string _tokenSymbol,
        bool _transfersEnabled
    ) public MiniMeToken(_tokenFactory, _parentToken, _parentSnapShotBlock, _tokenName, _decimalUnits, _tokenSymbol, _transfersEnabled) {
    vestingWhitelister = msg.sender;
    doSetCanCreateGrants(vestingWhitelister, true);
    }

    // @dev Add canTransfer modifier before allowing transfer and transferFrom to go through
    function transfer(address _to, uint _value)
             canTransfer(msg.sender, _value)
             public
             returns (bool success) {
    return super.transfer(_to, _value);
    }

    function transferFrom(address _from, address _to, uint _value)
             canTransfer(_from, _value)
             public
             returns (bool success) {
    return super.transferFrom(_from, _to, _value);
    }

    function spendableBalanceOf(address _holder) constant public returns (uint) {
    return transferableTokens(_holder, uint64(now));
    }

    /**
    * @dev Grant tokens to a specified address
    * @param _to address The address which the tokens will be granted to.
    * @param _value uint256 The amount of tokens to be granted.
    * @param _start uint64 Time of the beginning of the grant.
    * @param _cliff uint64 Time of the cliff period.
    * @param _vesting uint64 The vesting period.
    * @param _revokable bool Token can be revoked with send amount to back.
    * @param _burnsOnRevoke bool Token can be revoked with send amount to back and destroyed.
    */
    function grantVestedTokens(
    address _to,
    uint256 _value,
    uint64 _start,
    uint64 _cliff,
    uint64 _vesting,
    bool _revokable,
    bool _burnsOnRevoke
    ) public {

    // Check for date inconsistencies that may cause unexpected behavior
    require(_cliff >= _start && _vesting >= _cliff);
    require(canCreateGrants[msg.sender]);

    require(tokenGrantsCount(_to) < MAX_GRANTS_PER_ADDRESS);    // To prevent a user being spammed and have his balance locked (out of gas attack when calculating vesting).

    uint256 count = grants[_to].push(
               TokenGrant(
                   _revokable ? msg.sender : 0, // avoid storing an extra 20 bytes when it is non-revokable
                   _value,
                   _cliff,
                   _vesting,
                   _start,
                   _revokable,
                   _burnsOnRevoke
               )
               );

    transfer(_to, _value);

    NewTokenGrant(msg.sender, _to, _value, _cliff, _vesting, _start, count - 1);
    }

    function setCanCreateGrants(address _addr, bool _allowed) onlyVestingWhitelister public {
    doSetCanCreateGrants(_addr, _allowed);
    }

    function doSetCanCreateGrants(address _addr, bool _allowed) internal {
    canCreateGrants[_addr] = _allowed;
    }

    function changeVestingWhitelister(address _newWhitelister) onlyVestingWhitelister public {
    doSetCanCreateGrants(vestingWhitelister, false);
    vestingWhitelister = _newWhitelister;
    doSetCanCreateGrants(vestingWhitelister, true);
    }

    /**
    * @dev Revoke the grant of tokens of a specifed address.
    * @param _holder The address which will have its tokens revoked.
    * @param _grantId The id of the token grant.
    */
    function revokeTokenGrant(address _holder, uint256 _grantId) public {
    TokenGrant storage grant = grants[_holder][_grantId];

    require(grant.revokable);
    require(grant.granter == msg.sender); // Only granter can revoke it

    address receiver = grant.burnsOnRevoke ? 0xdead : msg.sender;

    uint256 nonVested = nonVestedTokens(grant, uint64(now));

    // remove grant from array
    delete grants[_holder][_grantId];
    grants[_holder][_grantId] = grants[_holder][grants[_holder].length.sub(1)];
    grants[_holder].length -= 1;

    var previousBalanceReceiver = balanceOfAt(receiver, block.number);

    //balances[receiver] = balances[receiver].add(nonVested);
    updateValueAtNow(balances[receiver], previousBalanceReceiver + nonVested);

    var previousBalance_holder = balanceOfAt(_holder, block.number);

    //balances[_holder] = balances[_holder].sub(nonVested);
    updateValueAtNow(balances[_holder], previousBalance_holder - nonVested);

    Transfer(_holder, receiver, nonVested);
    }

    /**
    * @dev Calculate the total amount of transferable tokens of a holder at a given time
    * @param holder address The address of the holder
    * @param time uint64 The specific time.
    * @return An uint256 representing a holder's total amount of transferable tokens.
    */
    function transferableTokens(address holder, uint64 time) public view returns (uint256) {
    uint256 grantIndex = tokenGrantsCount(holder);

    if (grantIndex == 0) return balanceOf(holder); // shortcut for holder without grants

    // Iterate through all the grants the holder has, and add all non-vested tokens
    uint256 nonVested = 0;
    for (uint256 i = 0; i < grantIndex; i++) {
        nonVested = SafeMath.add(nonVested, nonVestedTokens(grants[holder][i], time));
    }

    // Balance - totalNonVested is the amount of tokens a holder can transfer at any given time
    uint256 vestedTransferable = SafeMath.sub(balanceOf(holder), nonVested);

    // Return the minimum of how many vested can transfer and other value
    // in case there are other limiting transferability factors (default is balanceOf)
    return Math.min256(vestedTransferable, balanceOf(holder));
    }

    /**
    * @dev Check the amount of grants that an address has.
    * @param _holder The holder of the grants.
    * @return A uint256 representing the total amount of grants.
    */
    function tokenGrantsCount(address _holder) public view returns (uint256 index) {
    return grants[_holder].length;
    }

    /**
    * @dev Calculate amount of vested tokens at a specifc time.
    * @param tokens uint256 The amount of tokens grantted.
    * @param time uint64 The time to be checked
    * @param start uint64 A time representing the begining of the grant
    * @param cliff uint64 The cliff period.
    * @param vesting uint64 The vesting period.
    * @return An uint256 representing the amount of vested tokensof a specif grant.
    *    transferableTokens
    *    |                        _/--------    vestedTokens rect
    *    |                        _/
    *    |                    _/
    *    |                    _/
    *    |                 _/
    *    |               /
    *    |               .|
    *    |            .    |
    *    |            .    |
    *    |        .        |
    *    |        .        |
    *    |    .            |
    *    +===+===========+---------+----------> time
    *        Start         Clift    Vesting
    */
    function calculateVestedTokens(
    uint256 tokens,
    uint256 time,
    uint256 start,
    uint256 cliff,
    uint256 vesting) internal view returns (uint256)
    {
        // Shortcuts for before cliff and after vesting cases.
        if (time < cliff) return 0;
        if (time >= vesting) return tokens;

        // Interpolate all vested tokens.
        // As before cliff the shortcut returns 0, we can use just calculate a value
        // in the vesting rect (as shown in above's figure)

        // vestedTokens = tokens * (time - start) / (vesting - start)
        uint256 vestedTokens = SafeMath.div(
                                    SafeMath.mul(
                                       tokens,
                                       SafeMath.sub(time, start)
                                       ),
                                    SafeMath.sub(vesting, start)
                                    );

        return vestedTokens;
    }

    /**
    * @dev Get all information about a specifc grant.
    * @param _holder The address which will have its tokens revoked.
    * @param _grantId The id of the token grant.
    * @return Returns all the values that represent a TokenGrant(address, value, start, cliff,
    * revokability, burnsOnRevoke, and vesting) plus the vested value at the current time.
    */
    function tokenGrant(address _holder, uint256 _grantId) public view returns (address granter, uint256 value, uint256 vested, uint64 start, uint64 cliff, uint64 vesting, bool revokable, bool burnsOnRevoke) {
    TokenGrant storage grant = grants[_holder][_grantId];

    granter = grant.granter;
    value = grant.value;
    start = grant.start;
    cliff = grant.cliff;
    vesting = grant.vesting;
    revokable = grant.revokable;
    burnsOnRevoke = grant.burnsOnRevoke;

    vested = vestedTokens(grant, uint64(now));
    }

    /**
    * @dev Get the amount of vested tokens at a specific time.
    * @param grant TokenGrant The grant to be checked.
    * @param time The time to be checked
    * @return An uint256 representing the amount of vested tokens of a specific grant at a specific time.
    */
    function vestedTokens(TokenGrant grant, uint64 time) private constant returns (uint256) {
    return calculateVestedTokens(
        grant.value,
        uint256(time),
        uint256(grant.start),
        uint256(grant.cliff),
        uint256(grant.vesting)
    );
    }

    /**
    * @dev Calculate the amount of non vested tokens at a specific time.
    * @param grant TokenGrant The grant to be checked.
    * @param time uint64 The time to be checked
    * @return An uint256 representing the amount of non vested tokens of a specifc grant on the
    * passed time frame.
    */
    function nonVestedTokens(TokenGrant grant, uint64 time) private constant returns (uint256) {
    // Of all the tokens of the grant, how many of them are not vested?
    // grantValue - vestedTokens
    return grant.value.sub(vestedTokens(grant, time));
    }

    /**
    * @dev Calculate the date when the holder can trasfer all its tokens
    * @param holder address The address of the holder
    * @return An uint256 representing the date of the last transferable tokens.
    */
    function lastTokenIsTransferableDate(address holder) constant public returns (uint64 date) {
    date = uint64(now);
    uint256 grantIndex = grants[holder].length;
    for (uint256 i = 0; i < grantIndex; i++) {
        date = Math.max64(grants[holder][i].vesting, date);
    }
    }

}
// @dev MiniMeIrrevocableVestedToken is a derived version of MiniMeToken adding the
// ability to createTokenGrants which are basically a transfer that limits the
// receiver of the tokens how can he spend them over time.
// For simplicity, token grants are not saved in MiniMe type checkpoints.
// Vanilla cloning ESCBCoin will clone it into a MiniMeToken without vesting.
// More complex cloning could account for past vesting calendars.
function nonVestedTokens(TokenGrant grant, uint64 time) private constant returns (uint256) {
// Of all the tokens of the grant, how many of them are not vested?
// grantValue - vestedTokens
return grant.value.sub(vestedTokens(grant, time));
}

/**
 * @dev Calculate the amount of non vested tokens at a specific time.
 * @param grant TokenGrant The grant to be checked.
 * @param time uint64 The time to be checked
 * @return An uint256 representing the amount of non vested tokens of a specifc grant on the
 * passed time frame.
 */