ETH Price: $2,265.23 (-6.53%)

Transaction Decoder

Block:
5113717 at Feb-18-2018 04:51:41 PM +UTC
Transaction Fee:
0.0000747534 ETH $0.17
Gas Used:
24,114 Gas / 3.1 Gwei

Account State Difference:

  Address   Before After State Difference Code
(Nanopool)
3,327.052649077734030545 Eth3,327.052723831134030545 Eth0.0000747534
0xDb4e7307...62b95bf59
0.1266510156 Eth
Nonce: 9
0.1265762622 Eth
Nonce: 10
0.0000747534

Execution Trace

ETH 0.1 ColuLocalNetworkSale.CALL( )
pragma solidity 0.4.18;

/// @title Ownable
/// @dev The Ownable contract has an owner address, and provides basic authorization control functions,
/// this simplifies the implementation of "user permissions".
/// @dev Based on OpenZeppelin's Ownable.

contract Ownable {
    address public owner;
    address public newOwnerCandidate;

    event OwnershipRequested(address indexed _by, address indexed _to);
    event OwnershipTransferred(address indexed _from, address indexed _to);

    /// @dev Constructor sets the original `owner` of the contract to the sender account.
    function Ownable() public {
        owner = msg.sender;
    }

    /// @dev Reverts if called by any account other than the owner.
    modifier onlyOwner() {
        require(msg.sender == owner);
        _;
    }

    modifier onlyOwnerCandidate() {
        require(msg.sender == newOwnerCandidate);
        _;
    }

    /// @dev Proposes to transfer control of the contract to a newOwnerCandidate.
    /// @param _newOwnerCandidate address The address to transfer ownership to.
    function requestOwnershipTransfer(address _newOwnerCandidate) external onlyOwner {
        require(_newOwnerCandidate != address(0));

        newOwnerCandidate = _newOwnerCandidate;

        OwnershipRequested(msg.sender, newOwnerCandidate);
    }

    /// @dev Accept ownership transfer. This method needs to be called by the perviously proposed owner.
    function acceptOwnership() external onlyOwnerCandidate {
        address previousOwner = owner;

        owner = newOwnerCandidate;
        newOwnerCandidate = address(0);

        OwnershipTransferred(previousOwner, owner);
    }
}

/// @title Math operations with safety checks
library SafeMath {
    function mul(uint256 a, uint256 b) internal pure returns (uint256) {
        uint256 c = a * b;
        require(a == 0 || c / a == b);
        return c;
    }

    function div(uint256 a, uint256 b) internal pure returns (uint256) {
        // require(b > 0); // Solidity automatically throws when dividing by 0
        uint256 c = a / b;
        // require(a == b * c + a % b); // There is no case in which this doesn't hold
        return c;
    }

    function sub(uint256 a, uint256 b) internal pure returns (uint256) {
        require(b <= a);
        return a - b;
    }

    function add(uint256 a, uint256 b) internal pure returns (uint256) {
        uint256 c = a + b;
        require(c >= a);
        return c;
    }

    function max64(uint64 a, uint64 b) internal pure returns (uint64) {
        return a >= b ? a : b;
    }

    function min64(uint64 a, uint64 b) internal pure returns (uint64) {
        return a < b ? a : b;
    }

    function max256(uint256 a, uint256 b) internal pure returns (uint256) {
        return a >= b ? a : b;
    }

    function min256(uint256 a, uint256 b) internal pure returns (uint256) {
        return a < b ? a : b;
    }

    function toPower2(uint256 a) internal pure returns (uint256) {
        return mul(a, a);
    }

    function sqrt(uint256 a) internal pure returns (uint256) {
        uint256 c = (a + 1) / 2;
        uint256 b = a;
        while (c < b) {
            b = c;
            c = (a / c + c) / 2;
        }
        return b;
    }
}

/// @title ERC Token Standard #20 Interface (https://github.com/ethereum/EIPs/issues/20)
contract ERC20 {
    uint public totalSupply;
    function balanceOf(address _owner) constant public returns (uint balance);
    function transfer(address _to, uint _value) public returns (bool success);
    function transferFrom(address _from, address _to, uint _value) public returns (bool success);
    function approve(address _spender, uint _value) public returns (bool success);
    function allowance(address _owner, address _spender) public constant returns (uint remaining);
    event Transfer(address indexed from, address indexed to, uint value);
    event Approval(address indexed owner, address indexed spender, uint value);
}



/// @title ERC Token Standard #677 Interface (https://github.com/ethereum/EIPs/issues/677)
contract ERC677 is ERC20 {
    function transferAndCall(address to, uint value, bytes data) public returns (bool ok);

    event TransferAndCall(address indexed from, address indexed to, uint value, bytes data);
}

/// @title ERC223Receiver Interface
/// @dev Based on the specs form: https://github.com/ethereum/EIPs/issues/223
contract ERC223Receiver {
    function tokenFallback(address _sender, uint _value, bytes _data) external returns (bool ok);
}




/// @title Basic ERC20 token contract implementation.
/// @dev Based on OpenZeppelin's StandardToken.
contract BasicToken is ERC20 {
    using SafeMath for uint256;

    uint256 public totalSupply;
    mapping (address => mapping (address => uint256)) allowed;
    mapping (address => uint256) balances;

    event Approval(address indexed owner, address indexed spender, uint256 value);
    event Transfer(address indexed from, address indexed to, uint256 value);

    /// @dev Approve the passed address to spend the specified amount of tokens on behalf of msg.sender.
    /// @param _spender address The address which will spend the funds.
    /// @param _value uint256 The amount of tokens to be spent.
    function approve(address _spender, uint256 _value) public returns (bool) {
        // https://github.com/ethereum/EIPs/blob/master/EIPS/eip-20.md#approve (see NOTE)
        if ((_value != 0) && (allowed[msg.sender][_spender] != 0)) {
            revert();
        }

        allowed[msg.sender][_spender] = _value;

        Approval(msg.sender, _spender, _value);

        return true;
    }

    /// @dev Function to check the amount of tokens that an owner allowed to a spender.
    /// @param _owner address The address which owns the funds.
    /// @param _spender address The address which will spend the funds.
    /// @return uint256 specifying the amount of tokens still available for the spender.
    function allowance(address _owner, address _spender) constant public returns (uint256 remaining) {
        return allowed[_owner][_spender];
    }


    /// @dev Gets the balance of the specified address.
    /// @param _owner address The address to query the the balance of.
    /// @return uint256 representing the amount owned by the passed address.
    function balanceOf(address _owner) constant public returns (uint256 balance) {
        return balances[_owner];
    }

    /// @dev Transfer token to a specified address.
    /// @param _to address The address to transfer to.
    /// @param _value uint256 The amount to be transferred.
    function transfer(address _to, uint256 _value) public returns (bool) {
        require(_to != address(0));
        balances[msg.sender] = balances[msg.sender].sub(_value);
        balances[_to] = balances[_to].add(_value);

        Transfer(msg.sender, _to, _value);

        return true;
    }

    /// @dev Transfer tokens from one address to another.
    /// @param _from address The address which you want to send tokens from.
    /// @param _to address The address which you want to transfer to.
    /// @param _value uint256 the amount of tokens to be transferred.
    function transferFrom(address _from, address _to, uint256 _value) public returns (bool) {
        require(_to != address(0));
        var _allowance = allowed[_from][msg.sender];

        balances[_from] = balances[_from].sub(_value);
        balances[_to] = balances[_to].add(_value);

        allowed[_from][msg.sender] = _allowance.sub(_value);

        Transfer(_from, _to, _value);

        return true;
    }
}






/// @title Standard677Token implentation, base on https://github.com/ethereum/EIPs/issues/677

contract Standard677Token is ERC677, BasicToken {

  /// @dev ERC223 safe token transfer from one address to another
  /// @param _to address the address which you want to transfer to.
  /// @param _value uint256 the amount of tokens to be transferred.
  /// @param _data bytes data that can be attached to the token transation
  function transferAndCall(address _to, uint _value, bytes _data) public returns (bool) {
    require(super.transfer(_to, _value)); // do a normal token transfer
    TransferAndCall(msg.sender, _to, _value, _data);
    //filtering if the target is a contract with bytecode inside it
    if (isContract(_to)) return contractFallback(_to, _value, _data);
    return true;
  }

  /// @dev called when transaction target is a contract
  /// @param _to address the address which you want to transfer to.
  /// @param _value uint256 the amount of tokens to be transferred.
  /// @param _data bytes data that can be attached to the token transation
  function contractFallback(address _to, uint _value, bytes _data) private returns (bool) {
    ERC223Receiver receiver = ERC223Receiver(_to);
    require(receiver.tokenFallback(msg.sender, _value, _data));
    return true;
  }

  /// @dev check if the address is contract
  /// assemble the given address bytecode. If bytecode exists then the _addr is a contract.
  /// @param _addr address the address to check
  function isContract(address _addr) private constant returns (bool is_contract) {
    // retrieve the size of the code on target address, this needs assembly
    uint length;
    assembly { length := extcodesize(_addr) }
    return length > 0;
  }
}





/// @title Token holder contract.
contract TokenHolder is Ownable {
    /// @dev Allow the owner to transfer out any accidentally sent ERC20 tokens.
    /// @param _tokenAddress address The address of the ERC20 contract.
    /// @param _amount uint256 The amount of tokens to be transferred.
    function transferAnyERC20Token(address _tokenAddress, uint256 _amount) public onlyOwner returns (bool success) {
        return ERC20(_tokenAddress).transfer(owner, _amount);
    }
}






/// @title Colu Local Network contract.
/// @author Tal Beja.
contract ColuLocalNetwork is Ownable, Standard677Token, TokenHolder {
    using SafeMath for uint256;

    string public constant name = "Colu Local Network";
    string public constant symbol = "CLN";

    // Using same decimals value as ETH (makes ETH-CLN conversion much easier).
    uint8 public constant decimals = 18;

    // States whether token transfers is allowed or not.
    // Used during token sale.
    bool public isTransferable = false;

    event TokensTransferable();

    modifier transferable() {
        require(msg.sender == owner || isTransferable);
        _;
    }

    /// @dev Creates all tokens and gives them to the owner.
    function ColuLocalNetwork(uint256 _totalSupply) public {
        totalSupply = _totalSupply;
        balances[msg.sender] = totalSupply;
    }

    /// @dev start transferable mode.
    function makeTokensTransferable() external onlyOwner {
        if (isTransferable) {
            return;
        }

        isTransferable = true;

        TokensTransferable();
    }

    /// @dev Same ERC20 behavior, but reverts if not transferable.
    /// @param _spender address The address which will spend the funds.
    /// @param _value uint256 The amount of tokens to be spent.
    function approve(address _spender, uint256 _value) public transferable returns (bool) {
        return super.approve(_spender, _value);
    }

    /// @dev Same ERC20 behavior, but reverts if not transferable.
    /// @param _to address The address to transfer to.
    /// @param _value uint256 The amount to be transferred.
    function transfer(address _to, uint256 _value) public transferable returns (bool) {
        return super.transfer(_to, _value);
    }

    /// @dev Same ERC20 behavior, but reverts if not transferable.
    /// @param _from address The address to send tokens from.
    /// @param _to address The address to transfer to.
    /// @param _value uint256 the amount of tokens to be transferred.
    function transferFrom(address _from, address _to, uint256 _value) public transferable returns (bool) {
        return super.transferFrom(_from, _to, _value);
    }

    /// @dev Same ERC677 behavior, but reverts if not transferable.
    /// @param _to address The address to transfer to.
    /// @param _value uint256 The amount to be transferred.
    /// @param _data bytes data to send to receiver if it is a contract.
    function transferAndCall(address _to, uint _value, bytes _data) public transferable returns (bool success) {
      return super.transferAndCall(_to, _value, _data);
    }
}



 /// @title Standard ERC223 Token Receiver implementing tokenFallback function and tokenPayable modifier

contract Standard223Receiver is ERC223Receiver {
  Tkn tkn;

  struct Tkn {
    address addr;
    address sender; // the transaction caller
    uint256 value;
  }

  bool __isTokenFallback;

  modifier tokenPayable {
    require(__isTokenFallback);
    _;
  }

  /// @dev Called when the receiver of transfer is contract
  /// @param _sender address the address of tokens sender
  /// @param _value uint256 the amount of tokens to be transferred.
  /// @param _data bytes data that can be attached to the token transation
  function tokenFallback(address _sender, uint _value, bytes _data) external returns (bool ok) {
    if (!supportsToken(msg.sender)) {
      return false;
    }

    // Problem: This will do a sstore which is expensive gas wise. Find a way to keep it in memory.
    // Solution: Remove the the data
    tkn = Tkn(msg.sender, _sender, _value);
    __isTokenFallback = true;
    if (!address(this).delegatecall(_data)) {
      __isTokenFallback = false;
      return false;
    }
    // avoid doing an overwrite to .token, which would be more expensive
    // makes accessing .tkn values outside tokenPayable functions unsafe
    __isTokenFallback = false;

    return true;
  }

  function supportsToken(address token) public constant returns (bool);
}





/// @title TokenOwnable
/// @dev The TokenOwnable contract adds a onlyTokenOwner modifier as a tokenReceiver with ownable addaptation

contract TokenOwnable is Standard223Receiver, Ownable {
    /// @dev Reverts if called by any account other than the owner for token sending.
    modifier onlyTokenOwner() {
        require(tkn.sender == owner);
        _;
    }
}






/// @title Vesting trustee contract for Colu Local Network.
/// @dev This Contract can't be TokenHolder, since it will allow its owner to drain its vested tokens.
/// @dev This means that any token sent to it different than ColuLocalNetwork is basicly stucked here forever.
/// @dev ColuLocalNetwork that sent here (by mistake) can withdrawn using the grant method.
contract VestingTrustee is TokenOwnable {
    using SafeMath for uint256;

    // Colu Local Network contract.
    ColuLocalNetwork public cln;

    // Vesting grant for a speicifc holder.
    struct Grant {
        uint256 value;
        uint256 start;
        uint256 cliff;
        uint256 end;
        uint256 installmentLength; // In seconds.
        uint256 transferred;
        bool revokable;
    }

    // Holder to grant information mapping.
    mapping (address => Grant) public grants;

    // Total tokens vested.
    uint256 public totalVesting;

    event NewGrant(address indexed _from, address indexed _to, uint256 _value);
    event TokensUnlocked(address indexed _to, uint256 _value);
    event GrantRevoked(address indexed _holder, uint256 _refund);

    uint constant OK = 1;
    uint constant ERR_INVALID_VALUE = 10001;
    uint constant ERR_INVALID_VESTED = 10002;
    uint constant ERR_INVALID_TRANSFERABLE = 10003;

    event Error(address indexed sender, uint error);

    /// @dev Constructor that initializes the address of the Colu Local Network contract.
    /// @param _cln ColuLocalNetwork The address of the previously deployed Colu Local Network contract.
    function VestingTrustee(ColuLocalNetwork _cln) public {
        require(_cln != address(0));

        cln = _cln;
    }

    /// @dev Allow only cln token to be tokenPayable
    /// @param token the token to check
    function supportsToken(address token) public constant returns (bool) {
        return (cln == token);
    }

    /// @dev Grant tokens to a specified address.
    /// @param _to address The holder address.
    /// @param _start uint256 The beginning of the vesting period (timestamp).
    /// @param _cliff uint256 When the first installment is made (timestamp).
    /// @param _end uint256 The end of the vesting period (timestamp).
    /// @param _installmentLength uint256 The length of each vesting installment (in seconds).
    /// @param _revokable bool Whether the grant is revokable or not.
    function grant(address _to, uint256 _start, uint256 _cliff, uint256 _end,
        uint256 _installmentLength, bool _revokable)
        external onlyTokenOwner tokenPayable {

        require(_to != address(0));
        require(_to != address(this)); // Protect this contract from receiving a grant.

        uint256 value = tkn.value;

        require(value > 0);

        // Require that every holder can be granted tokens only once.
        require(grants[_to].value == 0);

        // Require for time ranges to be consistent and valid.
        require(_start <= _cliff && _cliff <= _end);

        // Require installment length to be valid and no longer than (end - start).
        require(_installmentLength > 0 && _installmentLength <= _end.sub(_start));

        // Grant must not exceed the total amount of tokens currently available for vesting.
        require(totalVesting.add(value) <= cln.balanceOf(address(this)));

        // Assign a new grant.
        grants[_to] = Grant({
            value: value,
            start: _start,
            cliff: _cliff,
            end: _end,
            installmentLength: _installmentLength,
            transferred: 0,
            revokable: _revokable
        });

        // Since tokens have been granted, increase the total amount vested.
        totalVesting = totalVesting.add(value);

        NewGrant(msg.sender, _to, value);
    }

    /// @dev Grant tokens to a specified address.
    /// @param _to address The holder address.
    /// @param _value uint256 The amount of tokens to be granted.
    /// @param _start uint256 The beginning of the vesting period (timestamp).
    /// @param _cliff uint256 When the first installment is made (timestamp).
    /// @param _end uint256 The end of the vesting period (timestamp).
    /// @param _installmentLength uint256 The length of each vesting installment (in seconds).
    /// @param _revokable bool Whether the grant is revokable or not.
    function grant(address _to, uint256 _value, uint256 _start, uint256 _cliff, uint256 _end,
        uint256 _installmentLength, bool _revokable)
        external onlyOwner {

        require(_to != address(0));
        require(_to != address(this)); // Protect this contract from receiving a grant.
        require(_value > 0);

        // Require that every holder can be granted tokens only once.
        require(grants[_to].value == 0);

        // Require for time ranges to be consistent and valid.
        require(_start <= _cliff && _cliff <= _end);

        // Require installment length to be valid and no longer than (end - start).
        require(_installmentLength > 0 && _installmentLength <= _end.sub(_start));

        // Grant must not exceed the total amount of tokens currently available for vesting.
        require(totalVesting.add(_value) <= cln.balanceOf(address(this)));

        // Assign a new grant.
        grants[_to] = Grant({
            value: _value,
            start: _start,
            cliff: _cliff,
            end: _end,
            installmentLength: _installmentLength,
            transferred: 0,
            revokable: _revokable
        });

        // Since tokens have been granted, increase the total amount vested.
        totalVesting = totalVesting.add(_value);

        NewGrant(msg.sender, _to, _value);
    }

    /// @dev Revoke the grant of tokens of a specifed address.
    /// @dev Unlocked tokens will be sent to the grantee, the rest is transferred to the trustee's owner.
    /// @param _holder The address which will have its tokens revoked.
    function revoke(address _holder) public onlyOwner {
        Grant memory grant = grants[_holder];

        // Grant must be revokable.
        require(grant.revokable);

        // Get the total amount of vested tokens, acccording to grant.
        uint256 vested = calculateVestedTokens(grant, now);

        // Calculate the untransferred vested tokens.
        uint256 transferable = vested.sub(grant.transferred);

        if (transferable > 0) {
            // Update transferred and total vesting amount, then transfer remaining vested funds to holder.
            grant.transferred = grant.transferred.add(transferable);
            totalVesting = totalVesting.sub(transferable);
            require(cln.transfer(_holder, transferable));

            TokensUnlocked(_holder, transferable);
        }

        // Calculate amount of remaining tokens that can still be returned.
        uint256 refund = grant.value.sub(grant.transferred);

        // Remove the grant.
        delete grants[_holder];

        // Update total vesting amount and transfer previously calculated tokens to owner.
        totalVesting = totalVesting.sub(refund);
        require(cln.transfer(msg.sender, refund));

        GrantRevoked(_holder, refund);
    }

    /// @dev Calculate the amount of ready tokens of a holder.
    /// @param _holder address The address of the holder.
    /// @return a uint256 Representing a holder's total amount of vested tokens.
    function readyTokens(address _holder) public constant returns (uint256) {
        Grant memory grant = grants[_holder];

        if (grant.value == 0) {
            return 0;
        }

        uint256 vested = calculateVestedTokens(grant, now);

        if (vested == 0) {
            return 0;
        }

        return vested.sub(grant.transferred);
    }

    /// @dev Calculate the total amount of vested tokens of a holder at a given time.
    /// @param _holder address The address of the holder.
    /// @param _time uint256 The specific time to calculate against.
    /// @return a uint256 Representing a holder's total amount of vested tokens.
    function vestedTokens(address _holder, uint256 _time) public constant returns (uint256) {
        Grant memory grant = grants[_holder];
        if (grant.value == 0) {
            return 0;
        }

        return calculateVestedTokens(grant, _time);
    }

    /// @dev Calculate amount of vested tokens at a specifc time.
    /// @param _grant Grant The vesting grant.
    /// @param _time uint256 The time to be checked
    /// @return An uint256 Representing the amount of vested tokens of a specific grant.
    function calculateVestedTokens(Grant _grant, uint256 _time) private pure returns (uint256) {
        // If we're before the cliff, then nothing is vested.
        if (_time < _grant.cliff) {
            return 0;
        }

        // If we're after the end of the vesting period - everything is vested.
        if (_time >= _grant.end) {
            return _grant.value;
        }

        // Calculate amount of installments past until now.
        //
        // NOTE: result gets floored because of integer division.
        uint256 installmentsPast = _time.sub(_grant.start).div(_grant.installmentLength);

        // Calculate amount of days in entire vesting period.
        uint256 vestingDays = _grant.end.sub(_grant.start);

        // Calculate and return the number of tokens according to vesting days that have passed.
        return _grant.value.mul(installmentsPast.mul(_grant.installmentLength)).div(vestingDays);
    }

    /// @dev Unlock vested tokens and transfer them to the grantee.
    /// @return a uint The success or error code.
    function unlockVestedTokens() external returns (uint) {
        return unlockVestedTokens(msg.sender);
    }

    /// @dev Unlock vested tokens and transfer them to the grantee (helper function).
    /// @param _grantee address The address of the grantee.
    /// @return a uint The success or error code.
    function unlockVestedTokens(address _grantee) private returns (uint) {
        Grant storage grant = grants[_grantee];

        // Make sure the grant has tokens available.
        if (grant.value == 0) {
            Error(_grantee, ERR_INVALID_VALUE);
            return ERR_INVALID_VALUE;
        }

        // Get the total amount of vested tokens, acccording to grant.
        uint256 vested = calculateVestedTokens(grant, now);
        if (vested == 0) {
            Error(_grantee, ERR_INVALID_VESTED);
            return ERR_INVALID_VESTED;
        }

        // Make sure the holder doesn't transfer more than what he already has.
        uint256 transferable = vested.sub(grant.transferred);
        if (transferable == 0) {
            Error(_grantee, ERR_INVALID_TRANSFERABLE);
            return ERR_INVALID_TRANSFERABLE;
        }

        // Update transferred and total vesting amount, then transfer remaining vested funds to holder.
        grant.transferred = grant.transferred.add(transferable);
        totalVesting = totalVesting.sub(transferable);
        require(cln.transfer(_grantee, transferable));

        TokensUnlocked(_grantee, transferable);
        return OK;
    }

    /// @dev batchUnlockVestedTokens vested tokens and transfer them to the grantees.
    /// @param _grantees address[] The addresses of the grantees.
    /// @return a boo if success.
    function batchUnlockVestedTokens(address[] _grantees) external onlyOwner returns (bool success) {
        for (uint i = 0; i<_grantees.length; i++) {
            unlockVestedTokens(_grantees[i]);
        }
        return true;
    }

    /// @dev Allow the owner to transfer out any accidentally sent ERC20 tokens.
    /// @param _tokenAddress address The address of the ERC20 contract.
    /// @param _amount uint256 The amount of tokens to be transferred.
    function withdrawERC20(address _tokenAddress, uint256 _amount) public onlyOwner returns (bool success) {
        if (_tokenAddress == address(cln)) {
            // If the token is cln, allow to withdraw only non vested tokens.
            uint256 availableCLN = cln.balanceOf(this).sub(totalVesting);
            require(_amount <= availableCLN);
        }
        return ERC20(_tokenAddress).transfer(owner, _amount);
    }
}








/// @title Colu Local Network sale contract.
/// @author Tal Beja.
contract ColuLocalNetworkSale is Ownable, TokenHolder {
    using SafeMath for uint256;

    // External parties:

    // Colu Local Network contract.
    ColuLocalNetwork public cln;

    // Vesting contract for presale participants.
    VestingTrustee public trustee;

    // Received funds are forwarded to this address.
    address public fundingRecipient;

    // Post-TDE multisig addresses.
    address public communityPoolAddress;
    address public futureDevelopmentPoolAddress;
    address public stakeholdersPoolAddress;

    // Colu Local Network decimals.
    // Using same decimals value as ETH (makes ETH-CLN conversion much easier).
    // This is the same as in Colu Local Network contract.
    uint256 public constant TOKEN_DECIMALS = 10 ** 18;

    // Additional Lockup Allocation Pool
    uint256 public constant ALAP = 40701333592592592592614116;

    // Maximum number of tokens in circulation: 1.5 trillion.
    uint256 public constant MAX_TOKENS = 15 * 10 ** 8 * TOKEN_DECIMALS + ALAP;

    // Maximum tokens offered in the sale (35%) + ALAP.
    uint256 public constant MAX_TOKENS_SOLD = 525 * 10 ** 6 * TOKEN_DECIMALS + ALAP;

    // Maximum tokens offered in the presale (from the initial 35% offered tokens) + ALAP.
    uint256 public constant MAX_PRESALE_TOKENS_SOLD = 2625 * 10 ** 5 * TOKEN_DECIMALS + ALAP;

    // Tokens allocated for Community pool (30%).
    uint256 public constant COMMUNITY_POOL = 45 * 10 ** 7 * TOKEN_DECIMALS;

    // Tokens allocated for Future development pool (29%).
    uint256 public constant FUTURE_DEVELOPMENT_POOL = 435 * 10 ** 6 * TOKEN_DECIMALS;

    // Tokens allocated for Stakeholdes pool (6%).
    uint256 public constant STAKEHOLDERS_POOL = 9 * 10 ** 7 * TOKEN_DECIMALS;

    // CLN to ETH ratio.
    uint256 public constant CLN_PER_ETH = 8600;

    // Sale start, end blocks (time ranges)
    uint256 public constant SALE_DURATION = 4 days;
    uint256 public startTime;
    uint256 public endTime;

    // Amount of tokens sold until now in the sale.
    uint256 public tokensSold = 0;

    // Amount of tokens sold until now in the presale.
    uint256 public presaleTokensSold = 0;

    // Accumulated amount each participant has contributed so far in the sale (in WEI).
    mapping (address => uint256) public participationHistory;

    // Accumulated amount each participant have contributed so far in the presale.
    mapping (address => uint256) public participationPresaleHistory;

    // Maximum amount that each particular is allowed to contribute (in ETH-WEI).
    // Defaults to zero. Serving as a functional whitelist. 
    mapping (address => uint256) public participationCaps;

    // Maximum amount ANYONE is currently allowed to contribute. Set to max uint256 so no limitation other than personal participationCaps.
    uint256 public hardParticipationCap = uint256(-1);

    // initialization of the contract, splitted from the constructor to avoid gas block limit.
    bool public initialized = false;

    // Vesting plan structure for presale
    struct VestingPlan {
        uint256 startOffset;
        uint256 cliffOffset;
        uint256 endOffset;
        uint256 installmentLength;
        uint8 alapPercent;
    }

    // Vesting plans for presale
    VestingPlan[] public vestingPlans;

    // Each token that is sent from the ColuLocalNetworkSale is considered as issued.
    event TokensIssued(address indexed to, uint256 tokens);

    /// @dev Reverts if called not before the sale.
    modifier onlyBeforeSale() {
        if (now >= startTime) {
            revert();
        }

        _;
    }

    /// @dev Reverts if called not during the sale.
    modifier onlyDuringSale() {
        if (tokensSold >= MAX_TOKENS_SOLD || now < startTime || now >= endTime) {
            revert();
        }

        _;
    }

    /// @dev Reverts if called before the sale ends.
    modifier onlyAfterSale() {
        if (!(tokensSold >= MAX_TOKENS_SOLD || now >= endTime)) {
            revert();
        }

        _;
    }

    /// @dev Reverts if called before the sale is initialized.
    modifier notInitialized() {
        if (initialized) {
            revert();
        }

        _;
    }


    /// @dev Reverts if called after the sale is initialized.
    modifier isInitialized() {
        if (!initialized) {
            revert();
        }

        _;
    }

    /// @dev Constructor sets the sale addresses and start time.
    /// @param _owner address The address of this contract owner.
    /// @param _fundingRecipient address The address of the funding recipient.
    /// @param _communityPoolAddress address The address of the community pool.
    /// @param _futureDevelopmentPoolAddress address The address of the future development pool.
    /// @param _stakeholdersPoolAddress address The address of the team pool.
    /// @param _startTime uint256 The start time of the token sale.
    function ColuLocalNetworkSale(address _owner,
        address _fundingRecipient,
        address _communityPoolAddress,
        address _futureDevelopmentPoolAddress,
        address _stakeholdersPoolAddress,
        uint256 _startTime) public {
        require(_owner != address(0));
        require(_fundingRecipient != address(0));
        require(_communityPoolAddress != address(0));
        require(_futureDevelopmentPoolAddress != address(0));
        require(_stakeholdersPoolAddress != address(0));
        require(_startTime > now);

        owner = _owner;
        fundingRecipient = _fundingRecipient;
        communityPoolAddress = _communityPoolAddress;
        futureDevelopmentPoolAddress = _futureDevelopmentPoolAddress;
        stakeholdersPoolAddress = _stakeholdersPoolAddress;
        startTime = _startTime;
        endTime = startTime + SALE_DURATION;
    }

    /// @dev Initialize the sale conditions.
    function initialize() public onlyOwner notInitialized {
        initialized = true;

        uint256 months = 1 years / 12;

        vestingPlans.push(VestingPlan(0, 0, 1, 1, 0));
        vestingPlans.push(VestingPlan(0, 0, 6 * months, 1 * months, 4));
        vestingPlans.push(VestingPlan(0, 0, 1 years, 1 * months, 12));
        vestingPlans.push(VestingPlan(0, 0, 2 years, 1 * months, 26));
        vestingPlans.push(VestingPlan(0, 0, 3 years, 1 * months, 35));

        // Deploy new ColuLocalNetwork contract.
        cln = new ColuLocalNetwork(MAX_TOKENS);

        // Deploy new VestingTrustee contract.
        trustee = new VestingTrustee(cln);

        // allocate pool tokens:
        // Issue the remaining tokens to designated pools.
        require(transferTokens(communityPoolAddress, COMMUNITY_POOL));

        // stakeholdersPoolAddress will create its own vesting trusts.
        require(transferTokens(stakeholdersPoolAddress, STAKEHOLDERS_POOL));
    }

    /// @dev Allocate tokens to presale participant according to its vesting plan and invesment value.
    /// @param _recipient address The presale participant address to recieve the tokens.
    /// @param _etherValue uint256 The invesment value (in ETH).
    /// @param _vestingPlanIndex uint8 The vesting plan index.
    function presaleAllocation(address _recipient, uint256 _etherValue, uint8 _vestingPlanIndex) external onlyOwner onlyBeforeSale isInitialized {
        require(_recipient != address(0));
        require(_vestingPlanIndex < vestingPlans.length);

        // Calculate plan and token amount.
        VestingPlan memory plan = vestingPlans[_vestingPlanIndex];
        uint256 tokensAndALAPPerEth = CLN_PER_ETH.mul(SafeMath.add(100, plan.alapPercent)).div(100);

        uint256 tokensLeftInPreSale = MAX_PRESALE_TOKENS_SOLD.sub(presaleTokensSold);
        uint256 weiLeftInSale = tokensLeftInPreSale.div(tokensAndALAPPerEth);
        uint256 weiToParticipate = SafeMath.min256(_etherValue, weiLeftInSale);
        require(weiToParticipate > 0);
        participationPresaleHistory[msg.sender] = participationPresaleHistory[msg.sender].add(weiToParticipate);
        uint256 tokensToTransfer = weiToParticipate.mul(tokensAndALAPPerEth);
        presaleTokensSold = presaleTokensSold.add(tokensToTransfer);
        tokensSold = tokensSold.add(tokensToTransfer);

        // Transfer tokens to trustee and create grant.
        grant(_recipient, tokensToTransfer, startTime.add(plan.startOffset), startTime.add(plan.cliffOffset),
            startTime.add(plan.endOffset), plan.installmentLength, false);
    }

    /// @dev Add a list of participants to a capped participation tier.
    /// @param _participants address[] The list of participant addresses.
    /// @param _cap uint256 The cap amount (in ETH-WEI).
    function setParticipationCap(address[] _participants, uint256 _cap) external onlyOwner isInitialized {
        for (uint i = 0; i < _participants.length; i++) {
            participationCaps[_participants[i]] = _cap;
        }
    }

    /// @dev Set hard participation cap for all participants.
    /// @param _cap uint256 The hard cap amount.
    function setHardParticipationCap(uint256 _cap) external onlyOwner isInitialized {
        require(_cap > 0);

        hardParticipationCap = _cap;
    }

    /// @dev Fallback function that will delegate the request to participate().
    function () external payable onlyDuringSale isInitialized {
        participate(msg.sender);
    }

    /// @dev Create and sell tokens to the caller.
    /// @param _recipient address The address of the recipient receiving the tokens.
    function participate(address _recipient) public payable onlyDuringSale isInitialized {
        require(_recipient != address(0));

        // Enforce participation cap (in WEI received).
        uint256 weiAlreadyParticipated = participationHistory[_recipient];
        uint256 participationCap = SafeMath.min256(participationCaps[_recipient], hardParticipationCap);
        uint256 cappedWeiReceived = SafeMath.min256(msg.value, participationCap.sub(weiAlreadyParticipated));
        require(cappedWeiReceived > 0);

        // Accept funds and transfer to funding recipient.
        uint256 tokensLeftInSale = MAX_TOKENS_SOLD.sub(tokensSold);
        uint256 weiLeftInSale = tokensLeftInSale.div(CLN_PER_ETH);
        uint256 weiToParticipate = SafeMath.min256(cappedWeiReceived, weiLeftInSale);
        participationHistory[_recipient] = weiAlreadyParticipated.add(weiToParticipate);
        fundingRecipient.transfer(weiToParticipate);

        // Transfer tokens to recipient.
        uint256 tokensToTransfer = weiToParticipate.mul(CLN_PER_ETH);
        if (tokensLeftInSale.sub(tokensToTransfer) < CLN_PER_ETH) {
            // If purchase would cause less than CLN_PER_ETH tokens to be left then nobody could ever buy them.
            // So, gift them to the last buyer.
            tokensToTransfer = tokensLeftInSale;
        }
        tokensSold = tokensSold.add(tokensToTransfer);
        require(transferTokens(_recipient, tokensToTransfer));

        // Partial refund if full participation not possible
        // e.g. due to cap being reached.
        uint256 refund = msg.value.sub(weiToParticipate);
        if (refund > 0) {
            msg.sender.transfer(refund);
        }
    }

    /// @dev Finalizes the token sale event: make future development pool grant (lockup) and make token transfarable.
    function finalize() external onlyAfterSale onlyOwner isInitialized {
        if (cln.isTransferable()) {
            revert();
        }

        // Add unsold token to the future development pool grant (lockup).
        uint256 tokensLeftInSale = MAX_TOKENS_SOLD.sub(tokensSold);
        uint256 futureDevelopmentPool = FUTURE_DEVELOPMENT_POOL.add(tokensLeftInSale);
        // Future Development Pool is locked for 3 years.
        grant(futureDevelopmentPoolAddress, futureDevelopmentPool, startTime, startTime.add(3 years),
            startTime.add(3 years), 1 days, false);

        // Make tokens Transferable, end the sale!.
        cln.makeTokensTransferable();
    }

    function grant(address _grantee, uint256 _amount, uint256 _start, uint256 _cliff, uint256 _end,
        uint256 _installmentLength, bool _revokable) private {
        // bytes4 grantSig = bytes4(keccak256("grant(address,uint256,uint256,uint256,uint256,bool)"));
        bytes4 grantSig = 0x5ee7e96d;
        // 6 arguments of size 32
        uint256 argsSize = 6 * 32;
        // sig + arguments size
        uint256 dataSize = 4 + argsSize;

        bytes memory m_data = new bytes(dataSize);

        assembly {
            // Add the signature first to memory
            mstore(add(m_data, 0x20), grantSig)
            // Add the parameters
            mstore(add(m_data, 0x24), _grantee)
            mstore(add(m_data, 0x44), _start)
            mstore(add(m_data, 0x64), _cliff)
            mstore(add(m_data, 0x84), _end)
            mstore(add(m_data, 0xa4), _installmentLength)
            mstore(add(m_data, 0xc4), _revokable)
        }

        require(transferTokens(trustee, _amount, m_data));
    }

    /// @dev Transfer tokens from the sale contract to a recipient.
    /// @param _recipient address The address of the recipient.
    /// @param _tokens uint256 The amount of tokens to transfer.
    function transferTokens(address _recipient, uint256 _tokens) private returns (bool ans) {
        ans = cln.transfer(_recipient, _tokens);
        if (ans) {
            TokensIssued(_recipient, _tokens);
        }
    }

    /// @dev Transfer tokens from the sale contract to a recipient.
    /// @param _recipient address The address of the recipient.
    /// @param _tokens uint256 The amount of tokens to transfer.
    /// @param _data bytes data to send to receiver if it is a contract.
    function transferTokens(address _recipient, uint256 _tokens, bytes _data) private returns (bool ans) {
        // Request Colu Local Network contract to transfer the requested tokens for the buyer.
        ans = cln.transferAndCall(_recipient, _tokens, _data);
        if (ans) {
            TokensIssued(_recipient, _tokens);
        }
    }

    /// @dev Requests to transfer control of the Colu Local Network contract to a new owner.
    /// @param _newOwnerCandidate address The address to transfer ownership to.
    ///
    /// NOTE:
    ///   1. The new owner will need to call Colu Local Network contract's acceptOwnership directly in order to accept the ownership.
    ///   2. Calling this method during the token sale will prevent the token sale to continue, since only the owner of
    ///      the Colu Local Network contract can transfer tokens during the sale.
    function requestColuLocalNetworkOwnershipTransfer(address _newOwnerCandidate) external onlyOwner {
        cln.requestOwnershipTransfer(_newOwnerCandidate);
    }

    /// @dev Accepts new ownership on behalf of the Colu Local Network contract.
    // This can be used by the sale contract itself to claim back ownership of the Colu Local Network contract.
    function acceptColuLocalNetworkOwnership() external onlyOwner {
        cln.acceptOwnership();
    }

    /// @dev Requests to transfer control of the VestingTrustee contract to a new owner.
    /// @param _newOwnerCandidate address The address to transfer ownership to.
    ///
    /// NOTE:
    ///   1. The new owner will need to call trustee contract's acceptOwnership directly in order to accept the ownership.
    ///   2. Calling this method during the token sale will prevent the token sale from alocation presale grunts add finalize, since only the owner of
    ///      the trustee contract can create grunts needed in the presaleAlocation add finalize methods.
    function requestVestingTrusteeOwnershipTransfer(address _newOwnerCandidate) external onlyOwner {
        trustee.requestOwnershipTransfer(_newOwnerCandidate);
    }

    /// @dev Accepts new ownership on behalf of the VestingTrustee contract.
    /// This can be used by the token sale contract itself to claim back ownership of the VestingTrustee contract.
    function acceptVestingTrusteeOwnership() external onlyOwner {
        trustee.acceptOwnership();
    }
}