Contract 0x4cc19356f2d37338b9802aa8e8fc58b0373296e7

 

TxHash Block Age From To Value [TxFee]
0x9e99475a9d46c16778e9911c478d77f9a4a50a6c0d4be623defccfca0373dd4e724968824 mins ago0x945aa26e0f84e7c210468ae7e3e2f217ccdec5af IN  0x4cc19356f2d37338b9802aa8e8fc58b0373296e70 Ether0.00037594
0xd7544996e6c6c4df5629d6ccfd65d0825bc63d5bfa11a843bf654f9a0bf198f972495571 hr 1 min agoBinance_4 IN  0x4cc19356f2d37338b9802aa8e8fc58b0373296e70 Ether0.00150376
0x6344b6a66c19e9a86a0b867ea8c80adc2a84a45cf52cddcb6f19f73f489b7e2572494921 hr 23 mins agoBinance_1 IN  0x4cc19356f2d37338b9802aa8e8fc58b0373296e70 Ether0.00210376
0x9b609f3d6f21d43be5f43a976c731447afa2f646be159fcbeff30e0182c17dd772494821 hr 27 mins ago0x63691c07822c7beb6f81d6cadb3a6958969104ad IN  0x4cc19356f2d37338b9802aa8e8fc58b0373296e70 Ether0.00045188
0x90f7b0ef301f97dc146200db38623bacc7c13c6f4cd480a3b85c313d9ed2a03072494031 hr 51 mins ago0xf9ee7b307b4294a1734cdf3e93fce5f0513449d7 IN  0x4cc19356f2d37338b9802aa8e8fc58b0373296e70 Ether0.00075188
0x7a406257a52fb9a7f74d7930db39f49864804f3497c970cb067d52b15831fe1072493782 hrs 1 min ago0x3768cde30126c3d9cc7b9cdc23e41865b7c26be7 IN  0x4cc19356f2d37338b9802aa8e8fc58b0373296e70 Ether0.0001042268
0xb3869a577baeedd98a81aded4bda75039cb1b2789d7463531c5dfff661f9ccf572493632 hrs 5 mins agoBinance_2 IN  0x4cc19356f2d37338b9802aa8e8fc58b0373296e70 Ether0.00210632
0xdc68a512d1210d8090099ac021b105d61c377a57bd1c69a3801668a503e3b36b72493282 hrs 16 mins agoBinance_3 IN  0x4cc19356f2d37338b9802aa8e8fc58b0373296e70 Ether0.00210376
0xe7713fed57d5243042de5fa597e8d141759e7bde6dd05d7e478357beb329a20e72493282 hrs 16 mins agoBinance_2 IN  0x4cc19356f2d37338b9802aa8e8fc58b0373296e70 Ether0.00210376
0xd54a2f28bf1a3cb7b761b5b9b93852027158a942ac0578264e8528469f6dc93872493062 hrs 23 mins ago0xf212ac92d3ff64a2b7ea095ced9d424c1826ab3b IN  0x4cc19356f2d37338b9802aa8e8fc58b0373296e70 Ether0.000135564
0xef7aa4c22af0484dd8d5a77c82d826eff633702b6eac9c8cbce3f57617c3edad72491933 hrs 6 mins agoBinance_1 IN  0x4cc19356f2d37338b9802aa8e8fc58b0373296e70 Ether0.00210376
0x7d67cca8f8f16a4eb2e6a84508576348d102494e4442d2422f21e732f417492e72484697 hrs 18 mins ago0x4f5d092582077d0e4a7f901acdf0c3c4675dbfab IN  0x4cc19356f2d37338b9802aa8e8fc58b0373296e70 Ether0.00045316
0xf8fb8cb7fb9ec20e6cb0eb7390d99978520f870a8803c6d7a83ba5af13715d4b72483627 hrs 51 mins ago0xa89a1278ac85367f38bdf6746658ce2b9875526e IN  0x4cc19356f2d37338b9802aa8e8fc58b0373296e70 Ether0.001632398
0x47f520cc0836b26fd6747695fbe37501747e5d6e5bddf198b76a0989bce4105e72482308 hrs 37 mins ago0x8fd0d3b4979342524e6c8ba9ff0054ec920409c7 IN  0x4cc19356f2d37338b9802aa8e8fc58b0373296e70 Ether0.00045316
0x2b6679733f16b7a7cc113f4c6e3a81b4e72ce96467138a9131a97beb0adafccf72481459 hrs 5 mins agoKucoin IN  0x4cc19356f2d37338b9802aa8e8fc58b0373296e70 Ether0.00078891
0x569341c2bdc0a160970a53a6d9c3fca6690965b6e83f14ae90a6c76357547023724711914 hrs 47 mins ago0x5ea301f121c861f4921809a3db1b458b9d7f7eb7 IN  0x4cc19356f2d37338b9802aa8e8fc58b0373296e70 Ether0.00045188
0xa9c957206eebdd6a49538ab7b16cba1a31968824d5bf016f751f0e14fea02dd5724703315 hrs 15 mins ago0x05f51aab068caa6ab7eeb672f88c180f67f17ec7 IN  0x4cc19356f2d37338b9802aa8e8fc58b0373296e70 Ether0.000631128
0xe07db98eb06041909b445cb37e91ad5b627b027b4213e2b602d49a56577167b3724679716 hrs 35 mins agoKucoin IN  0x4cc19356f2d37338b9802aa8e8fc58b0373296e70 Ether0.0006610716
0xe8a3ce723e81745cd80d3e0c1b0165408acf15edc0b208b9bde034abbe5f3469724667617 hrs 16 mins ago0x9e4bd92f6a6074b8046be60771c98c8254ff2088 IN  0x4cc19356f2d37338b9802aa8e8fc58b0373296e70 Ether0.00045316
0xd657b6735663de6a8143d5ab4580dea9dd08f1f7523b7c1a3f338be6812a915c724661617 hrs 41 mins agoKucoin IN  0x4cc19356f2d37338b9802aa8e8fc58b0373296e70 Ether0.00070772352
0xd37fe9996007dce408c75943da5d6df3801fa2a37a909e82e45a7e35b12fdd88724604020 hrs 49 mins agoBinance_3 IN  0x4cc19356f2d37338b9802aa8e8fc58b0373296e70 Ether0.00210376
0x0c72bbd2af33808ec63da6f36b76f0ed6e79d26f3e7a6df0b103314b9daa1d3a72454201 day 17 mins ago0xd16bb6bfdd07247a17565e9d8796d68b0a083c6c IN  0x4cc19356f2d37338b9802aa8e8fc58b0373296e70 Ether0.00045188
0x57cbea9de3b6859a1af31371b86fc03a32af4dc8fb7ff1f6e6ec105ffd75e33d72453221 day 55 mins ago0xe008a106666eff51bce609c35ec3041cd4e8fa74 IN  0x4cc19356f2d37338b9802aa8e8fc58b0373296e70 Ether0.000300752
0x846f9b489bee7b0526961121cb59fee616e0628a2a2f0dfe5f39993b4886840172451511 day 1 hr agoKucoin IN  0x4cc19356f2d37338b9802aa8e8fc58b0373296e70 Ether0.00083909808
0x853720ccbdf049ddbc989cada3ae986489cc780996d634ea572d3848bd8e091c72441291 day 7 hrs ago0xd0b5ef11a04199e66811a5029e0a192e166f58b7 IN  0x4cc19356f2d37338b9802aa8e8fc58b0373296e70 Ether0.000288915
[ Download CSV Export 

Latest 1 Internal Transaction Internal Transactions as a result of Contract Execution

Parent TxHash Block Age From To Value
0x3ef81d7dbf944307154b1c93c1f0284795b7fdd38fbad2ba318f52043799b2ab4891159406 days 2 hrs ago0x8d4b2cffe2dcbbf06eaa5920401db86ca5fb8177  Contract Creation0 Ether
[ Download CSV Export 
Warning: The compiled contract might be susceptible to ExpExponentCleanup (medium/high-severity), EventStructWrongData (very low-severity), NestedArrayFunctionCallDecoder (medium-severity) Solidity Compiler Bugs.

Contract Source Code Verified (Exact Match)
Contract Name: SelfKeyToken
Compiler Version: v0.4.19+commit.c4cbbb05
Optimization Enabled: Yes
Runs (Optimizer):  200


Contract Source Code
pragma solidity ^0.4.18;


/**
 * @title SafeMath
 * @dev Math operations with safety checks that throw on error
 */
library SafeMath {
  function mul(uint256 a, uint256 b) internal pure returns (uint256) {
    if (a == 0) {
      return 0;
    }
    uint256 c = a * b;
    assert(c / a == b);
    return c;
  }

  function div(uint256 a, uint256 b) internal pure returns (uint256) {
    // assert(b > 0); // Solidity automatically throws when dividing by 0
    uint256 c = a / b;
    // assert(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) {
    assert(b <= a);
    return a - b;
  }

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



/**
 * @title ERC20Basic
 * @dev Simpler version of ERC20 interface
 * @dev see https://github.com/ethereum/EIPs/issues/179
 */
contract ERC20Basic {
  uint256 public totalSupply;
  function balanceOf(address who) public view returns (uint256);
  function transfer(address to, uint256 value) public returns (bool);
  event Transfer(address indexed from, address indexed to, uint256 value);
}









/**
 * @title ERC20 interface
 * @dev see https://github.com/ethereum/EIPs/issues/20
 */
contract ERC20 is ERC20Basic {
  function allowance(address owner, address spender) public view returns (uint256);
  function transferFrom(address from, address to, uint256 value) public returns (bool);
  function approve(address spender, uint256 value) public returns (bool);
  event Approval(address indexed owner, address indexed spender, uint256 value);
}


/**
 * @title SafeERC20
 * @dev Wrappers around ERC20 operations that throw on failure.
 * To use this library you can add a `using SafeERC20 for ERC20;` statement to your contract,
 * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.
 */
library SafeERC20 {
  function safeTransfer(ERC20Basic token, address to, uint256 value) internal {
    assert(token.transfer(to, value));
  }

  function safeTransferFrom(ERC20 token, address from, address to, uint256 value) internal {
    assert(token.transferFrom(from, to, value));
  }

  function safeApprove(ERC20 token, address spender, uint256 value) internal {
    assert(token.approve(spender, value));
  }
}



/**
 * @title CrowdsaleConfig
 * @dev Holds all constants for SelfKeyCrowdsale contract
*/
contract CrowdsaleConfig {
    uint256 public constant TOKEN_DECIMALS = 18;
    uint256 public constant MIN_TOKEN_UNIT = 10 ** uint256(TOKEN_DECIMALS);

    // Initial distribution amounts
    uint256 public constant TOTAL_SUPPLY_CAP = 6000000000 * MIN_TOKEN_UNIT;

    // 33% of the total supply cap
    uint256 public constant SALE_CAP = 1980000000 * MIN_TOKEN_UNIT;

    // Minimum cap per purchaser on public sale = $100 in KEY (at $0.015)
    uint256 public constant PURCHASER_MIN_TOKEN_CAP = 6666 * MIN_TOKEN_UNIT;

    // Maximum cap per purchaser on first day of public sale = $3,000 in KEY (at $0.015)
    uint256 public constant PURCHASER_MAX_TOKEN_CAP_DAY1 = 200000 * MIN_TOKEN_UNIT;

    // Maximum cap per purchaser on public sale = $18,000 in KEY (at $0.015)
    uint256 public constant PURCHASER_MAX_TOKEN_CAP = 1200000 * MIN_TOKEN_UNIT;

    // 16.5%
    uint256 public constant FOUNDATION_POOL_TOKENS = 876666666 * MIN_TOKEN_UNIT;
    uint256 public constant FOUNDATION_POOL_TOKENS_VESTED = 113333334 * MIN_TOKEN_UNIT;

    // Approx 33%
    uint256 public constant COMMUNITY_POOL_TOKENS = 1980000000 * MIN_TOKEN_UNIT;

    // Founders' distribution. Total = 16.5%
    uint256 public constant FOUNDERS_TOKENS = 330000000 * MIN_TOKEN_UNIT;
    uint256 public constant FOUNDERS_TOKENS_VESTED_1 = 330000000 * MIN_TOKEN_UNIT;
    uint256 public constant FOUNDERS_TOKENS_VESTED_2 = 330000000 * MIN_TOKEN_UNIT;

    // 1% for legal advisors
    uint256 public constant LEGAL_EXPENSES_1_TOKENS = 54000000 * MIN_TOKEN_UNIT;
    uint256 public constant LEGAL_EXPENSES_2_TOKENS = 6000000 * MIN_TOKEN_UNIT;

    // KEY price in USD (thousandths)
    uint256 public constant TOKEN_PRICE_THOUSANDTH = 15;  // $0.015 per KEY

    // Contract wallet addresses for initial allocation
    address public constant CROWDSALE_WALLET_ADDR = 0xE0831b1687c9faD3447a517F9371E66672505dB0;
    address public constant FOUNDATION_POOL_ADDR = 0xD68947892Ef4D94Cdef7165b109Cf6Cd3f58A8e8;
    address public constant FOUNDATION_POOL_ADDR_VEST = 0xd0C24Bb82e71A44eA770e84A3c79979F9233308D;
    address public constant COMMUNITY_POOL_ADDR = 0x0506c5485AE54aB14C598Ef16C459409E5d8Fc03;
    address public constant FOUNDERS_POOL_ADDR = 0x4452d6454e777743a5Ee233fbe873055008fF528;
    address public constant LEGAL_EXPENSES_ADDR_1 = 0xb57911380F13A0a9a6Ba6562248674B5f56D7BFE;
    address public constant LEGAL_EXPENSES_ADDR_2 = 0x9be281CdcF34B3A01468Ad1008139410Ba5BB2fB;

    // 6 months period, in seconds, for pre-commitment half-vesting
    uint64 public constant PRECOMMITMENT_VESTING_SECONDS = 15552000;
}



/**
 * @title Ownable
 * @dev The Ownable contract has an owner address, and provides basic authorization control
 * functions, this simplifies the implementation of "user permissions".
 */
contract Ownable {
  address public owner;


  event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);


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


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


  /**
   * @dev Allows the current owner to transfer control of the contract to a newOwner.
   * @param newOwner The address to transfer ownership to.
   */
  function transferOwnership(address newOwner) public onlyOwner {
    require(newOwner != address(0));
    OwnershipTransferred(owner, newOwner);
    owner = newOwner;
  }

}















/**
 * @title Basic token
 * @dev Basic version of StandardToken, with no allowances.
 */
contract BasicToken is ERC20Basic {
  using SafeMath for uint256;

  mapping(address => uint256) balances;

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

    // SafeMath.sub will throw if there is not enough balance.
    balances[msg.sender] = balances[msg.sender].sub(_value);
    balances[_to] = balances[_to].add(_value);
    Transfer(msg.sender, _to, _value);
    return true;
  }

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

}




/**
 * @title Standard ERC20 token
 *
 * @dev Implementation of the basic standard token.
 * @dev https://github.com/ethereum/EIPs/issues/20
 * @dev Based on code by FirstBlood: https://github.com/Firstbloodio/token/blob/master/smart_contract/FirstBloodToken.sol
 */
contract StandardToken is ERC20, BasicToken {

  mapping (address => mapping (address => uint256)) internal allowed;


  /**
   * @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));
    require(_value <= balances[_from]);
    require(_value <= allowed[_from][msg.sender]);

    balances[_from] = balances[_from].sub(_value);
    balances[_to] = balances[_to].add(_value);
    allowed[_from][msg.sender] = allowed[_from][msg.sender].sub(_value);
    Transfer(_from, _to, _value);
    return true;
  }

  /**
   * @dev Approve the passed address to spend the specified amount of tokens on behalf of msg.sender.
   *
   * Beware that changing an allowance with this method brings the risk that someone may use both the old
   * and the new allowance by unfortunate transaction ordering. One possible solution to mitigate this
   * race condition is to first reduce the spender's allowance to 0 and set the desired value afterwards:
   * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
   * @param _spender The address which will spend the funds.
   * @param _value The amount of tokens to be spent.
   */
  function approve(address _spender, uint256 _value) public returns (bool) {
    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 A uint256 specifying the amount of tokens still available for the spender.
   */
  function allowance(address _owner, address _spender) public view returns (uint256) {
    return allowed[_owner][_spender];
  }

  /**
   * @dev Increase the amount of tokens that an owner allowed to a spender.
   *
   * approve should be called when allowed[_spender] == 0. To increment
   * allowed value is better to use this function to avoid 2 calls (and wait until
   * the first transaction is mined)
   * From MonolithDAO Token.sol
   * @param _spender The address which will spend the funds.
   * @param _addedValue The amount of tokens to increase the allowance by.
   */
  function increaseApproval(address _spender, uint _addedValue) public returns (bool) {
    allowed[msg.sender][_spender] = allowed[msg.sender][_spender].add(_addedValue);
    Approval(msg.sender, _spender, allowed[msg.sender][_spender]);
    return true;
  }

  /**
   * @dev Decrease the amount of tokens that an owner allowed to a spender.
   *
   * approve should be called when allowed[_spender] == 0. To decrement
   * allowed value is better to use this function to avoid 2 calls (and wait until
   * the first transaction is mined)
   * From MonolithDAO Token.sol
   * @param _spender The address which will spend the funds.
   * @param _subtractedValue The amount of tokens to decrease the allowance by.
   */
  function decreaseApproval(address _spender, uint _subtractedValue) public returns (bool) {
    uint oldValue = allowed[msg.sender][_spender];
    if (_subtractedValue > oldValue) {
      allowed[msg.sender][_spender] = 0;
    } else {
      allowed[msg.sender][_spender] = oldValue.sub(_subtractedValue);
    }
    Approval(msg.sender, _spender, allowed[msg.sender][_spender]);
    return true;
  }

}





/**
 * @title Mintable token
 * @dev Simple ERC20 Token example, with mintable token creation
 * @dev Issue: * https://github.com/OpenZeppelin/zeppelin-solidity/issues/120
 * Based on code by TokenMarketNet: https://github.com/TokenMarketNet/ico/blob/master/contracts/MintableToken.sol
 */

contract MintableToken is StandardToken, Ownable {
  event Mint(address indexed to, uint256 amount);
  event MintFinished();

  bool public mintingFinished = false;


  modifier canMint() {
    require(!mintingFinished);
    _;
  }

  /**
   * @dev Function to mint tokens
   * @param _to The address that will receive the minted tokens.
   * @param _amount The amount of tokens to mint.
   * @return A boolean that indicates if the operation was successful.
   */
  function mint(address _to, uint256 _amount) onlyOwner canMint public returns (bool) {
    totalSupply = totalSupply.add(_amount);
    balances[_to] = balances[_to].add(_amount);
    Mint(_to, _amount);
    Transfer(address(0), _to, _amount);
    return true;
  }

  /**
   * @dev Function to stop minting new tokens.
   * @return True if the operation was successful.
   */
  function finishMinting() onlyOwner canMint public returns (bool) {
    mintingFinished = true;
    MintFinished();
    return true;
  }
}

/* solhint-disable not-rely-on-time */









/**
 * @title SelfKeyToken
 * @dev SelfKey Token implementation.
 */
contract SelfKeyToken is MintableToken {
    string public constant name = 'SelfKey'; //solhint-disable-line const-name-snakecase
    string public constant symbol = 'KEY'; //solhint-disable-line const-name-snakecase
    uint256 public constant decimals = 18; //solhint-disable-line const-name-snakecase

    uint256 public cap;
    bool private transfersEnabled = false;

    event Burned(address indexed burner, uint256 value);

    /**
     * @dev Only the contract owner can transfer without restrictions.
     *      Regular holders need to wait until sale is finalized.
     * @param _sender — The address sending the tokens
     * @param _value — The number of tokens to send
     */
    modifier canTransfer(address _sender, uint256 _value) {
        require(transfersEnabled || _sender == owner);
        _;
    }

    /**
     * @dev Constructor that sets a maximum supply cap.
     * @param _cap — The maximum supply cap.
     */
    function SelfKeyToken(uint256 _cap) public {
        cap = _cap;
    }

    /**
     * @dev Overrides MintableToken.mint() for restricting supply under cap
     * @param _to — The address to receive minted tokens
     * @param _value — The number of tokens to mint
     */
    function mint(address _to, uint256 _value) public onlyOwner canMint returns (bool) {
        require(totalSupply.add(_value) <= cap);
        return super.mint(_to, _value);
    }

    /**
     * @dev Checks modifier and allows transfer if tokens are not locked.
     * @param _to — The address to receive tokens
     * @param _value — The number of tokens to send
     */
    function transfer(address _to, uint256 _value)
        public canTransfer(msg.sender, _value) returns (bool)
    {
        return super.transfer(_to, _value);
    }

    /**
     * @dev Checks modifier and allows transfer if tokens are not locked.
     * @param _from — The address to send tokens from
     * @param _to — The address to receive tokens
     * @param _value — The number of tokens to send
     */
    function transferFrom(address _from, address _to, uint256 _value)
        public canTransfer(_from, _value) returns (bool)
    {
        return super.transferFrom(_from, _to, _value);
    }

    /**
     * @dev Enables token transfers.
     *      Called when the token sale is successfully finalized
     */
    function enableTransfers() public onlyOwner {
        transfersEnabled = true;
    }

    /**
    * @dev Burns a specific number of tokens.
    * @param _value — The number of tokens to be burned.
    */
    function burn(uint256 _value) public onlyOwner {
        require(_value > 0);

        address burner = msg.sender;
        balances[burner] = balances[burner].sub(_value);
        totalSupply = totalSupply.sub(_value);
        Burned(burner, _value);
    }
}












/**
 * @title TokenTimelock
 * @dev TokenTimelock is a token holder contract that will allow a
 * beneficiary to extract the tokens after a given release time
 */
contract TokenTimelock {
  using SafeERC20 for ERC20Basic;

  // ERC20 basic token contract being held
  ERC20Basic public token;

  // beneficiary of tokens after they are released
  address public beneficiary;

  // timestamp when token release is enabled
  uint256 public releaseTime;

  function TokenTimelock(ERC20Basic _token, address _beneficiary, uint256 _releaseTime) public {
    require(_releaseTime > now);
    token = _token;
    beneficiary = _beneficiary;
    releaseTime = _releaseTime;
  }

  /**
   * @notice Transfers tokens held by timelock to beneficiary.
   */
  function release() public {
    require(now >= releaseTime);

    uint256 amount = token.balanceOf(this);
    require(amount > 0);

    token.safeTransfer(beneficiary, amount);
  }
}






/**
 * @title RefundVault
 * @dev This contract is used for storing funds while a crowdsale
 * is in progress. Supports refunding the money if crowdsale fails,
 * and forwarding it if crowdsale is successful.
 */
contract RefundVault is Ownable {
  using SafeMath for uint256;

  enum State { Active, Refunding, Closed }

  mapping (address => uint256) public deposited;
  address public wallet;
  State public state;

  event Closed();
  event RefundsEnabled();
  event Refunded(address indexed beneficiary, uint256 weiAmount);

  function RefundVault(address _wallet) public {
    require(_wallet != address(0));
    wallet = _wallet;
    state = State.Active;
  }

  function deposit(address investor) onlyOwner public payable {
    require(state == State.Active);
    deposited[investor] = deposited[investor].add(msg.value);
  }

  function close() onlyOwner public {
    require(state == State.Active);
    state = State.Closed;
    Closed();
    wallet.transfer(this.balance);
  }

  function enableRefunds() onlyOwner public {
    require(state == State.Active);
    state = State.Refunding;
    RefundsEnabled();
  }

  function refund(address investor) public {
    require(state == State.Refunding);
    uint256 depositedValue = deposited[investor];
    deposited[investor] = 0;
    investor.transfer(depositedValue);
    Refunded(investor, depositedValue);
  }
}



/**
 * @title SelfKeyCrowdsale
 * @dev SelfKey Token Crowdsale implementation.
 */
// solhint-disable-next-line max-states-count
contract SelfKeyCrowdsale is Ownable, CrowdsaleConfig {
    using SafeMath for uint256;
    using SafeERC20 for SelfKeyToken;

    // whitelist of addresses that can perform precommitments and KYC verifications
    mapping(address => bool) public isVerifier;

    // Token contract
    SelfKeyToken public token;

    uint64 public startTime;
    uint64 public endTime;

    // Minimum tokens expected to sell
    uint256 public goal;

    // How many tokens a buyer gets per ETH
    uint256 public rate = 51800;

    // ETH price in USD, can be later updated until start date
    uint256 public ethPrice = 777;

    // Total amount of tokens purchased, including pre-sale
    uint256 public totalPurchased = 0;

    mapping(address => bool) public kycVerified;
    mapping(address => uint256) public tokensPurchased;

    // a mapping of dynamically instantiated token timelocks for each pre-commitment beneficiary
    mapping(address => address) public vestedTokens;

    bool public isFinalized = false;

    // Token Timelocks
    TokenTimelock public foundersTimelock1;
    TokenTimelock public foundersTimelock2;
    TokenTimelock public foundationTimelock;

    // Vault to hold funds until crowdsale is finalized. Allows refunding if crowdsale is not successful.
    RefundVault public vault;

    // Crowdsale events
    event TokenPurchase(
        address indexed purchaser,
        address indexed beneficiary,
        uint256 value,
        uint256 amount
    );

    event VerifiedKYC(address indexed participant);

    event AddedPrecommitment(
        address indexed participant,
        uint256 tokensAllocated
    );

    event Finalized();

    modifier verifierOnly() {
        require(isVerifier[msg.sender]);
        _;
    }

    /**
     * @dev Crowdsale contract constructor
     * @param _startTime — Unix timestamp representing the crowdsale start time
     * @param _endTime — Unix timestamp representing the crowdsale start time
     * @param _goal — Minimum amount of tokens expected to sell.
     */
    function SelfKeyCrowdsale(
        uint64 _startTime,
        uint64 _endTime,
        uint256 _goal
    ) public
    {
        require(_endTime > _startTime);

        // sets contract owner as a verifier
        isVerifier[msg.sender] = true;

        token = new SelfKeyToken(TOTAL_SUPPLY_CAP);

        // mints all possible tokens to the crowdsale contract
        token.mint(address(this), TOTAL_SUPPLY_CAP);
        token.finishMinting();

        startTime = _startTime;
        endTime = _endTime;
        goal = _goal;

        vault = new RefundVault(CROWDSALE_WALLET_ADDR);

        // Set timelocks to 6 months and a year after startTime, respectively
        uint64 sixMonthLock = uint64(startTime + 15552000);
        uint64 yearLock = uint64(startTime + 31104000);

        // Instantiation of token timelocks
        foundersTimelock1 = new TokenTimelock(token, FOUNDERS_POOL_ADDR, sixMonthLock);
        foundersTimelock2 = new TokenTimelock(token, FOUNDERS_POOL_ADDR, yearLock);
        foundationTimelock = new TokenTimelock(token, FOUNDATION_POOL_ADDR_VEST, yearLock);

        // Genesis allocation of tokens
        token.safeTransfer(FOUNDATION_POOL_ADDR, FOUNDATION_POOL_TOKENS);
        token.safeTransfer(COMMUNITY_POOL_ADDR, COMMUNITY_POOL_TOKENS);
        token.safeTransfer(FOUNDERS_POOL_ADDR, FOUNDERS_TOKENS);
        token.safeTransfer(LEGAL_EXPENSES_ADDR_1, LEGAL_EXPENSES_1_TOKENS);
        token.safeTransfer(LEGAL_EXPENSES_ADDR_2, LEGAL_EXPENSES_2_TOKENS);

        // Allocation of vested tokens
        token.safeTransfer(foundersTimelock1, FOUNDERS_TOKENS_VESTED_1);
        token.safeTransfer(foundersTimelock2, FOUNDERS_TOKENS_VESTED_2);
        token.safeTransfer(foundationTimelock, FOUNDATION_POOL_TOKENS_VESTED);
    }

    /**
     * @dev Fallback function is used to buy tokens.
     *      It's the only entry point since `buyTokens` is internal
     */
    function () public payable {
        buyTokens(msg.sender);
    }

    /**
     * @dev Adds an address to the whitelist of Verifiers
     * @param _address - address of the verifier
     */
    function addVerifier (address _address) public onlyOwner {
        isVerifier[_address] = true;
    }

    /**
     * @dev Removes an address from the whitelist of Verifiers
     * @param _address - address of the verifier to be removed
     */
    function removeVerifier (address _address) public onlyOwner {
        isVerifier[_address] = false;
    }

    /**
     * @dev Sets a new start date as long as token hasn't started yet
     * @param _startTime - unix timestamp of the new start time
     */
    function setStartTime (uint64 _startTime) public onlyOwner {
        require(now < startTime);
        require(_startTime > now);
        require(_startTime < endTime);

        startTime = _startTime;
    }

    /**
     * @dev Sets a new end date as long as end date hasn't been reached
     * @param _endTime - unix timestamp of the new end time
     */
    function setEndTime (uint64 _endTime) public onlyOwner {
        require(now < endTime);
        require(_endTime > now);
        require(_endTime > startTime);

        endTime = _endTime;
    }

    /**
     * @dev Updates the ETH/USD conversion rate as long as the public sale hasn't started
     * @param _ethPrice - Updated conversion rate
     */
    function setEthPrice(uint256 _ethPrice) public onlyOwner {
        require(now < startTime);
        require(_ethPrice > 0);

        ethPrice = _ethPrice;
        rate = ethPrice.mul(1000).div(TOKEN_PRICE_THOUSANDTH);
    }

    /**
     * @dev Must be called after crowdsale ends, to do some extra finalization
     *      work. Calls the contract's finalization function.
     */
    function finalize() public onlyOwner {
        require(now > startTime);
        require(!isFinalized);

        finalization();
        Finalized();

        isFinalized = true;
    }

    /**
     * @dev If crowdsale is unsuccessful, a refund can be claimed back
     */
    function claimRefund(address participant) public {
        // requires sale to be finalized and goal not reached,
        require(isFinalized);
        require(!goalReached());

        vault.refund(participant);
    }

    /**
     * @dev If crowdsale is unsuccessful, participants can claim refunds
     */
    function goalReached() public constant returns (bool) {
        return totalPurchased >= goal;
    }

    /**
     * @dev Release time-locked tokens
     */
    function releaseLockFounders1() public {
        foundersTimelock1.release();
    }

    function releaseLockFounders2() public {
        foundersTimelock2.release();
    }

    function releaseLockFoundation() public {
        foundationTimelock.release();
    }

    /**
     * @dev Release time-locked tokens for any vested address
     */
    function releaseLock(address participant) public {
        require(vestedTokens[participant] != 0x0);

        TokenTimelock timelock = TokenTimelock(vestedTokens[participant]);
        timelock.release();
    }

    /**
     * @dev Verifies KYC for given participant.
     *      This enables token purchases by the participant addres
     */
    function verifyKYC(address participant) public verifierOnly {
        kycVerified[participant] = true;

        VerifiedKYC(participant);
    }

    /**
     * @dev Adds an address for pre-sale commitments made off-chain.
     * @param beneficiary — Address of the already verified participant
     * @param tokensAllocated — Exact amount of KEY tokens (including decimal places) to allocate
     * @param halfVesting — determines whether the half the tokens will be time-locked or not
     */
    function addPrecommitment(
        address beneficiary,
        uint256 tokensAllocated,
        bool halfVesting
    ) public verifierOnly
    {
        // requires to be on pre-sale
        require(now < startTime); // solhint-disable-line not-rely-on-time

        kycVerified[beneficiary] = true;

        uint256 tokens = tokensAllocated;
        totalPurchased = totalPurchased.add(tokens);
        tokensPurchased[beneficiary] = tokensPurchased[beneficiary].add(tokens);

        if (halfVesting) {
            // half the tokens are put into a time-lock for a pre-defined period
            uint64 endTimeLock = uint64(startTime + PRECOMMITMENT_VESTING_SECONDS);

            // Sets a timelock for half the tokens allocated
            uint256 half = tokens.div(2);
            TokenTimelock timelock;

            if (vestedTokens[beneficiary] == 0x0) {
                timelock = new TokenTimelock(token, beneficiary, endTimeLock);
                vestedTokens[beneficiary] = address(timelock);
            } else {
                timelock = TokenTimelock(vestedTokens[beneficiary]);
            }

            token.safeTransfer(beneficiary, half);
            token.safeTransfer(timelock, tokens.sub(half));
        } else {
            // all tokens are sent to the participant's address
            token.safeTransfer(beneficiary, tokens);
        }

        AddedPrecommitment(
            beneficiary,
            tokens
        );
    }

    /**
     * @dev Additional finalization logic. Enables token transfers.
     */
    function finalization() internal {
        if (goalReached()) {
            burnUnsold();
            vault.close();
            token.enableTransfers();
        } else {
            vault.enableRefunds();
        }
    }

    /**
     *  @dev Low level token purchase. Only callable internally. Participants MUST be KYC-verified before purchase
     *  @param participant — The address of the token purchaser
     */
    function buyTokens(address participant) internal {
        require(kycVerified[participant]);
        require(now >= startTime);
        require(now < endTime);
        require(!isFinalized);
        require(msg.value != 0);

        // Calculate the token amount to be allocated
        uint256 weiAmount = msg.value;
        uint256 tokens = weiAmount.mul(rate);

        // Update state
        tokensPurchased[participant] = tokensPurchased[participant].add(tokens);
        totalPurchased = totalPurchased.add(tokens);

        require(totalPurchased <= SALE_CAP);
        require(tokensPurchased[participant] >= PURCHASER_MIN_TOKEN_CAP);

        if (now < startTime + 86400) {
            // if still during the first day of token sale, apply different max cap
            require(tokensPurchased[participant] <= PURCHASER_MAX_TOKEN_CAP_DAY1);
        } else {
            require(tokensPurchased[participant] <= PURCHASER_MAX_TOKEN_CAP);
        }

        // Sends ETH contribution to the RefundVault and tokens to participant
        vault.deposit.value(msg.value)(participant);
        token.safeTransfer(participant, tokens);

        TokenPurchase(
            msg.sender,
            participant,
            weiAmount,
            tokens
        );
    }

    /**
     * @dev Burn all remaining (unsold) tokens.
     *      This should be called after sale finalization
     */
    function burnUnsold() internal {
        // All tokens held by this contract get burned
        token.burn(token.balanceOf(this));
    }
}

Contract ABI
[{"constant":true,"inputs":[],"name":"mintingFinished","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"name","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_spender","type":"address"},{"name":"_value","type":"uint256"}],"name":"approve","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"totalSupply","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_from","type":"address"},{"name":"_to","type":"address"},{"name":"_value","type":"uint256"}],"name":"transferFrom","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"decimals","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"cap","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_to","type":"address"},{"name":"_value","type":"uint256"}],"name":"mint","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_value","type":"uint256"}],"name":"burn","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_spender","type":"address"},{"name":"_subtractedValue","type":"uint256"}],"name":"decreaseApproval","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_owner","type":"address"}],"name":"balanceOf","outputs":[{"name":"balance","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"finishMinting","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"owner","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"symbol","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_to","type":"address"},{"name":"_value","type":"uint256"}],"name":"transfer","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"enableTransfers","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_spender","type":"address"},{"name":"_addedValue","type":"uint256"}],"name":"increaseApproval","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_owner","type":"address"},{"name":"_spender","type":"address"}],"name":"allowance","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"inputs":[{"name":"_cap","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"name":"burner","type":"address"},{"indexed":false,"name":"value","type":"uint256"}],"name":"Burned","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"to","type":"address"},{"indexed":false,"name":"amount","type":"uint256"}],"name":"Mint","type":"event"},{"anonymous":false,"inputs":[],"name":"MintFinished","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"previousOwner","type":"address"},{"indexed":true,"name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"owner","type":"address"},{"indexed":true,"name":"spender","type":"address"},{"indexed":false,"name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"from","type":"address"},{"indexed":true,"name":"to","type":"address"},{"indexed":false,"name":"value","type":"uint256"}],"name":"Transfer","type":"event"}]

Contract Creation Code
60606040526003805460a060020a60ff02191690556005805460ff19169055341561002957600080fd5b604051602080610ded8339810160405280805160038054600160a060020a03191633600160a060020a031617905560045550610d8190508061006c6000396000f3006060604052600436106101065763ffffffff7c010000000000000000000000000000000000000000000000000000000060003504166305d2035b811461010b57806306fdde0314610132578063095ea7b3146101bc57806318160ddd146101de57806323b872dd14610203578063313ce5671461022b578063355274ea1461023e57806340c10f191461025157806342966c6814610273578063661884631461028b57806370a08231146102ad5780637d64bcb4146102cc5780638da5cb5b146102df57806395d89b411461030e578063a9059cbb14610321578063af35c6c714610343578063d73dd62314610356578063dd62ed3e14610378578063f2fde38b1461039d575b600080fd5b341561011657600080fd5b61011e6103bc565b604051901515815260200160405180910390f35b341561013d57600080fd5b6101456103cc565b60405160208082528190810183818151815260200191508051906020019080838360005b83811015610181578082015183820152602001610169565b50505050905090810190601f1680156101ae5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34156101c757600080fd5b61011e600160a060020a0360043516602435610403565b34156101e957600080fd5b6101f161046f565b60405190815260200160405180910390f35b341561020e57600080fd5b61011e600160a060020a0360043581169060243516604435610475565b341561023657600080fd5b6101f16104ba565b341561024957600080fd5b6101f16104bf565b341561025c57600080fd5b61011e600160a060020a03600435166024356104c5565b341561027e57600080fd5b61028960043561052c565b005b341561029657600080fd5b61011e600160a060020a03600435166024356105ed565b34156102b857600080fd5b6101f1600160a060020a03600435166106e7565b34156102d757600080fd5b61011e610702565b34156102ea57600080fd5b6102f261078d565b604051600160a060020a03909116815260200160405180910390f35b341561031957600080fd5b61014561079c565b341561032c57600080fd5b61011e600160a060020a03600435166024356107d3565b341561034e57600080fd5b610289610816565b341561036157600080fd5b61011e600160a060020a0360043516602435610840565b341561038357600080fd5b6101f1600160a060020a03600435811690602435166108e4565b34156103a857600080fd5b610289600160a060020a036004351661090f565b60035460a060020a900460ff1681565b60408051908101604052600781527f53656c664b657900000000000000000000000000000000000000000000000000602082015281565b600160a060020a03338116600081815260026020908152604080832094871680845294909152808220859055909291907f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259085905190815260200160405180910390a350600192915050565b60005481565b6005546000908490839060ff168061049a5750600354600160a060020a038381169116145b15156104a557600080fd5b6104b08686866109aa565b9695505050505050565b601281565b60045481565b60035460009033600160a060020a039081169116146104e357600080fd5b60035460a060020a900460ff16156104fa57600080fd5b600454600054610510908463ffffffff610b2c16565b111561051b57600080fd5b6105258383610b3b565b9392505050565b60035460009033600160a060020a0390811691161461054a57600080fd5b6000821161055757600080fd5b5033600160a060020a03811660009081526001602052604090205461057c9083610c48565b600160a060020a038216600090815260016020526040812091909155546105a9908363ffffffff610c4816565b600055600160a060020a0381167f696de425f79f4a40bc6d2122ca50507f0efbeabbff86a84871b7196ab8ea8df78360405190815260200160405180910390a25050565b600160a060020a0333811660009081526002602090815260408083209386168352929052908120548083111561064a57600160a060020a033381166000908152600260209081526040808320938816835292905290812055610681565b61065a818463ffffffff610c4816565b600160a060020a033381166000908152600260209081526040808320938916835292905220555b600160a060020a0333811660008181526002602090815260408083209489168084529490915290819020547f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925915190815260200160405180910390a35060019392505050565b600160a060020a031660009081526001602052604090205490565b60035460009033600160a060020a0390811691161461072057600080fd5b60035460a060020a900460ff161561073757600080fd5b6003805474ff0000000000000000000000000000000000000000191660a060020a1790557fae5184fba832cb2b1f702aca6117b8d265eaf03ad33eb133f19dde0f5920fa0860405160405180910390a150600190565b600354600160a060020a031681565b60408051908101604052600381527f4b45590000000000000000000000000000000000000000000000000000000000602082015281565b6005546000903390839060ff16806107f85750600354600160a060020a038381169116145b151561080357600080fd5b61080d8585610c5a565b95945050505050565b60035433600160a060020a0390811691161461083157600080fd5b6005805460ff19166001179055565b600160a060020a033381166000908152600260209081526040808320938616835292905290812054610878908363ffffffff610b2c16565b600160a060020a0333811660008181526002602090815260408083209489168084529490915290819020849055919290917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591905190815260200160405180910390a350600192915050565b600160a060020a03918216600090815260026020908152604080832093909416825291909152205490565b60035433600160a060020a0390811691161461092a57600080fd5b600160a060020a038116151561093f57600080fd5b600354600160a060020a0380831691167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a36003805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a0392909216919091179055565b6000600160a060020a03831615156109c157600080fd5b600160a060020a0384166000908152600160205260409020548211156109e657600080fd5b600160a060020a0380851660009081526002602090815260408083203390941683529290522054821115610a1957600080fd5b600160a060020a038416600090815260016020526040902054610a42908363ffffffff610c4816565b600160a060020a038086166000908152600160205260408082209390935590851681522054610a77908363ffffffff610b2c16565b600160a060020a03808516600090815260016020908152604080832094909455878316825260028152838220339093168252919091522054610abf908363ffffffff610c4816565b600160a060020a03808616600081815260026020908152604080832033861684529091529081902093909355908516917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9085905190815260200160405180910390a35060019392505050565b60008282018381101561052557fe5b60035460009033600160a060020a03908116911614610b5957600080fd5b60035460a060020a900460ff1615610b7057600080fd5b600054610b83908363ffffffff610b2c16565b6000908155600160a060020a038416815260016020526040902054610bae908363ffffffff610b2c16565b600160a060020a0384166000818152600160205260409081902092909255907f0f6798a560793a54c3bcfe86a93cde1e73087d944c0ea20544137d41213968859084905190815260200160405180910390a2600160a060020a03831660007fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8460405190815260200160405180910390a350600192915050565b600082821115610c5457fe5b50900390565b6000600160a060020a0383161515610c7157600080fd5b600160a060020a033316600090815260016020526040902054821115610c9657600080fd5b600160a060020a033316600090815260016020526040902054610cbf908363ffffffff610c4816565b600160a060020a033381166000908152600160205260408082209390935590851681522054610cf4908363ffffffff610b2c16565b600160a060020a0380851660008181526001602052604090819020939093559133909116907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9085905190815260200160405180910390a3506001929150505600a165627a7a72305820a0db4a7417f51dac893a505484403c713964d24a776ca71d61c0b642f6760aae002900000000000000000000000000000000000000001363156bbee3016d70000000


    Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
00000000000000000000000000000000000000001363156bbee3016d70000000

-----Encoded View---------------
1 Constructor Arguments found :
Arg [0] : 00000000000000000000000000000000000000001363156bbee3016d70000000


   Swarm Source:
bzzr://a0db4a7417f51dac893a505484403c713964d24a776ca71d61c0b642f6760aae
Block Age transaction Difficulty GasUsed Reward
Block Age Uncle Number Difficulty GasUsed Reward
Make sure to use the "Vote Down" button for any spammy posts, and the "Vote Up" for interesting conversations.