Sponsored:   Temco - Join the Largest VC Backed ICO on the Bitcoin Network! TEMCO KYC Whitelist Starts Now!!
Contract Overview
Balance: 0 Ether
Ether Value: $0
Transactions: 140 txns
Token Tracker: Blok (BLO)
Misc:
Address Watch: Add To Watch List
Contract Creator: 0x4863e8c8bd928bd1cf85eea784736e35c2f48a6aat txn 0xf98121f0ad1a6c927d6bfff8e0557e69eb08a6f87a5e2e5db5288f200188dd07
Token Balance:
 Latest 25 transactions from a total of 140 transactions

TxHash Age From To Value [TxFee]
0x6f420aa3c27e7ae38038c4c0de330f3d804122b80d6d79db7a052a9756b0a4e425 days 12 hrs ago0xbe5f29686d9e99f2dd3d51eaf6650989b6e0afd4  IN   0x8426d0dc03335d4a391bf4cf7fe546ff89549de40 Ether0.001519788
0xe6604bf80164ee13ff4f9cece726d73843d8b2ec57b47ae9abf4da0f2bbd31c927 days 11 mins ago0x1c67c70347a4922df28aa7b421583ed867b1bcc8  IN   0x8426d0dc03335d4a391bf4cf7fe546ff89549de40 Ether0.000419166
0xf12dee9f7d663338a0f1efdbeac00812094df2319a34b6a4fe4dfac693b3572e31 days 14 hrs ago0xa2f831857be9d0e632f424741e7f0852c4915f01  IN   0x8426d0dc03335d4a391bf4cf7fe546ff89549de40 Ether0.00116115
0x51a64e476eac44ee181f45b2498e58448136753f3f436d94353f0b2424cd9ea443 days 2 hrs ago0x070cd8501672850aea81fe9cf67b6464efd1a37a  IN   0x8426d0dc03335d4a391bf4cf7fe546ff89549de40 Ether0.000185528
0xb03120ff4bb8d0dbbaddff09ef44a8607a4122ca4f7744bf77dd511506c6db8571 days 20 hrs ago0x5d698041326fa0a8d238cea6ad4fe0571de33249  IN   0x8426d0dc03335d4a391bf4cf7fe546ff89549de40 Ether0.000907412
0xae618e1c080bb1d9774768d23e486419fac1d9d955e9883650b9f2585c5a90c071 days 20 hrs ago0x5d698041326fa0a8d238cea6ad4fe0571de33249  IN   0x8426d0dc03335d4a391bf4cf7fe546ff89549de40 Ether0.002137412
0x87ccc30629bc016591b8ee4121626f081ae0f75d7081e84127b16a28b02c89db75 days 12 hrs ago0x5f1fd2fb5d74403824a26cdf6ffcd809056aed56  IN   0x8426d0dc03335d4a391bf4cf7fe546ff89549de40 Ether0.000652036
0x02609f4cb5121c95fb99afecbd454a43a91250b3a0aaf07c5ab7117e1391fc5282 days 57 mins ago0xe2d1ec062201dd4b422b49c6638f9e169c227405  IN   0x8426d0dc03335d4a391bf4cf7fe546ff89549de40 Ether0.00046446
0x9c66687fc70921196a2fad835df8671992fb1c9f11306aa1d85253a207a0303382 days 1 hr ago0x10efc29d1f9157ab167909ef77d0690cff9a8d79  IN   0x8426d0dc03335d4a391bf4cf7fe546ff89549de40 Ether0.000176544
0x8d70f9bd19e6c8081ba2a34c4d7e9cd5cf8d3f9b8ec20855d51a8eaf12fb28c595 days 15 hrs ago0xa47202a61da5c6e061f094675d46d6bf59b1d75f  IN   0x8426d0dc03335d4a391bf4cf7fe546ff89549de40 Ether0.00046574
0x5772860dbb00afcb49b96f37474feb66da18f9edf936da862cc14c70a3f8e1a697 days 9 hrs ago0x52d0d07ec186c760c9f0c3776275ceb7bfb5dfb4  IN   0x8426d0dc03335d4a391bf4cf7fe546ff89549de40 Ether0.00018502
0x19bb933be0a271d68c2ee1169af28a59e9f988b42f80fafe8a3bc3fb05401472112 days 3 hrs ago0x4694a75d51d35172fdaa8052aab1c76901ba40ce  IN   0x8426d0dc03335d4a391bf4cf7fe546ff89549de40 Ether0.00018502
0x11c7e390eb46e33e7ccf9cf717d9ca357ed1cf3d5754787b40fc689c4d2e51aa123 days 2 hrs ago0xb1ac9db0d6a1ec291f427ad03fc3b632e1e93a56  IN   0x8426d0dc03335d4a391bf4cf7fe546ff89549de40 Ether0.000510906
0x57785b3d0ffcd234a4753b16d5889a0d67939d15698aa46eb5c8ee33156615c2126 days 23 hrs ago0x537f904ba3dd9ea01322573c40f3a92586cbd3be  IN   0x8426d0dc03335d4a391bf4cf7fe546ff89549de40 Ether0.002134788
0x07ff1d8c21e6ac587539763466210e9199f13788f8e69b07dc12ebc107f81f16128 days 6 hrs ago0xb388634f94d42241fb8882f47b679b53ef8d1e39  IN   0x8426d0dc03335d4a391bf4cf7fe546ff89549de40 Ether0.000222024
0x55020ad81b66900496d660f04488f8d6e805de0f4c9798c88ab08f862bbfc222128 days 16 hrs ago0x43810069958805d5bec6430eacc273a4b940c658  IN   0x8426d0dc03335d4a391bf4cf7fe546ff89549de40 Ether0.000111588
0x6dfcec6befc770879644e9c75637116cd00bb93657e1d6bcf5625abcaced6501128 days 16 hrs ago0x76ab8405b80f3f68636c7a7c39587cb85f006647  IN   0x8426d0dc03335d4a391bf4cf7fe546ff89549de40 Ether0.000222024
0xa90b180db75ab021c8fa85539505d5d6be7ff5c88988fa966ffb4f72d663c0df131 days 23 hrs ago0xa8bbe616a51a2b1c2f4bf47ebabf12cfcc4a2eed  IN   0x8426d0dc03335d4a391bf4cf7fe546ff89549de40 Ether0.000111204
0xad794fa872dd36cfd33bd1d89d574d952dc4d24e89729ad267b321de1fcd2d48133 days 5 hrs ago0xb1ac9db0d6a1ec291f427ad03fc3b632e1e93a56  IN   0x8426d0dc03335d4a391bf4cf7fe546ff89549de40 Ether0.000185784
0x55af27d101f6da08a4f422613a87dfdf2d5f8e785be11b4a7aafbc2f5accd708134 days 22 hrs ago0x9d9c2a27e4739e7bf65c10ca3c6ca15165e0a502  IN   0x8426d0dc03335d4a391bf4cf7fe546ff89549de40 Ether0.000186296
0xbc341f6ebac5529619a7ec40ada099dc0f588067a03f14b1eb3b938ac8616ef2138 days 46 mins ago0xbc4a9e6a990a646b4cccb2b4b07cd1f3232ee9be  IN   0x8426d0dc03335d4a391bf4cf7fe546ff89549de40 Ether0.000143946
0xb14792b16fe5dabb37edd3bcb187c6c2b7c40379a6e6275c5ce96875ac2c63c6138 days 2 hrs ago0x59a9d61607c745d542fac9fc8371f3930ae46108  IN   0x8426d0dc03335d4a391bf4cf7fe546ff89549de40 Ether0.000148784
0xef6380f17b6ed299fac37c949039930cef5be7707e7e5abac86a7f2f6ccae5a6138 days 7 hrs ago0xa47202a61da5c6e061f094675d46d6bf59b1d75f  IN   0x8426d0dc03335d4a391bf4cf7fe546ff89549de40 Ether0.00023287
0x27bf0239976c16e125b63a08cd0ad953a7d85982e1241ceeab1f28833568f606138 days 7 hrs ago0xe2d1ec062201dd4b422b49c6638f9e169c227405  IN   0x8426d0dc03335d4a391bf4cf7fe546ff89549de40 Ether0.000156204
0x92ba9103da7f9921a0186498eb91726cff4aec1741e8eef374f77ff61dae1684138 days 11 hrs ago0x965433c4ccf2d4354082d3364913baa0a85e0305  IN   0x8426d0dc03335d4a391bf4cf7fe546ff89549de40 Ether0.000095964
[ Download CSV Export  ] 
 Internal Transactions as a result of Contract Execution
 Latest 1 Internal Transaction

ParentTxHash Block Age From To Value
0xf98121f0ad1a6c927d6bfff8e0557e69eb08a6f87a5e2e5db5288f200188dd075398615248 days 18 hrs ago0x4863e8c8bd928bd1cf85eea784736e35c2f48a6a  Contract Creation0 Ether
[ Download CSV Export  ] 
Contract Name: BlokToken
Compiler Text: v0.4.13+commit.fb4cb1a
Optimization Enabled: Yes
Runs (Optimiser):  200



  Contract Source Code   Find Similiar Contracts

pragma solidity ^0.4.13;

contract ERC20 {
    uint256 public totalSupply;
    function balanceOf(address _owner) constant returns (uint256 balance);
    function transfer(address _to, uint256 _value) returns (bool success);
    function transferFrom(address _from, address _to, uint256 _value) returns (bool success);
    function approve(address _spender, uint256 _value) returns (bool success);
    function allowance(address _owner, address _spender) constant returns (uint256 remaining);
    event Transfer(address indexed _from, address indexed _to, uint256 _value);
    event Approval(address indexed _owner, address indexed _spender, uint256 _value);
}

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/issues/20#issuecomment-263524729
        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 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 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) {
        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) {
        uint256 _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;
    }
}

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 The Ownable constructor sets the original `owner` of the contract to the sender
    /// account.
    function Ownable() {
        owner = msg.sender;
    }

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

        _;
    }

    modifier onlyOwnerCandidate() {
        if (msg.sender != newOwnerCandidate) {
            revert();
        }

        _;
    }

    /// @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 previously proposed owner.
    function acceptOwnership() external onlyOwnerCandidate {
        address previousOwner = owner;

        owner = newOwnerCandidate;
        newOwnerCandidate = address(0);

        OwnershipTransferred(previousOwner, owner);
    }
}

library SafeMath {
    function mul(uint256 a, uint256 b) internal returns (uint256) {
        uint256 c = a * b;
        assert(a == 0 || c / a == b);
        return c;
    }

    function div(uint256 a, uint256 b) internal 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 returns (uint256) {
        assert(b <= a);
        return a - b;
    }

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

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

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

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

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

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) onlyOwner returns (bool success) {
        return ERC20(_tokenAddress).transfer(owner, _amount);
    }
}

contract BlokToken is Ownable, BasicToken, TokenHolder {
    using SafeMath for uint256;

    string public constant name = "Blok";
    string public constant symbol = "BLO";

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

    // States whether creating more tokens is allowed or not.
    // Used during token sale.
    bool public isMinting = true;

    event MintingEnded();

    modifier onlyDuringMinting() {
        require(isMinting);

        _;
    }

    modifier onlyAfterMinting() {
        require(!isMinting);

        _;
    }

    /// @dev Mint Blok tokens.
    /// @param _to address Address to send minted Blok to.
    /// @param _amount uint256 Amount of Blok tokens to mint.
    function mint(address _to, uint256 _amount) external onlyOwner onlyDuringMinting {
        totalSupply = totalSupply.add(_amount);
        balances[_to] = balances[_to].add(_amount);

        Transfer(0x0, _to, _amount);
    }

    /// @dev End minting mode.
    function endMinting() external onlyOwner {
        if (isMinting == false) {
            return;
        }

        isMinting = false;

        MintingEnded();
    }

    /// @dev Same ERC20 behavior, but reverts if still minting.
    /// @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 onlyAfterMinting returns (bool) {
        return super.approve(_spender, _value);
    }

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

    /// @dev Same ERC20 behavior, but reverts if still minting.
    /// @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 onlyAfterMinting returns (bool) {
        return super.transferFrom(_from, _to, _value);
    }
}

contract BlokTokenSale is Ownable, TokenHolder {
    using SafeMath for uint256;

    // External parties:

    // BLO token contract.
    BlokToken public blok;

    // Vesting contract for pre-sale participants.
    VestingTrustee public trustee;

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

    // Blok token unit.
    // Using same decimal value as ETH (makes ETH-BLO conversion much easier).
    // This is the same as in Blok token contract.
    uint256 public constant TOKEN_UNIT = 10 ** 18;

    // Maximum number of tokens in circulation: 10 trillion.
    uint256 public constant MAX_TOKENS = 360000000 * TOKEN_UNIT;

    // Maximum tokens offered in the sale.
    uint256 public constant MAX_TOKENS_SOLD = 234000000 * TOKEN_UNIT;

    // BLO to 1 wei ratio.
    uint256 public constant BLO_PER_WEI = 5700;

    // Sale start and end timestamps.
    uint256 public constant SALE_DURATION = 30 days;
    uint256 public startTime;
    uint256 public endTime;

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

    // Participation caps, according to KYC tiers.
    uint256 public constant TIER_1_CAP = 20000 ether; // Maximum uint256 value

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

    // Maximum amount that each participant is allowed to contribute (in WEI).
    mapping (address => uint256) public participationCaps;

    // Maximum amount ANYBODY is currently allowed to contribute.
    uint256 public hardParticipationCap = uint256(-1);

    // Vesting information for special addresses:
    struct TokenGrant {
        uint256 value;
        uint256 startOffset;
        uint256 cliffOffset;
        uint256 endOffset;
        uint256 installmentLength;
        uint8 percentVested;
    }

    address[] public tokenGrantees;
    mapping (address => TokenGrant) public tokenGrants;
    uint256 public lastGrantedIndex = 0;
    uint256 public constant MAX_TOKEN_GRANTEES = 100;
    uint256 public constant GRANT_BATCH_SIZE = 10;

    address public constant RESERVE_TOKENS = 0xA67E1c56A5e0363B61a23670FFC0FcD8F09f178d;
    address public constant TEAM_WALLET = 0x52aA6A62404107742ac01Ff247ED47b49b16c40A;
    address public constant BOUNTY_WALLET = 0xCf1e64Ce2740A03192F1d7a3234AABd88c025c4B;    

    event TokensIssued(address indexed _to, uint256 _tokens);

    /// @dev Reverts if called when not during sale.
    modifier onlyDuringSale() {
        require(!saleEnded() && now >= startTime);

        _;
    }

    /// @dev Reverts if called before sale ends.
    modifier onlyAfterSale() {
        require(saleEnded());

        _;
    }

    /// @dev Constructor that initializes the sale conditions.
    /// @param _fundingRecipient address The address of the funding recipient.
    /// @param _startTime uint256 The start time of the token sale.
    function BlokTokenSale(address _fundingRecipient, uint256 _startTime) {
        require(_fundingRecipient != address(0));
        require(_startTime > now);

        // Deploy new BlokToken contract.
        blok = new BlokToken();

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

        fundingRecipient = _fundingRecipient;
        startTime = _startTime;
        endTime = startTime + SALE_DURATION;

        // Initialize special vesting grants.
        initTokenGrants();
    }

    /// @dev Initialize token grants.
    function initTokenGrants() private onlyOwner {
        tokenGrantees.push(RESERVE_TOKENS);
        tokenGrants[RESERVE_TOKENS] = TokenGrant(MAX_TOKENS.mul(18).div(100), 0, 0, 10 days, 1 days, 0);

        tokenGrantees.push(TEAM_WALLET);
        tokenGrants[TEAM_WALLET] = TokenGrant(MAX_TOKENS.mul(13).div(100), 0, 0, 10 days, 1 days, 0);

        tokenGrantees.push(BOUNTY_WALLET);
        tokenGrants[BOUNTY_WALLET] = TokenGrant(MAX_TOKENS.mul(4).div(100), 0, 0, 10 days, 1 days, 0);
    }

    /// @dev Adds a Blok token vesting grant.
    /// @param _grantee address The address of the token grantee. Can be granted only once.
    /// @param _value uint256 The value of the grant.
    function addTokenGrant(address _grantee, uint256 _value) external onlyOwner {
        require(_grantee != address(0));
        require(_value > 0);
        require(tokenGrantees.length + 1 <= MAX_TOKEN_GRANTEES);

        // Verify the grant doesn't already exist.
        require(tokenGrants[_grantee].value == 0);
        for (uint i = 0; i < tokenGrantees.length; i++) {
            require(tokenGrantees[i] != _grantee);
        }

        // Add grant and add to grantee list.
        tokenGrantees.push(_grantee);
        tokenGrants[_grantee] = TokenGrant(_value, 0, 1 years, 1 years, 1 days, 50);
    }

    /// @dev Deletes a Blok token grant.
    /// @param _grantee address The address of the token grantee.
    function deleteTokenGrant(address _grantee) external onlyOwner {
        require(_grantee != address(0));

        // Delete the grant from the keys array.
        for (uint i = 0; i < tokenGrantees.length; i++) {
            if (tokenGrantees[i] == _grantee) {
                delete tokenGrantees[i];

                break;
            }
        }

        // Delete the grant from the mapping.
        delete tokenGrants[_grantee];
    }

    /// @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).
    function setParticipationCap(address[] _participants, uint256 _cap) private onlyOwner {
        for (uint i = 0; i < _participants.length; i++) {
            participationCaps[_participants[i]] = _cap;
        }
    }

    /// @dev Add a list of participants to cap tier #1.
    /// @param _participants address[] The list of participant addresses.
    function setTier1Participants(address[] _participants) external onlyOwner {
        setParticipationCap(_participants, TIER_1_CAP);
    }

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

        hardParticipationCap = _cap;
    }

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

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

        // Enforce participation cap (in Wei received).
        uint256 weiAlreadyParticipated = participationHistory[msg.sender];
        uint256 participationCap = SafeMath.min256(TOKEN_UNIT.mul(15).add(participationCaps[msg.sender]), hardParticipationCap);
        uint256 cappedWeiReceived = SafeMath.min256(msg.value, participationCap.sub(weiAlreadyParticipated));
        require(cappedWeiReceived > 0);

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

        // Issue tokens and transfer to recipient.
        uint256 tokensLeftInSale = MAX_TOKENS_SOLD.sub(tokensSold);
        uint256 tokensToIssue = weiToParticipate.mul(BLO_PER_WEI);
        if (tokensLeftInSale.sub(tokensToIssue) < BLO_PER_WEI) {
            // If purchase would cause less than BLO_PER_WEI tokens left then nobody could ever buy them.
            // So, gift them to the last buyer.
            tokensToIssue = tokensLeftInSale;
        }
        tokensSold = tokensSold.add(tokensToIssue);
        issueTokens(_recipient, tokensToIssue);

        // 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, by stopping token minting.
    function finalize() external onlyAfterSale onlyOwner {
        if (!blok.isMinting()) {
            revert();
        }

        require(lastGrantedIndex == tokenGrantees.length);

        // Finish minting.
        blok.endMinting();
    }

    /// @dev Grants pre-configured token grants in batches. When the method is called, it'll resume from the last grant,
    /// from its previous run, and will finish either after granting GRANT_BATCH_SIZE grants or finishing the whole list
    /// of grants.
    function grantTokens() external onlyAfterSale onlyOwner {
        uint endIndex = SafeMath.min256(tokenGrantees.length, lastGrantedIndex + GRANT_BATCH_SIZE);
        for (uint i = lastGrantedIndex; i < endIndex; i++) {
            address grantee = tokenGrantees[i];

            // Calculate how many tokens have been granted, vested, and issued such that: granted = vested + issued.
            TokenGrant memory tokenGrant = tokenGrants[grantee];
            uint256 tokensGranted = tokenGrant.value;
            uint256 tokensVesting = tokensGranted.mul(tokenGrant.percentVested).div(100);
            uint256 tokensIssued = tokensGranted.sub(tokensVesting);

            // Transfer issued tokens that have yet to be transferred to grantee.
            if (tokensIssued > 0) {
                issueTokens(grantee, tokensIssued);
            }

            // Transfer vested tokens that have yet to be transferred to vesting trustee, and initialize grant.
            if (tokensVesting > 0) {
                issueTokens(trustee, tokensVesting);
                trustee.grant(grantee, tokensVesting, now.add(tokenGrant.startOffset), now.add(tokenGrant.cliffOffset),
                    now.add(tokenGrant.endOffset), tokenGrant.installmentLength, true);
            }

            lastGrantedIndex++;
        }
    }

    /// @dev Issues tokens for the recipient.
    /// @param _recipient address The address of the recipient.
    /// @param _tokens uint256 The amount of tokens to issue.
    function issueTokens(address _recipient, uint256 _tokens) private {
        // Request Blok token contract to mint the requested tokens for the buyer.
        blok.mint(_recipient, _tokens);

        TokensIssued(_recipient, _tokens);
    }

    /// @dev Returns whether the sale has ended.
    /// @return bool Whether the sale has ended or not.
    function saleEnded() private constant returns (bool) {
        return tokensSold >= MAX_TOKENS_SOLD || now >= endTime;
    }

    /// @dev Requests to transfer control of the Blok token contract to a new owner.
    /// @param _newOwnerCandidate address The address to transfer ownership to.
    ///
    /// NOTE:
    ///   1. The new owner will need to call Blok token 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 Blok token contract can issue new tokens.
    function requestBlokTokenOwnershipTransfer(address _newOwnerCandidate) external onlyOwner {
        blok.requestOwnershipTransfer(_newOwnerCandidate);
    }

    /// @dev Accepts new ownership on behalf of the Blok token contract.
    // This can be used by the sale contract itself to claim back ownership of the Blok token contract.
    function acceptBlokTokenOwnership() external onlyOwner {
        blok.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 VestingTrustee's acceptOwnership directly in order to accept the ownership.
    ///   2. Calling this method during the token sale will prevent the token sale from finalizaing, since only the owner
    ///      of the VestingTrustee contract can issue new token grants.
    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();
    }
}

contract VestingTrustee is Ownable {
    using SafeMath for uint256;

    // Blok token contract.
    BlokToken public blok;

    // 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 available for vesting.
    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);

    /// @dev Constructor that initializes the address of the Blok token contract.
    /// @param _blok BlokToken The address of the previously deployed Blok token contract.
    function VestingTrustee(BlokToken _blok) {
        require(_blok != address(0));

        blok = _blok;
    }

    /// @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.
    /// @param _cliff uint256 Duration of the cliff period (when the first installment is made).
    /// @param _end uint256 The end of the vesting period.
    /// @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)); // Don't allow holder to be this contract.
        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) <= blok.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, reduce the total amount available for vesting.
        totalVesting = totalVesting.add(_value);

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

    /// @dev Revoke the grant of tokens of a specifed address.
    /// @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);

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

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

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

        GrantRevoked(_holder, refund);
    }

    /// @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) external 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 a uint256 Representing the amount of vested tokens of a specific grant.
    function calculateVestedTokens(Grant _grant, uint256 _time) private constant 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 installments that have passed 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 their holder.
    /// @return a uint256 Representing the amount of vested tokens transferred to their holder.
    function unlockVestedTokens() external {
        Grant storage grant = grants[msg.sender];

        // Require that there will be funds left in grant to tranfser to holder.
        require(grant.value != 0);

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

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

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

        TokensUnlocked(msg.sender, transferable);
    }
}

    Contract ABI  
[{"constant":true,"inputs":[],"name":"name","outputs":[{"name":"","type":"string"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_newOwnerCandidate","type":"address"}],"name":"requestOwnershipTransfer","outputs":[],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_spender","type":"address"},{"name":"_value","type":"uint256"}],"name":"approve","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"totalSupply","outputs":[{"name":"","type":"uint256"}],"payable":false,"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,"type":"function"},{"constant":true,"inputs":[],"name":"isMinting","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"decimals","outputs":[{"name":"","type":"uint8"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_to","type":"address"},{"name":"_amount","type":"uint256"}],"name":"mint","outputs":[],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"_owner","type":"address"}],"name":"balanceOf","outputs":[{"name":"balance","type":"uint256"}],"payable":false,"type":"function"},{"constant":false,"inputs":[],"name":"acceptOwnership","outputs":[],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"owner","outputs":[{"name":"","type":"address"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"symbol","outputs":[{"name":"","type":"string"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_to","type":"address"},{"name":"_value","type":"uint256"}],"name":"transfer","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"newOwnerCandidate","outputs":[{"name":"","type":"address"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_tokenAddress","type":"address"},{"name":"_amount","type":"uint256"}],"name":"transferAnyERC20Token","outputs":[{"name":"success","type":"bool"}],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"_owner","type":"address"},{"name":"_spender","type":"address"}],"name":"allowance","outputs":[{"name":"remaining","type":"uint256"}],"payable":false,"type":"function"},{"constant":false,"inputs":[],"name":"endMinting","outputs":[],"payable":false,"type":"function"},{"anonymous":false,"inputs":[],"name":"MintingEnded","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"},{"anonymous":false,"inputs":[{"indexed":true,"name":"_by","type":"address"},{"indexed":true,"name":"_to","type":"address"}],"name":"OwnershipRequested","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"_from","type":"address"},{"indexed":true,"name":"_to","type":"address"}],"name":"OwnershipTransferred","type":"event"}]

  Contract Creation Code Switch To Opcodes View
60606040526006805460ff191660011790555b60018054600160a060020a03191633600160a060020a03161790555b5b610bd88061003e6000396000f300606060405236156100ee5763ffffffff7c010000000000000000000000000000000000000000000000000000000060003504166306fdde0381146100f35780630952c5041461017e578063095ea7b31461019f57806318160ddd146101d557806323b872dd146101fa5780632a8092df14610236578063313ce5671461025d57806340c10f191461028657806370a08231146102aa57806379ba5097146102db5780638da5cb5b146102f057806395d89b411461031f578063a9059cbb146103aa578063d091b550146103e0578063dc39d06d1461040f578063dd62ed3e14610445578063ef70aebf1461047c575b600080fd5b34156100fe57600080fd5b610106610491565b60405160208082528190810183818151815260200191508051906020019080838360005b838110156101435780820151818401525b60200161012a565b50505050905090810190601f1680156101705780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b341561018957600080fd5b61019d600160a060020a03600435166104c8565b005b34156101aa57600080fd5b6101c1600160a060020a036004351660243561055d565b604051901515815260200160405180910390f35b34156101e057600080fd5b6101e8610584565b60405190815260200160405180910390f35b341561020557600080fd5b6101c1600160a060020a036004358116906024351660443561058a565b604051901515815260200160405180910390f35b341561024157600080fd5b6101c16105b3565b604051901515815260200160405180910390f35b341561026857600080fd5b6102706105bc565b60405160ff909116815260200160405180910390f35b341561029157600080fd5b61019d600160a060020a03600435166024356105c1565b005b34156102b557600080fd5b6101e8600160a060020a0360043516610685565b60405190815260200160405180910390f35b34156102e657600080fd5b61019d6106a4565b005b34156102fb57600080fd5b610303610733565b604051600160a060020a03909116815260200160405180910390f35b341561032a57600080fd5b610106610742565b60405160208082528190810183818151815260200191508051906020019080838360005b838110156101435780820151818401525b60200161012a565b50505050905090810190601f1680156101705780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34156103b557600080fd5b6101c1600160a060020a0360043516602435610779565b604051901515815260200160405180910390f35b34156103eb57600080fd5b6103036107a0565b604051600160a060020a03909116815260200160405180910390f35b341561041a57600080fd5b6101c1600160a060020a03600435166024356107af565b604051901515815260200160405180910390f35b341561045057600080fd5b6101e8600160a060020a036004358116906024351661086d565b60405190815260200160405180910390f35b341561048757600080fd5b61019d61089a565b005b60408051908101604052600481527f426c6f6b00000000000000000000000000000000000000000000000000000000602082015281565b60015433600160a060020a039081169116146104e357600080fd5b600160a060020a03811615156104f857600080fd5b6002805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a0383811691909117918290559081169033167f13a4b3bc0d5234dd3d87c9f1557d8faefa37986da62c36ba49309e2fb2c9aec460405160405180910390a35b5b50565b60065460009060ff161561057057600080fd5b61057a8383610900565b90505b5b92915050565b60035481565b60065460009060ff161561059d57600080fd5b6105a88484846109a9565b90505b5b9392505050565b60065460ff1681565b601281565b60015433600160a060020a039081169116146105dc57600080fd5b60065460ff1615156105ed57600080fd5b600354610600908263ffffffff610abb16565b600355600160a060020a03821660009081526005602052604090205461062c908263ffffffff610abb16565b600160a060020a0383166000818152600560205260408082209390935590917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9084905190815260200160405180910390a35b5b5b5050565b600160a060020a0381166000908152600560205260409020545b919050565b60025460009033600160a060020a039081169116146106c257600080fd5b50600180546002805473ffffffffffffffffffffffffffffffffffffffff19808416600160a060020a03838116919091179586905591169091559081169116817f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35b5b50565b600154600160a060020a031681565b60408051908101604052600381527f424c4f0000000000000000000000000000000000000000000000000000000000602082015281565b60065460009060ff161561078c57600080fd5b61057a8383610ad5565b90505b5b92915050565b600254600160a060020a031681565b60015460009033600160a060020a039081169116146107cd57600080fd5b600154600160a060020a038085169163a9059cbb9116846000604051602001526040517c010000000000000000000000000000000000000000000000000000000063ffffffff8516028152600160a060020a0390921660048301526024820152604401602060405180830381600087803b151561084957600080fd5b6102c65a03f1151561085a57600080fd5b50505060405180519150505b5b92915050565b600160a060020a038083166000908152600460209081526040808320938516835292905220545b92915050565b60015433600160a060020a039081169116146108b557600080fd5b60065460ff1615156108c6576108fd565b6006805460ff191690557ff48339e4a272bd7aee715c343ca34ad137607f1df78cf8d7ba137228954d2d8560405160405180910390a15b5b565b600081158015906109355750600160a060020a0333811660009081526004602090815260408083209387168352929052205415155b1561093f57600080fd5b600160a060020a03338116600081815260046020908152604080832094881680845294909152908190208590557f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259085905190815260200160405180910390a35060015b92915050565b600160a060020a0380841660008181526004602090815260408083203390951683529381528382205492825260059052918220546109ed908463ffffffff610b9516565b600160a060020a038087166000908152600560205260408082209390935590861681522054610a22908463ffffffff610abb16565b600160a060020a038516600090815260056020526040902055610a4b818463ffffffff610b9516565b600160a060020a03808716600081815260046020908152604080832033861684529091529081902093909355908616917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9086905190815260200160405180910390a3600191505b509392505050565b600082820183811015610aca57fe5b8091505b5092915050565b600160a060020a033316600090815260056020526040812054610afe908363ffffffff610b9516565b600160a060020a033381166000908152600560205260408082209390935590851681522054610b33908363ffffffff610abb16565b600160a060020a0380851660008181526005602052604090819020939093559133909116907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9085905190815260200160405180910390a35060015b92915050565b600082821115610ba157fe5b508082035b929150505600a165627a7a72305820cd86ff87d6077ca6241da3f17159a15d5919070affb84aea252d7c8af6698ca20029

   Swarm Source:
bzzr://cd86ff87d6077ca6241da3f17159a15d5919070affb84aea252d7c8af6698ca2

 

View All
Block Age transaction Difficulty GasUsed Reward
View All
Block Age UncleNumber Difficulty GasUsed Reward
Make sure to use the "Vote Down" button for any spammy posts, and the "Vote Up" for interesting conversations.