Contract 0x54c548703c6f423cf7ed22806b608d332fcebb3b

 

You can refer this tutorial here on How to withdraw my STAR Token
TxHash Block Age From To Value [TxFee]
0xa1a86fe54127c710959a8ee092dc37dfcdb3a041438b0ee167f025f769f559706608825141 days 3 hrs ago0xbd9e303aa45557a25003781be50371568218a2cb IN  StarbaseWithdrawalContract0 Ether0.002700575
0x7ad4ef84eace21120f6b3c9c31a1a0fb1025802015863618fce1436d7bfac75c6117403222 days 12 hrs ago0xe0f015a9cd1f40728378fc4629964855df0b825f IN  StarbaseWithdrawalContract0 Ether0.004428943
0x41884fb227afe30383d6f8c77ebdd75288403aea697d43fd5f81491c14541d905652770302 days 13 hrs ago0x6578503aff55d5630d7a90adee497de0d4b96731 IN  StarbaseWithdrawalContract0 Ether0.001720688
0x4ecbdcf4828afb68a326d71355a4540fba2197e6338fd58dca44cbf4e7496b0d5513120327 days ago0x1b7dc8c29b9dbaf06f20bb29201f7d612dd1131c IN  StarbaseWithdrawalContract0 Ether0.000969814
0x428cac4855b0b34905ef42c5c5df14ed70b0fe10b63934d01481799ab7834b0a5498277329 days 13 hrs ago0x0d36476c8aa059a64b5854f03ce834e188d099b1 IN  StarbaseWithdrawalContract0 Ether0.000021063
0x6461ff1d1fa5435e2c4bcf2c13d989b7c4893dfa8097894befc7618673b89d1f5490903330 days 20 hrs ago0x1b7dc8c29b9dbaf06f20bb29201f7d612dd1131c IN  StarbaseWithdrawalContract0 Ether0.00059135
0xaafb41881466cac1f3123ba5d5ec00836d8e5cd5d1c44162c7499b9dddaec7775468791334 days 15 hrs ago0x434fd7c2496c6beedc3a8e438ad0dfe9e99b75bb IN  StarbaseWithdrawalContract0 Ether0.00006929727
0x24c2080bacb915147c51200d2cf72d8a11598f5dbc9f12ef40e10512a0796d6b5384675348 days 18 hrs ago0xfa6869162f9d4f90897231deb34b37df0ccabfb2 IN  StarbaseWithdrawalContract0 Ether0.000983202
0x55e6edcf73289ca93a53b081ce6eef4726518ee228b05ec9a5b016c188ecb96b5199847379 days 20 hrs ago0x97bfe40199d6ba4c8acd57795d3a7d624b9aa14d IN  StarbaseWithdrawalContract0 Ether0.010694277
0x65f3cbc89c4e1fea5af4f36f4df66c0421aba8b8d3b9a74ca0365af5083bf6e95134271391 days 25 mins ago0x61c01767fb484241e95d6435f242f9cf1246e5f2 IN  StarbaseWithdrawalContract0 Ether0.000044691
0xeddbcf49e7a106535c46336b9aa0759f76e821203bf08d5dd5a3236aa51422b05117731393 days 20 hrs ago0xc9ba1344ccdffcaab9c28375b82f7f2bee68fd5b IN  StarbaseWithdrawalContract0 Ether0.000089382
0xffe475db3ba9a1ef98821f2e88463595b9de464c08996c90fccd0fd16e10cba95078240400 days 11 hrs ago0xba032705ffb40dcbdca747424be71e5810d71475 IN  StarbaseWithdrawalContract0.1 Ether0.002106099956
0x65f2b42f35f5f3d8aae4245c8b96193db4b470bf459c247a69207692ec236b595069240401 days 23 hrs ago0x33581cee233088c0860d944e0cf1ceabb8261c2e IN  StarbaseWithdrawalContract0 Ether0.00558138
0x3fc1939cb39043397e6f09ea132b7f7cca9539c89de286cb027ea402d5961a545064330402 days 19 hrs ago0xbf11e7e1e5bb337912882ad61c7e0c0d4addbfec IN  StarbaseWithdrawalContract0 Ether0.004409263
0x34c3c806aaf48b8f9faac7f79b9b43b3aff50f4e15c581c54808381559ebb3a45061199403 days 7 hrs ago0x8b4c686a0dd0c03df359cff2dc719b6eb95e84ee IN  StarbaseWithdrawalContract0 Ether0.00059135
0xde87af5fd77b82e5f112dec61beda0478fcb2a5fc8ff91538280f72e941b27af5054392404 days 11 hrs ago0x41e69eeb7eccf642764060c732ec3dc1b9fb4c59 IN  StarbaseWithdrawalContract0 Ether0.00044691
0xe013c4c4acbd9b30d0b626107403be92515d1b4e781542af76d54b474a17ba2f5030516408 days 11 hrs ago0xcd8fa1e688f120ad84eb109cf5f6631d0140ea82 IN  StarbaseWithdrawalContract0 Ether0.002258403
0xcff25a51666c334d2c7207d62130e37d94decac3ab6af56443885693a37176a85011436411 days 17 hrs ago0xa07ac35fb6e95412552136bd3e0a62101e23654b IN  StarbaseWithdrawalContract0 Ether0.003619971
0x21424727491c165d1852ebe31d42e705b30211808de2e5349a9b30101b5776225005994412 days 15 hrs ago0xeefcd01087281d035ece6a3bc369eb3afafc4cec IN  StarbaseWithdrawalContract0 Ether0.00324069
0xa9ff4a2aab35da2f360d1598cf88c543e222d096ca2c1a928bd3c1e00cafcb414964069419 days 16 hrs ago0x401f1d1e091a6403b3c8932ad53b065f1c170dca IN  StarbaseWithdrawalContract0 Ether0.000860344
0xab07992a95cfc0409887fb3a2293aa99a1debefed47aadee1db81256c1cdcbe44953947421 days 9 hrs ago0xad00a8b2ba43d527e09f87a52907e3d01217101a IN  StarbaseWithdrawalContract0 Ether0.002258403
0xd278bb0c7d2241efb363e5930255ce512c71fd991881eb87520124599b298a334953877421 days 10 hrs ago0xb9594dce2cc567bfaf10345f04dac5e68f5339ab IN  StarbaseWithdrawalContract0 Ether0.002268483
0xc6479900c15717f5336f6f0441cdaaecccce3f25e196b1748fccc3fe655471564929713425 days 14 hrs ago0x6ab2b714a36939be78a6b0cb026ee0fb5f5bfef1 IN  StarbaseWithdrawalContract0 Ether0.004409263
0x7a2dbf788c6ccb047ae265a088fe4bac4c64fc2bd5f9f7cd5ba17afd9eedaaf04929473425 days 15 hrs ago0x6ab2b714a36939be78a6b0cb026ee0fb5f5bfef1 IN  StarbaseWithdrawalContract0 Ether0.00123
0xdaef1ad340bc4ba027d965a42b0a18881223e250f2cc0c4765f4419056f677d64926246426 days 5 hrs ago0x32c6220c6116e3666c220ffbcddd2e7ae8d78c2d IN  StarbaseWithdrawalContract0 Ether0.002258403
[ Download CSV Export 

Internal Transactions as a result of Contract Execution

Parent TxHash Block Age From To Value

Contract Source Code Verified (Exact Match)

Contract Name:
StarbaseCrowdsaleContractW

Compiler Version
v0.4.16+commit.d7661dd9

Optimization Enabled:
Yes

Runs (Optimizer):
200

Contract Source Code

pragma solidity ^0.4.13;

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

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

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

/**
 * @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() {
    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) onlyOwner public {
    require(newOwner != address(0));
    OwnershipTransferred(owner, newOwner);
    owner = newOwner;
  }

}

contract AbstractStarbaseToken {
    function isFundraiser(address fundraiserAddress) public returns (bool);
    function company() public returns (address);
    function allocateToCrowdsalePurchaser(address to, uint256 value) public returns (bool);
    function allocateToMarketingSupporter(address to, uint256 value) public returns (bool);
}


contract AbstractStarbaseCrowdsale {
    function startDate() constant returns (uint256) {}
    function endedAt() constant returns (uint256) {}
    function isEnded() constant returns (bool);
    function totalRaisedAmountInCny() constant returns (uint256);
    function numOfPurchasedTokensOnCsBy(address purchaser) constant returns (uint256);
    function numOfPurchasedTokensOnEpBy(address purchaser) constant returns (uint256);
}

/// @title EarlyPurchase contract - Keep track of purchased amount by Early Purchasers
/// @author Starbase PTE. LTD. - <[email protected]>
contract StarbaseEarlyPurchase {
    /*
     *  Constants
     */
    string public constant PURCHASE_AMOUNT_UNIT = 'CNY';    // Chinese Yuan
    string public constant PURCHASE_AMOUNT_RATE_REFERENCE = 'http://www.xe.com/currencytables/';
    uint256 public constant PURCHASE_AMOUNT_CAP = 9000000;

    /*
     *  Types
     */
    struct EarlyPurchase {
        address purchaser;
        uint256 amount;        // CNY based amount
        uint256 purchasedAt;   // timestamp
    }

    /*
     *  External contracts
     */
    AbstractStarbaseCrowdsale public starbaseCrowdsale;

    /*
     *  Storage
     */
    address public owner;
    EarlyPurchase[] public earlyPurchases;
    uint256 public earlyPurchaseClosedAt;

    /*
     *  Modifiers
     */
    modifier noEther() {
        require(msg.value == 0);
        _;
    }

    modifier onlyOwner() {
        require(msg.sender == owner);
        _;
    }

    modifier onlyBeforeCrowdsale() {
        assert(address(starbaseCrowdsale) == address(0) || starbaseCrowdsale.startDate() == 0);
        _;
    }

    modifier onlyEarlyPurchaseTerm() {
        assert(earlyPurchaseClosedAt <= 0);
        _;
    }

    /*
     *  Contract functions
     */

    /**
     * @dev Returns early purchased amount by purchaser's address
     * @param purchaser Purchaser address
     */
    function purchasedAmountBy(address purchaser)
        external
        constant
        noEther
        returns (uint256 amount)
    {
        for (uint256 i; i < earlyPurchases.length; i++) {
            if (earlyPurchases[i].purchaser == purchaser) {
                amount += earlyPurchases[i].amount;
            }
        }
    }

    /**
     * @dev Returns total amount of raised funds by Early Purchasers
     */
    function totalAmountOfEarlyPurchases()
        constant
        noEther
        public
        returns (uint256 totalAmount)
    {
        for (uint256 i; i < earlyPurchases.length; i++) {
            totalAmount += earlyPurchases[i].amount;
        }
    }

    /**
     * @dev Returns number of early purchases
     */
    function numberOfEarlyPurchases()
        external
        constant
        noEther
        returns (uint256)
    {
        return earlyPurchases.length;
    }

    /**
     * @dev Append an early purchase log
     * @param purchaser Purchaser address
     * @param amount Purchase amount
     * @param purchasedAt Timestamp of purchased date
     */
    function appendEarlyPurchase(address purchaser, uint256 amount, uint256 purchasedAt)
        external
        noEther
        onlyOwner
        onlyBeforeCrowdsale
        onlyEarlyPurchaseTerm
        returns (bool)
    {
        if (amount == 0 ||
            totalAmountOfEarlyPurchases() + amount > PURCHASE_AMOUNT_CAP)
        {
            return false;
        }

        assert(purchasedAt != 0 || purchasedAt <= now);

        earlyPurchases.push(EarlyPurchase(purchaser, amount, purchasedAt));
        return true;
    }

    /**
     * @dev Close early purchase term
     */
    function closeEarlyPurchase()
        external
        noEther
        onlyOwner
        returns (bool)
    {
        earlyPurchaseClosedAt = now;
    }

    /**
     * @dev Setup function sets external contract's address
     * @param starbaseCrowdsaleAddress Token address
     */
    function setup(address starbaseCrowdsaleAddress)
        external
        noEther
        onlyOwner
        returns (bool)
    {
        if (address(starbaseCrowdsale) == 0) {
            starbaseCrowdsale = AbstractStarbaseCrowdsale(starbaseCrowdsaleAddress);
            return true;
        }
        return false;
    }

    /**
     * @dev Contract constructor function
     */
    function StarbaseEarlyPurchase() noEther {
        owner = msg.sender;
    }
}

/// @title EarlyPurchaseAmendment contract - Amend early purchase records of the original contract
/// @author Starbase PTE. LTD. - <[email protected]>
contract StarbaseEarlyPurchaseAmendment {
    /*
     *  Events
     */
    event EarlyPurchaseInvalidated(uint256 epIdx);
    event EarlyPurchaseAmended(uint256 epIdx);

    /*
     *  External contracts
     */
    AbstractStarbaseCrowdsale public starbaseCrowdsale;
    StarbaseEarlyPurchase public starbaseEarlyPurchase;

    /*
     *  Storage
     */
    address public owner;
    uint256[] public invalidEarlyPurchaseIndexes;
    uint256[] public amendedEarlyPurchaseIndexes;
    mapping (uint256 => StarbaseEarlyPurchase.EarlyPurchase) public amendedEarlyPurchases;

    /*
     *  Modifiers
     */
    modifier noEther() {
        require(msg.value == 0);
        _;
    }

    modifier onlyOwner() {
        require(msg.sender == owner);
        _;
    }

    modifier onlyBeforeCrowdsale() {
        assert(address(starbaseCrowdsale) == address(0) || starbaseCrowdsale.startDate() == 0);
        _;
    }

    modifier onlyEarlyPurchasesLoaded() {
        assert(address(starbaseEarlyPurchase) != address(0));
        _;
    }

    /*
     *  Functions below are compatible with starbaseEarlyPurchase contract
     */

    /**
     * @dev Returns an early purchase record
     * @param earlyPurchaseIndex Index number of an early purchase
     */
    function earlyPurchases(uint256 earlyPurchaseIndex)
        external
        constant
        onlyEarlyPurchasesLoaded
        returns (address purchaser, uint256 amount, uint256 purchasedAt)
    {
        return starbaseEarlyPurchase.earlyPurchases(earlyPurchaseIndex);
    }

    /**
     * @dev Returns early purchased amount by purchaser's address
     * @param purchaser Purchaser address
     */
    function purchasedAmountBy(address purchaser)
        external
        constant
        noEther
        returns (uint256 amount)
    {
        StarbaseEarlyPurchase.EarlyPurchase[] memory normalizedEP =
            normalizedEarlyPurchases();
        for (uint256 i; i < normalizedEP.length; i++) {
            if (normalizedEP[i].purchaser == purchaser) {
                amount += normalizedEP[i].amount;
            }
        }
    }

    /**
     * @dev Returns total amount of raised funds by Early Purchasers
     */
    function totalAmountOfEarlyPurchases()
        constant
        noEther
        public
        returns (uint256 totalAmount)
    {
        StarbaseEarlyPurchase.EarlyPurchase[] memory normalizedEP =
            normalizedEarlyPurchases();
        for (uint256 i; i < normalizedEP.length; i++) {
            totalAmount += normalizedEP[i].amount;
        }
    }

    /**
     * @dev Returns number of early purchases
     */
    function numberOfEarlyPurchases()
        external
        constant
        noEther
        returns (uint256)
    {
        return normalizedEarlyPurchases().length;
    }

    /**
     * @dev Sets up function sets external contract's address
     * @param starbaseCrowdsaleAddress Token address
     */
    function setup(address starbaseCrowdsaleAddress)
        external
        noEther
        onlyOwner
        returns (bool)
    {
        if (address(starbaseCrowdsale) == 0) {
            starbaseCrowdsale = AbstractStarbaseCrowdsale(starbaseCrowdsaleAddress);
            return true;
        }
        return false;
    }

    /*
     *  Contract functions unique to StarbaseEarlyPurchaseAmendment
     */

     /**
      * @dev Invalidate early purchase
      * @param earlyPurchaseIndex Index number of the purchase
      */
    function invalidateEarlyPurchase(uint256 earlyPurchaseIndex)
        external
        noEther
        onlyOwner
        onlyEarlyPurchasesLoaded
        onlyBeforeCrowdsale
        returns (bool)
    {
        assert(numberOfRawEarlyPurchases() > earlyPurchaseIndex); // Array Index Out of Bounds Exception

        for (uint256 i; i < invalidEarlyPurchaseIndexes.length; i++) {
            assert(invalidEarlyPurchaseIndexes[i] != earlyPurchaseIndex);
        }

        invalidEarlyPurchaseIndexes.push(earlyPurchaseIndex);
        EarlyPurchaseInvalidated(earlyPurchaseIndex);
        return true;
    }

    /**
     * @dev Checks whether early purchase is invalid
     * @param earlyPurchaseIndex Index number of the purchase
     */
    function isInvalidEarlyPurchase(uint256 earlyPurchaseIndex)
        constant
        noEther
        public
        returns (bool)
    {
        assert(numberOfRawEarlyPurchases() > earlyPurchaseIndex); // Array Index Out of Bounds Exception


        for (uint256 i; i < invalidEarlyPurchaseIndexes.length; i++) {
            if (invalidEarlyPurchaseIndexes[i] == earlyPurchaseIndex) {
                return true;
            }
        }
        return false;
    }

    /**
     * @dev Amends a given early purchase with data
     * @param earlyPurchaseIndex Index number of the purchase
     * @param purchaser Purchaser's address
     * @param amount Value of purchase
     * @param purchasedAt Purchase timestamp
     */
    function amendEarlyPurchase(uint256 earlyPurchaseIndex, address purchaser, uint256 amount, uint256 purchasedAt)
        external
        noEther
        onlyOwner
        onlyEarlyPurchasesLoaded
        onlyBeforeCrowdsale
        returns (bool)
    {
        assert(purchasedAt != 0 || purchasedAt <= now);

        assert(numberOfRawEarlyPurchases() > earlyPurchaseIndex);

        assert(!isInvalidEarlyPurchase(earlyPurchaseIndex)); // Invalid early purchase cannot be amended

        if (!isAmendedEarlyPurchase(earlyPurchaseIndex)) {
            amendedEarlyPurchaseIndexes.push(earlyPurchaseIndex);
        }

        amendedEarlyPurchases[earlyPurchaseIndex] =
            StarbaseEarlyPurchase.EarlyPurchase(purchaser, amount, purchasedAt);
        EarlyPurchaseAmended(earlyPurchaseIndex);
        return true;
    }

    /**
     * @dev Checks whether early purchase is amended
     * @param earlyPurchaseIndex Index number of the purchase
     */
    function isAmendedEarlyPurchase(uint256 earlyPurchaseIndex)
        constant
        noEther
        returns (bool)
    {
        assert(numberOfRawEarlyPurchases() > earlyPurchaseIndex); // Array Index Out of Bounds Exception

        for (uint256 i; i < amendedEarlyPurchaseIndexes.length; i++) {
            if (amendedEarlyPurchaseIndexes[i] == earlyPurchaseIndex) {
                return true;
            }
        }
        return false;
    }

    /**
     * @dev Loads early purchases data to StarbaseEarlyPurchaseAmendment contract
     * @param starbaseEarlyPurchaseAddress Address from starbase early purchase
     */
    function loadStarbaseEarlyPurchases(address starbaseEarlyPurchaseAddress)
        external
        noEther
        onlyOwner
        onlyBeforeCrowdsale
        returns (bool)
    {
        assert(starbaseEarlyPurchaseAddress != 0 ||
            address(starbaseEarlyPurchase) == 0);

        starbaseEarlyPurchase = StarbaseEarlyPurchase(starbaseEarlyPurchaseAddress);
        assert(starbaseEarlyPurchase.earlyPurchaseClosedAt() != 0); // the early purchase must be closed

        return true;
    }

    /**
     * @dev Contract constructor function. It sets owner
     */
    function StarbaseEarlyPurchaseAmendment() noEther {
        owner = msg.sender;
    }

    /**
     * Internal functions
     */

    /**
     * @dev Normalizes early purchases data
     */
    function normalizedEarlyPurchases()
        constant
        internal
        returns (StarbaseEarlyPurchase.EarlyPurchase[] normalizedEP)
    {
        uint256 rawEPCount = numberOfRawEarlyPurchases();
        normalizedEP = new StarbaseEarlyPurchase.EarlyPurchase[](
            rawEPCount - invalidEarlyPurchaseIndexes.length);

        uint256 normalizedIdx;
        for (uint256 i; i < rawEPCount; i++) {
            if (isInvalidEarlyPurchase(i)) {
                continue;   // invalid early purchase should be ignored
            }

            StarbaseEarlyPurchase.EarlyPurchase memory ep;
            if (isAmendedEarlyPurchase(i)) {
                ep = amendedEarlyPurchases[i];  // amended early purchase should take a priority
            } else {
                ep = getEarlyPurchase(i);
            }

            normalizedEP[normalizedIdx] = ep;
            normalizedIdx++;
        }
    }

    /**
     * @dev Fetches early purchases data
     */
    function getEarlyPurchase(uint256 earlyPurchaseIndex)
        internal
        constant
        onlyEarlyPurchasesLoaded
        returns (StarbaseEarlyPurchase.EarlyPurchase)
    {
        var (purchaser, amount, purchasedAt) =
            starbaseEarlyPurchase.earlyPurchases(earlyPurchaseIndex);
        return StarbaseEarlyPurchase.EarlyPurchase(purchaser, amount, purchasedAt);
    }

    /**
     * @dev Returns raw number of early purchases
     */
    function numberOfRawEarlyPurchases()
        internal
        constant
        onlyEarlyPurchasesLoaded
        returns (uint256)
    {
        return starbaseEarlyPurchase.numberOfEarlyPurchases();
    }
}


contract Certifier {
	event Confirmed(address indexed who);
	event Revoked(address indexed who);
	function certified(address) public constant returns (bool);
	function get(address, string) public constant returns (bytes32);
	function getAddress(address, string) public constant returns (address);
	function getUint(address, string) public constant returns (uint);
}

/**
 * @title Crowdsale contract - Starbase crowdsale to create STAR.
 * @author Starbase PTE. LTD. - <[email protected]>
 */
contract StarbaseCrowdsale is Ownable {
    using SafeMath for uint256;
    /*
     *  Events
     */
    event CrowdsaleEnded(uint256 endedAt);
    event StarbasePurchasedWithEth(address purchaser, uint256 amount, uint256 rawAmount, uint256 cnyEthRate);
    event CnyEthRateUpdated(uint256 cnyEthRate);
    event CnyBtcRateUpdated(uint256 cnyBtcRate);
    event QualifiedPartnerAddress(address qualifiedPartner);

    /**
     *  External contracts
     */
    AbstractStarbaseToken public starbaseToken;
    StarbaseEarlyPurchaseAmendment public starbaseEpAmendment;
    Certifier public picopsCertifier;

    /**
     *  Constants
     */
    uint256 constant public crowdsaleTokenAmount = 125000000e18;
    uint256 constant public earlyPurchaseTokenAmount = 50000000e18;
    uint256 constant public MIN_INVESTMENT = 1; // min is 1 Wei
    uint256 constant public MAX_CAP = 67000000; // in CNY. approximately 10M USD. (includes raised amount from both EP and CS)
    string public constant PURCHASE_AMOUNT_UNIT = 'CNY';  // Chinese Yuan

    /**
     * Types
     */
    struct CrowdsalePurchase {
        address purchaser;
        uint256 amount;        // CNY based amount with bonus
        uint256 rawAmount;     // CNY based amount no bonus
        uint256 purchasedAt;   // timestamp
    }

    struct QualifiedPartners {
        uint256 amountCap;
        uint256 amountRaised;
        bool    bonaFide;
        uint256 commissionFeePercentage; // example 5 will calculate the percentage as 5%
    }

    /*
     *  Enums
     */
    enum BonusMilestones {
        First,
        Second,
        Third,
        Fourth,
        Fifth
    }

    // Initialize bonusMilestones
    BonusMilestones public bonusMilestones = BonusMilestones.First;

    /**
     *  Storage
     */
    uint public numOfDeliveredCrowdsalePurchases;  // index to keep the number of crowdsale purchases have already been processed by `withdrawPurchasedTokens`
    uint public numOfDeliveredEarlyPurchases;  // index to keep the number of early purchases have already been processed by `withdrawPurchasedTokens`
    uint256 public numOfLoadedEarlyPurchases; // index to keep the number of early purchases that have already been loaded by `loadEarlyPurchases`

    // early purchase
    address[] public earlyPurchasers;
    mapping (address => uint256) public earlyPurchasedAmountBy; // early purchased amount in CNY per purchasers' address
    bool public earlyPurchasesLoaded = false;  // returns whether all early purchases are loaded into this contract
    uint256 public totalAmountOfEarlyPurchases; // including 20% bonus

    // crowdsale
    bool public presalePurchasesLoaded = false; // returns whether all presale purchases are loaded into this contract
    uint256 public maxCrowdsaleCap;     // = 67M CNY - (total raised amount from EP)
    uint256 public totalAmountOfCrowdsalePurchases; // in CNY, including bonuses
    uint256 public totalAmountOfCrowdsalePurchasesWithoutBonus; // in CNY
    mapping (address => QualifiedPartners) public qualifiedPartners;
    uint256 public purchaseStartBlock;  // crowdsale purchases can be accepted from this block number
    uint256 public startDate;
    uint256 public endedAt;
    CrowdsalePurchase[] public crowdsalePurchases;
    mapping (address => uint256) public crowdsalePurchaseAmountBy; // crowdsale purchase amount in CNY per purchasers' address
    uint256 public cnyBtcRate; // this rate won't be used from a smart contract function but external system
    uint256 public cnyEthRate;

    // bonus milestones
    uint256 public firstBonusEnds;
    uint256 public secondBonusEnds;
    uint256 public thirdBonusEnds;
    uint256 public fourthBonusEnds;

    // after the crowdsale
    mapping (address => uint256) public numOfPurchasedTokensOnCsBy;    // the number of tokens purchased on the crowdsale by a purchaser
    mapping (address => uint256) public numOfPurchasedTokensOnEpBy;    // the number of tokens early purchased by a purchaser

    /**
     *  Modifiers
     */
    modifier minInvestment() {
        // User has to send at least the ether value of one token.
        assert(msg.value >= MIN_INVESTMENT);
        _;
    }

    modifier whenNotStarted() {
        assert(startDate == 0);
        _;
    }

    modifier whenEnded() {
        assert(isEnded());
        _;
    }

    modifier hasBalance() {
        assert(this.balance > 0);
        _;
    }
    modifier rateIsSet(uint256 _rate) {
        assert(_rate != 0);
        _;
    }

    modifier whenNotEnded() {
        assert(!isEnded());
        _;
    }

    modifier tokensNotDelivered() {
        assert(numOfDeliveredCrowdsalePurchases == 0);
        assert(numOfDeliveredEarlyPurchases == 0);
        _;
    }

    modifier onlyFundraiser() {
        assert(address(starbaseToken) != 0);
        assert(starbaseToken.isFundraiser(msg.sender));
        _;
    }

    modifier onlyQualifiedPartner() {
        assert(qualifiedPartners[msg.sender].bonaFide);
        _;
    }

    modifier onlyQualifiedPartnerORPicopsCertified() {
        assert(qualifiedPartners[msg.sender].bonaFide || picopsCertifier.certified(msg.sender));
        _;
    }

    /**
     * Contract functions
     */
    /**
     * @dev Contract constructor function sets owner address and
     *      address of StarbaseEarlyPurchaseAmendment contract.
     * @param starbaseEpAddr The address that holds the early purchasers Star tokens
     * @param picopsCertifierAddr The address of the PICOPS certifier.
     *                            See also https://picops.parity.io/#/details
     */
    function StarbaseCrowdsale(address starbaseEpAddr, address picopsCertifierAddr) {
        require(starbaseEpAddr != 0 && picopsCertifierAddr != 0);
        owner = msg.sender;
        starbaseEpAmendment = StarbaseEarlyPurchaseAmendment(starbaseEpAddr);
        picopsCertifier = Certifier(picopsCertifierAddr);
    }

    /**
     * @dev Fallback accepts payment for Star tokens with Eth
     */
    function() payable {
        redirectToPurchase();
    }

    /**
     * External functions
     */

    /**
     * @dev Setup function sets external contracts' addresses and set the max crowdsale cap
     * @param starbaseTokenAddress Token address.
     * @param _purchaseStartBlock Block number to start crowdsale
     */
    function setup(address starbaseTokenAddress, uint256 _purchaseStartBlock)
        external
        onlyOwner
        returns (bool)
    {
        require(starbaseTokenAddress != address(0));
        require(address(starbaseToken) == 0);
        starbaseToken = AbstractStarbaseToken(starbaseTokenAddress);
        purchaseStartBlock = _purchaseStartBlock;

        // set the max cap of this crowdsale
        maxCrowdsaleCap = MAX_CAP.sub(totalAmountOfEarlyPurchasesWithoutBonus());

        assert(maxCrowdsaleCap > 0);

        return true;
    }

    /**
     * @dev Transfers raised funds to company's wallet address at any given time.
     */
    function withdrawForCompany()
        external
        onlyFundraiser
        hasBalance
    {
        address company = starbaseToken.company();
        require(company != address(0));
        company.transfer(this.balance);
    }

    /**
     * @dev Update start block Number for the crowdsale
     */
    function updatePurchaseStartBlock(uint256 _purchaseStartBlock)
        external
        whenNotStarted
        onlyFundraiser
        returns (bool)
    {
        purchaseStartBlock = _purchaseStartBlock;
        return true;
    }

    /**
     * @dev Update the CNY/ETH rate to record purchases in CNY
     */
    function updateCnyEthRate(uint256 rate)
        external
        onlyFundraiser
        returns (bool)
    {
        cnyEthRate = rate;
        CnyEthRateUpdated(cnyEthRate);
        return true;
    }

    /**
     * @dev Update the CNY/BTC rate to record purchases in CNY
     */
    function updateCnyBtcRate(uint256 rate)
        external
        onlyFundraiser
        returns (bool)
    {
        cnyBtcRate = rate;
        CnyBtcRateUpdated(cnyBtcRate);
        return true;
    }

    /**
     * @dev Allow for the possibility for contract owner to start crowdsale
     */
    function ownerStartsCrowdsale(uint256 timestamp)
        external
        whenNotStarted
        onlyOwner
    {
        assert(block.number >= purchaseStartBlock);   // this should be after the crowdsale start block
        startCrowdsale(timestamp);
    }

    /**
     * @dev Ends crowdsale
     *      This may be executed by an owner if the raised funds did not reach the map cap
     * @param timestamp Timestamp at the crowdsale ended
     */
    function endCrowdsale(uint256 timestamp)
        external
        onlyOwner
    {
        assert(timestamp > 0 && timestamp <= now);
        assert(block.number >= purchaseStartBlock && endedAt == 0);   // cannot end before it starts and overwriting time is not permitted
        endedAt = timestamp;
        CrowdsaleEnded(endedAt);
    }

    /**
     * @dev Ends crowdsale
     *      This may be executed by purchaseWithEth when the raised funds reach the map cap
     */
    function endCrowdsale() internal {
        assert(block.number >= purchaseStartBlock && endedAt == 0);
        endedAt = now;
        CrowdsaleEnded(endedAt);
    }

    /**
     * @dev Deliver tokens to purchasers according to their purchase amount in CNY
     */
    function withdrawPurchasedTokens()
        external
        whenEnded
        returns (bool)
    {
        assert(earlyPurchasesLoaded);
        assert(address(starbaseToken) != 0);

        /*
         * “Value” refers to the contribution of the User:
         *  {crowdsale_purchaser_token_amount} =
         *  {crowdsale_token_amount} * {crowdsalePurchase_value} / {earlypurchase_value} + {crowdsale_value}.
         *
         * Example: If a User contributes during the Contribution Period 100 CNY (including applicable
         * Bonus, if any) and the total amount early purchases amounts to 6’000’000 CNY
         * and total amount raised during the Contribution Period is 30’000’000, then he will get
         * 347.22 STAR = 125’000’000 STAR * 100 CNY / 30’000’000 CNY + 6’000’000 CNY.
        */

        if (crowdsalePurchaseAmountBy[msg.sender] > 0) {
            uint256 crowdsalePurchaseValue = crowdsalePurchaseAmountBy[msg.sender];
            crowdsalePurchaseAmountBy[msg.sender] = 0;

            uint256 tokenCount =
                SafeMath.mul(crowdsaleTokenAmount, crowdsalePurchaseValue) /
                totalRaisedAmountInCny();

            numOfPurchasedTokensOnCsBy[msg.sender] =
                SafeMath.add(numOfPurchasedTokensOnCsBy[msg.sender], tokenCount);
            assert(starbaseToken.allocateToCrowdsalePurchaser(msg.sender, tokenCount));
            numOfDeliveredCrowdsalePurchases++;
        }

        /*
         * “Value” refers to the contribution of the User:
         * {earlypurchaser_token_amount} =
         * {earlypurchaser_token_amount} * ({earlypurchase_value} / {total_earlypurchase_value})
         *  + {crowdsale_token_amount} * ({earlypurchase_value} / {earlypurchase_value} + {crowdsale_value}).
         *
         * Example: If an Early Purchaser contributes 100 CNY (including Bonus of 20%) and the
         * total amount of early purchases amounts to 6’000’000 CNY and the total amount raised
         * during the Contribution Period is 30’000’000 CNY, then he will get 1180.55 STAR =
         * 50’000’000 STAR * 100 CNY / 6’000’000 CNY + 125’000’000 STAR * 100 CNY /
         * 30’000’000 CNY + 6’000’000 CNY
         */

        if (earlyPurchasedAmountBy[msg.sender] > 0) {  // skip if is not an early purchaser
            uint256 earlyPurchaserPurchaseValue = earlyPurchasedAmountBy[msg.sender];
            earlyPurchasedAmountBy[msg.sender] = 0;

            uint256 epTokenCalculationFromEPTokenAmount = SafeMath.mul(earlyPurchaseTokenAmount, earlyPurchaserPurchaseValue) / totalAmountOfEarlyPurchases;

            uint256 epTokenCalculationFromCrowdsaleTokenAmount = SafeMath.mul(crowdsaleTokenAmount, earlyPurchaserPurchaseValue) / totalRaisedAmountInCny();

            uint256 epTokenCount = SafeMath.add(epTokenCalculationFromEPTokenAmount, epTokenCalculationFromCrowdsaleTokenAmount);

            numOfPurchasedTokensOnEpBy[msg.sender] = SafeMath.add(numOfPurchasedTokensOnEpBy[msg.sender], epTokenCount);
            assert(starbaseToken.allocateToCrowdsalePurchaser(msg.sender, epTokenCount));
            numOfDeliveredEarlyPurchases++;
        }

        return true;
    }

    /**
     * @dev Load early purchases from the contract keeps track of them
     */
    function loadEarlyPurchases() external onlyOwner returns (bool) {
        if (earlyPurchasesLoaded) {
            return false;    // all EPs have already been loaded
        }

        uint256 numOfOrigEp = starbaseEpAmendment
            .starbaseEarlyPurchase()
            .numberOfEarlyPurchases();

        for (uint256 i = numOfLoadedEarlyPurchases; i < numOfOrigEp && msg.gas > 200000; i++) {
            if (starbaseEpAmendment.isInvalidEarlyPurchase(i)) {
                numOfLoadedEarlyPurchases = SafeMath.add(numOfLoadedEarlyPurchases, 1);
                continue;
            }
            var (purchaser, amount,) =
                starbaseEpAmendment.isAmendedEarlyPurchase(i)
                ? starbaseEpAmendment.amendedEarlyPurchases(i)
                : starbaseEpAmendment.earlyPurchases(i);
            if (amount > 0) {
                if (earlyPurchasedAmountBy[purchaser] == 0) {
                    earlyPurchasers.push(purchaser);
                }
                // each early purchaser receives 20% bonus
                uint256 bonus = SafeMath.mul(amount, 20) / 100;
                uint256 amountWithBonus = SafeMath.add(amount, bonus);

                earlyPurchasedAmountBy[purchaser] = SafeMath.add(earlyPurchasedAmountBy[purchaser], amountWithBonus);
                totalAmountOfEarlyPurchases = totalAmountOfEarlyPurchases.add(amountWithBonus);
            }

            numOfLoadedEarlyPurchases = SafeMath.add(numOfLoadedEarlyPurchases, 1);
        }

        assert(numOfLoadedEarlyPurchases <= numOfOrigEp);
        if (numOfLoadedEarlyPurchases == numOfOrigEp) {
            earlyPurchasesLoaded = true;    // enable the flag
        }
        return true;
    }

    /**
     * @dev Load presale purchases from the contract keeps track of them
     * @param starbaseCrowdsalePresale Starbase presale contract address
     */
    function loadPresalePurchases(address starbaseCrowdsalePresale)
        external
        onlyOwner
        whenNotEnded
    {
        require(starbaseCrowdsalePresale != 0);
        require(!presalePurchasesLoaded);
        StarbaseCrowdsale presale = StarbaseCrowdsale(starbaseCrowdsalePresale);
        for (uint i; i < presale.numOfPurchases(); i++) {
            var (purchaser, amount, rawAmount, purchasedAt) =
                presale.crowdsalePurchases(i);  // presale purchase
            crowdsalePurchases.push(CrowdsalePurchase(purchaser, amount, rawAmount, purchasedAt));

            // Increase the sums
            crowdsalePurchaseAmountBy[purchaser] = SafeMath.add(crowdsalePurchaseAmountBy[purchaser], amount);
            totalAmountOfCrowdsalePurchases = totalAmountOfCrowdsalePurchases.add(amount);
            totalAmountOfCrowdsalePurchasesWithoutBonus = totalAmountOfCrowdsalePurchasesWithoutBonus.add(rawAmount);
        }
        presalePurchasesLoaded = true;
    }

    /**
      * @dev Set qualified crowdsale partner i.e. Bitcoin Suisse address
      * @param _qualifiedPartner Address of the qualified partner that can purchase during crowdsale
      * @param _amountCap Ether value which partner is able to contribute
      * @param _commissionFeePercentage Integer that represents the fee to pay qualified partner 5 is 5%
      */
    function setQualifiedPartner(address _qualifiedPartner, uint256 _amountCap, uint256 _commissionFeePercentage)
        external
        onlyOwner
    {
        assert(!qualifiedPartners[_qualifiedPartner].bonaFide);
        qualifiedPartners[_qualifiedPartner].bonaFide = true;
        qualifiedPartners[_qualifiedPartner].amountCap = _amountCap;
        qualifiedPartners[_qualifiedPartner].commissionFeePercentage = _commissionFeePercentage;
        QualifiedPartnerAddress(_qualifiedPartner);
    }

    /**
     * @dev Remove address from qualified partners list.
     * @param _qualifiedPartner Address to be removed from the list.
     */
    function unlistQualifiedPartner(address _qualifiedPartner) external onlyOwner {
        assert(qualifiedPartners[_qualifiedPartner].bonaFide);
        qualifiedPartners[_qualifiedPartner].bonaFide = false;
    }

    /**
     * @dev Update whitelisted address amount allowed to raise during the presale.
     * @param _qualifiedPartner Qualified Partner address to be updated.
     * @param _amountCap Amount that the address is able to raise during the presale.
     */
    function updateQualifiedPartnerCapAmount(address _qualifiedPartner, uint256 _amountCap) external onlyOwner {
        assert(qualifiedPartners[_qualifiedPartner].bonaFide);
        qualifiedPartners[_qualifiedPartner].amountCap = _amountCap;
    }

    /**
     * Public functions
     */

    /**
     * @dev Returns boolean for whether crowdsale has ended
     */
    function isEnded() constant public returns (bool) {
        return (endedAt > 0 && endedAt <= now);
    }

    /**
     * @dev Returns number of purchases to date.
     */
    function numOfPurchases() constant public returns (uint256) {
        return crowdsalePurchases.length;
    }

    /**
     * @dev Returns total raised amount in CNY (includes EP) and bonuses
     */
    function totalRaisedAmountInCny() constant public returns (uint256) {
        return totalAmountOfEarlyPurchases.add(totalAmountOfCrowdsalePurchases);
    }

    /**
     * @dev Returns total amount of early purchases in CNY and bonuses
     */
    function totalAmountOfEarlyPurchasesWithBonus() constant public returns(uint256) {
       return starbaseEpAmendment.totalAmountOfEarlyPurchases().mul(120).div(100);
    }

    /**
     * @dev Returns total amount of early purchases in CNY
     */
    function totalAmountOfEarlyPurchasesWithoutBonus() constant public returns(uint256) {
       return starbaseEpAmendment.totalAmountOfEarlyPurchases();
    }

    /**
     * @dev Allows qualified crowdsale partner to purchase Star Tokens
     */
    function purchaseAsQualifiedPartner()
        payable
        public
        rateIsSet(cnyEthRate)
        onlyQualifiedPartner
        returns (bool)
    {
        require(msg.value > 0);
        qualifiedPartners[msg.sender].amountRaised = SafeMath.add(msg.value, qualifiedPartners[msg.sender].amountRaised);

        assert(qualifiedPartners[msg.sender].amountRaised <= qualifiedPartners[msg.sender].amountCap);

        uint256 rawAmount = SafeMath.mul(msg.value, cnyEthRate) / 1e18;
        recordPurchase(msg.sender, rawAmount, now);

        if (qualifiedPartners[msg.sender].commissionFeePercentage > 0) {
            sendQualifiedPartnerCommissionFee(msg.sender, msg.value);
        }

        return true;
    }

    /**
     * @dev Allows user to purchase STAR tokens with Ether
     */
    function purchaseWithEth()
        payable
        public
        minInvestment
        whenNotEnded
        rateIsSet(cnyEthRate)
        onlyQualifiedPartnerORPicopsCertified
        returns (bool)
    {
        require(purchaseStartBlock > 0 && block.number >= purchaseStartBlock);

        if (startDate == 0) {
            startCrowdsale(block.timestamp);
        }

        uint256 rawAmount = SafeMath.mul(msg.value, cnyEthRate) / 1e18;
        recordPurchase(msg.sender, rawAmount, now);

        if (totalAmountOfCrowdsalePurchasesWithoutBonus >= maxCrowdsaleCap) {
            endCrowdsale(); // ends this crowdsale automatically
        }

        return true;
    }

    /**
     * Internal functions
     */

    /**
     * @dev Initializes Starbase crowdsale
     */
    function startCrowdsale(uint256 timestamp) internal {
        startDate = timestamp;
        uint256 presaleAmount = totalAmountOfCrowdsalePurchasesWithoutBonus;
        if (maxCrowdsaleCap > presaleAmount) {
            uint256 mainSaleCap = maxCrowdsaleCap.sub(presaleAmount);
            uint256 twentyPercentOfCrowdsalePurchase = mainSaleCap.mul(20).div(100);

            // set token bonus milestones in cny total crowdsale purchase
            firstBonusEnds =  twentyPercentOfCrowdsalePurchase;
            secondBonusEnds = firstBonusEnds.add(twentyPercentOfCrowdsalePurchase);
            thirdBonusEnds =  secondBonusEnds.add(twentyPercentOfCrowdsalePurchase);
            fourthBonusEnds = thirdBonusEnds.add(twentyPercentOfCrowdsalePurchase);
        }
    }

    /**
     * @dev Abstract record of a purchase to Tokens
     * @param purchaser Address of the buyer
     * @param rawAmount Amount in CNY as per the CNY/ETH rate used
     * @param timestamp Timestamp at the purchase made
     */
    function recordPurchase(
        address purchaser,
        uint256 rawAmount,
        uint256 timestamp
    )
        internal
        returns(uint256 amount)
    {
        amount = rawAmount; // amount to check reach of max cap. it does not care for bonus tokens here

        // presale transfers which occurs before the crowdsale ignores the crowdsale hard cap
        if (block.number >= purchaseStartBlock) {
            require(totalAmountOfCrowdsalePurchasesWithoutBonus < maxCrowdsaleCap);   // check if the amount has already reached the cap

            uint256 crowdsaleTotalAmountAfterPurchase =
                SafeMath.add(totalAmountOfCrowdsalePurchasesWithoutBonus, amount);

            // check whether purchase goes over the cap and send the difference back to the purchaser.
            if (crowdsaleTotalAmountAfterPurchase > maxCrowdsaleCap) {
              uint256 difference = SafeMath.sub(crowdsaleTotalAmountAfterPurchase, maxCrowdsaleCap);
              uint256 ethValueToReturn = SafeMath.mul(difference, 1e18) / cnyEthRate;
              purchaser.transfer(ethValueToReturn);
              amount = SafeMath.sub(amount, difference);
              rawAmount = amount;
            }
        }

        amount = getBonusAmountCalculation(amount); // at this point amount bonus is calculated

        CrowdsalePurchase memory purchase = CrowdsalePurchase(purchaser, amount, rawAmount, timestamp);
        crowdsalePurchases.push(purchase);
        StarbasePurchasedWithEth(msg.sender, amount, rawAmount, cnyEthRate);
        crowdsalePurchaseAmountBy[purchaser] = SafeMath.add(crowdsalePurchaseAmountBy[purchaser], amount);
        totalAmountOfCrowdsalePurchases = totalAmountOfCrowdsalePurchases.add(amount);
        totalAmountOfCrowdsalePurchasesWithoutBonus = totalAmountOfCrowdsalePurchasesWithoutBonus.add(rawAmount);
        return amount;
    }

    /**
     * @dev Calculates amount with bonus for bonus milestones
     */
    function calculateBonus
        (
            BonusMilestones nextMilestone,
            uint256 amount,
            uint256 bonusRange,
            uint256 bonusTier,
            uint256 results
        )
        internal
        returns (uint256 result, uint256 newAmount)
    {
        uint256 bonusCalc;

        if (amount <= bonusRange) {
            bonusCalc = amount.mul(bonusTier).div(100);

            if (amount.add(totalAmountOfCrowdsalePurchasesWithoutBonus) >= bonusRange)
                bonusMilestones = nextMilestone;

            result = results.add(amount).add(bonusCalc);
            newAmount = 0;

        } else {
            bonusCalc = bonusRange.mul(bonusTier).div(100);
            bonusMilestones = nextMilestone;
            result = results.add(bonusRange).add(bonusCalc);
            newAmount = amount.sub(bonusRange);
        }
    }

    /**
     * @dev Fetchs Bonus tier percentage per bonus milestones
     */
    function getBonusAmountCalculation(uint256 amount) internal returns (uint256) {
        if (block.number < purchaseStartBlock) {
            uint256 bonusFromAmount = amount.mul(30).div(100); // presale has 30% bonus
            return amount.add(bonusFromAmount);
        }

        // range of each bonus milestones
        uint256 firstBonusRange = firstBonusEnds;
        uint256 secondBonusRange = secondBonusEnds.sub(firstBonusEnds);
        uint256 thirdBonusRange = thirdBonusEnds.sub(secondBonusEnds);
        uint256 fourthBonusRange = fourthBonusEnds.sub(thirdBonusEnds);
        uint256 result;

        if (bonusMilestones == BonusMilestones.First)
            (result, amount) = calculateBonus(BonusMilestones.Second, amount, firstBonusRange, 20, result);

        if (bonusMilestones == BonusMilestones.Second)
            (result, amount) = calculateBonus(BonusMilestones.Third, amount, secondBonusRange, 15, result);

        if (bonusMilestones == BonusMilestones.Third)
            (result, amount) = calculateBonus(BonusMilestones.Fourth, amount, thirdBonusRange, 10, result);

        if (bonusMilestones == BonusMilestones.Fourth)
            (result, amount) = calculateBonus(BonusMilestones.Fifth, amount, fourthBonusRange, 5, result);

        return result.add(amount);
    }

    /**
     * @dev Fetchs Bonus tier percentage per bonus milestones
     * @dev qualifiedPartner Address of partners that participated in pre sale
     * @dev amountSent Value sent by qualified partner
     */
    function sendQualifiedPartnerCommissionFee(address qualifiedPartner, uint256 amountSent) internal {
        //calculate the commission fee to send to qualified partner
        uint256 commissionFeePercentageCalculationAmount = SafeMath.mul(amountSent, qualifiedPartners[qualifiedPartner].commissionFeePercentage) / 100;

        // send commission fee amount
        qualifiedPartner.transfer(commissionFeePercentageCalculationAmount);
    }

    /**
     * @dev redirectToPurchase Redirect to adequate purchase function within the smart contract
     */
    function redirectToPurchase() internal {
        if (block.number < purchaseStartBlock) {
            purchaseAsQualifiedPartner();
        } else {
            purchaseWithEth();
        }
    }
}

/**
 * @title Starbase Crowdsale Contract Withdrawal contract - Provides an function
          to withdraw STAR token according to crowdsale results
 * @author Starbase PTE. LTD. - <[email protected]>
 */
contract StarbaseCrowdsaleContractW is Ownable {
    using SafeMath for uint256;

    /*
     *  Events
     */
    event TokenWithdrawn(address purchaser, uint256 tokenCount);
    event CrowdsalePurchaseBonusLog(
        uint256 purchaseIdx, uint256 rawAmount, uint256 bonus);

    /**
     *  External contracts
     */
    AbstractStarbaseToken public starbaseToken;
    StarbaseCrowdsale public starbaseCrowdsale;
    StarbaseEarlyPurchaseAmendment public starbaseEpAmendment;

    /**
     *  Constants
     */
    uint256 constant public crowdsaleTokenAmount = 125000000e18;
    uint256 constant public earlyPurchaseTokenAmount = 50000000e18;

    /**
     *  Storage
     */

    // early purchase
    address[] public earlyPurchasers;
    mapping (address => uint256) public earlyPurchasedAmountBy; // early purchased amount in CNY per purchasers' address
    bool public earlyPurchasesLoaded = false;  // returns whether all early purchases are loaded into this contract
    uint256 public totalAmountOfEarlyPurchases; // including bonus
    uint public numOfDeliveredEarlyPurchases;  // index to keep the number of early purchases have already been processed by `withdrawPurchasedTokens`
    uint256 public numOfLoadedEarlyPurchases; // index to keep the number of early purchases that have already been loaded by `loadEarlyPurchases`

    // crowdsale
    uint256 public totalAmountOfCrowdsalePurchases; // in CNY, including bonuses
    uint256 public totalAmountOfCrowdsalePurchasesWithoutBonus; // in CNY
    uint256 public startDate;
    uint256 public endedAt;
    mapping (address => uint256) public crowdsalePurchaseAmountBy; // crowdsale purchase amount in CNY per purchasers' address
    uint public numOfDeliveredCrowdsalePurchases;  // index to keep the number of crowdsale purchases have already been processed by `withdrawPurchasedTokens`

    // crowdsale contract withdrawal
    bool public crowdsalePurchasesLoaded = false;   // returns whether all crowdsale purchases are loaded into this contract
    uint256 public numOfLoadedCrowdsalePurchases; // index to keep the number of crowdsale purchases that have already been loaded by `loadCrowdsalePurchases`
    uint256 public totalAmountOfPresalePurchasesWithoutBonus;  // in CNY

    // after the crowdsale
    mapping (address => bool) public tokenWithdrawn;    // returns whether purchased tokens were withdrawn by a purchaser
    mapping (address => uint256) public numOfPurchasedTokensOnCsBy;    // the number of tokens purchased on the crowdsale by a purchaser
    mapping (address => uint256) public numOfPurchasedTokensOnEpBy;    // the number of tokens early purchased by a purchaser

    /**
     *  Modifiers
     */
    modifier whenEnded() {
        assert(isEnded());
        _;
    }

    /**
     * Contract functions
     */

    /**
     * @dev Reject all incoming Ether transfers
     */
    function () { revert(); }

    /**
     * External functions
     */

    /**
     * @dev Setup function sets external contracts' address
     * @param starbaseTokenAddress Token address.
     * @param StarbaseCrowdsaleAddress Token address.
     */
    function setup(address starbaseTokenAddress, address StarbaseCrowdsaleAddress)
        external
        onlyOwner
    {
        require(starbaseTokenAddress != address(0) && StarbaseCrowdsaleAddress != address(0));
        require(address(starbaseToken) == 0 && address(starbaseCrowdsale) == 0);

        starbaseToken = AbstractStarbaseToken(starbaseTokenAddress);
        starbaseCrowdsale = StarbaseCrowdsale(StarbaseCrowdsaleAddress);
        starbaseEpAmendment = StarbaseEarlyPurchaseAmendment(starbaseCrowdsale.starbaseEpAmendment());

        require(starbaseCrowdsale.startDate() > 0);
        startDate = starbaseCrowdsale.startDate();

        require(starbaseCrowdsale.endedAt() > 0);
        endedAt = starbaseCrowdsale.endedAt();
    }

    /**
     * @dev Load crowdsale purchases from the contract keeps track of them
     * @param numOfPresalePurchases Number of presale purchase
     */
    function loadCrowdsalePurchases(uint256 numOfPresalePurchases)
        external
        onlyOwner
        whenEnded
    {
        require(!crowdsalePurchasesLoaded);

        uint256 numOfPurchases = starbaseCrowdsale.numOfPurchases();

        for (uint256 i = numOfLoadedCrowdsalePurchases; i < numOfPurchases && msg.gas > 200000; i++) {
            var (purchaser, amount, rawAmount,) =
                starbaseCrowdsale.crowdsalePurchases(i);

            uint256 bonus;
            if (i < numOfPresalePurchases) {
                bonus = rawAmount * 30 / 100;   // presale: 30% bonus
                totalAmountOfPresalePurchasesWithoutBonus =
                    totalAmountOfPresalePurchasesWithoutBonus.add(rawAmount);
            } else {
                bonus = calculateBonus(rawAmount); // mainsale: 20% ~ 0% bonus
            }

            // Update amount with bonus
            CrowdsalePurchaseBonusLog(i, rawAmount, bonus);
            amount = rawAmount + bonus;

            // Increase the sums
            crowdsalePurchaseAmountBy[purchaser] = SafeMath.add(crowdsalePurchaseAmountBy[purchaser], amount);
            totalAmountOfCrowdsalePurchases = totalAmountOfCrowdsalePurchases.add(amount);
            totalAmountOfCrowdsalePurchasesWithoutBonus = totalAmountOfCrowdsalePurchasesWithoutBonus.add(rawAmount);

            numOfLoadedCrowdsalePurchases++;    // Increase the index
        }

        assert(numOfLoadedCrowdsalePurchases <= numOfPurchases);
        if (numOfLoadedCrowdsalePurchases == numOfPurchases) {
            crowdsalePurchasesLoaded = true;    // enable the flag
        }
    }

    /**
     * @dev Add early purchases
     */
    function addEarlyPurchases() external onlyOwner returns (bool) {
        if (earlyPurchasesLoaded) {
            return false;    // all EPs have already been loaded
        }

        uint256 numOfOrigEp = starbaseEpAmendment
            .starbaseEarlyPurchase()
            .numberOfEarlyPurchases();

        for (uint256 i = numOfLoadedEarlyPurchases; i < numOfOrigEp && msg.gas > 200000; i++) {
            if (starbaseEpAmendment.isInvalidEarlyPurchase(i)) {
                numOfLoadedEarlyPurchases = SafeMath.add(numOfLoadedEarlyPurchases, 1);
                continue;
            }
            var (purchaser, amount,) =
                starbaseEpAmendment.isAmendedEarlyPurchase(i)
                ? starbaseEpAmendment.amendedEarlyPurchases(i)
                : starbaseEpAmendment.earlyPurchases(i);
            if (amount > 0) {
                if (earlyPurchasedAmountBy[purchaser] == 0) {
                    earlyPurchasers.push(purchaser);
                }
                // each early purchaser receives 10% bonus
                uint256 bonus = SafeMath.mul(amount, 10) / 100;
                uint256 amountWithBonus = SafeMath.add(amount, bonus);

                earlyPurchasedAmountBy[purchaser] = SafeMath.add(earlyPurchasedAmountBy[purchaser], amountWithBonus);
                totalAmountOfEarlyPurchases = totalAmountOfEarlyPurchases.add(amountWithBonus);
            }

            numOfLoadedEarlyPurchases = SafeMath.add(numOfLoadedEarlyPurchases, 1);
        }

        assert(numOfLoadedEarlyPurchases <= numOfOrigEp);
        if (numOfLoadedEarlyPurchases == numOfOrigEp) {
            earlyPurchasesLoaded = true;    // enable the flag
        }

        return true;
    }

    /**
     * @dev Deliver tokens to purchasers according to their purchase amount in CNY
     */
    function withdrawPurchasedTokens()
        external
        whenEnded
    {
        require(crowdsalePurchasesLoaded);
        assert(earlyPurchasesLoaded);
        assert(address(starbaseToken) != 0);

        // prevent double withdrawal
        require(!tokenWithdrawn[msg.sender]);
        tokenWithdrawn[msg.sender] = true;

        /*
         * “Value” refers to the contribution of the User:
         *  {crowdsale_purchaser_token_amount} =
         *  {crowdsale_token_amount} * {crowdsalePurchase_value} / {earlypurchase_value} + {crowdsale_value}.
         *
         * Example: If a User contributes during the Contribution Period 100 CNY (including applicable
         * Bonus, if any) and the total amount early purchases amounts to 6’000’000 CNY
         * and total amount raised during the Contribution Period is 30’000’000, then he will get
         * 347.22 STAR = 125’000’000 STAR * 100 CNY / 30’000’000 CNY + 6’000’000 CNY.
        */

        if (crowdsalePurchaseAmountBy[msg.sender] > 0) {
            uint256 crowdsalePurchaseValue = crowdsalePurchaseAmountBy[msg.sender];
            uint256 tokenCount =
                SafeMath.mul(crowdsaleTokenAmount, crowdsalePurchaseValue) /
                totalRaisedAmountInCny();

            numOfPurchasedTokensOnCsBy[msg.sender] =
                SafeMath.add(numOfPurchasedTokensOnCsBy[msg.sender], tokenCount);
            assert(starbaseToken.allocateToCrowdsalePurchaser(msg.sender, tokenCount));
            numOfDeliveredCrowdsalePurchases++;
            TokenWithdrawn(msg.sender, tokenCount);
        }

        /*
         * “Value” refers to the contribution of the User:
         * {earlypurchaser_token_amount} =
         * {earlypurchaser_token_amount} * ({earlypurchase_value} / {total_earlypurchase_value})
         *  + {crowdsale_token_amount} * ({earlypurchase_value} / {earlypurchase_value} + {crowdsale_value}).
         *
         * Example: If an Early Purchaser contributes 100 CNY (including Bonus) and the
         * total amount of early purchases amounts to 6’000’000 CNY and the total amount raised
         * during the Contribution Period is 30’000’000 CNY, then he will get 1180.55 STAR =
         * 50’000’000 STAR * 100 CNY / 6’000’000 CNY + 125’000’000 STAR * 100 CNY /
         * 30’000’000 CNY + 6’000’000 CNY
         */

        if (earlyPurchasedAmountBy[msg.sender] > 0) {  // skip if is not an early purchaser
            uint256 earlyPurchaserPurchaseValue = earlyPurchasedAmountBy[msg.sender];
            uint256 epTokenCalculationFromEPTokenAmount = SafeMath.mul(earlyPurchaseTokenAmount, earlyPurchaserPurchaseValue) / totalAmountOfEarlyPurchases;
            uint256 epTokenCalculationFromCrowdsaleTokenAmount = SafeMath.mul(crowdsaleTokenAmount, earlyPurchaserPurchaseValue) / totalRaisedAmountInCny();
            uint256 epTokenCount = SafeMath.add(epTokenCalculationFromEPTokenAmount, epTokenCalculationFromCrowdsaleTokenAmount);

            numOfPurchasedTokensOnEpBy[msg.sender] = SafeMath.add(numOfPurchasedTokensOnEpBy[msg.sender], epTokenCount);
            assert(starbaseToken.allocateToCrowdsalePurchaser(msg.sender, epTokenCount));
            numOfDeliveredEarlyPurchases++;
            TokenWithdrawn(msg.sender, epTokenCount);
        }
    }

    /**
     * Public functions
     */

    /**
     * @dev Returns boolean for whether crowdsale has ended
     */
    function isEnded() constant public returns (bool) {
        return (starbaseCrowdsale != address(0) && endedAt > 0);
    }

    /**
     * @dev Returns total raised amount in CNY (includes EP) and bonuses
     */
    function totalRaisedAmountInCny() constant public returns (uint256) {
        return totalAmountOfEarlyPurchases.add(totalAmountOfCrowdsalePurchases);
    }

    /**
     * Internal functions
     */

    /**
     * @dev Calculates bonus of a purchase
     */
    function calculateBonus(uint256 rawAmount)
        internal
        returns (uint256 bonus)
    {
        uint256 purchasedAmount =
            totalAmountOfCrowdsalePurchasesWithoutBonus
                .sub(totalAmountOfPresalePurchasesWithoutBonus);
        uint256 e1 = starbaseCrowdsale.firstBonusEnds();
        uint256 e2 = starbaseCrowdsale.secondBonusEnds();
        uint256 e3 = starbaseCrowdsale.thirdBonusEnds();
        uint256 e4 = starbaseCrowdsale.fourthBonusEnds();
        return calculateBonusInRange(purchasedAmount, rawAmount, 0, e1, 20)
            .add(calculateBonusInRange(purchasedAmount, rawAmount, e1, e2, 15))
            .add(calculateBonusInRange(purchasedAmount, rawAmount, e2, e3, 10))
            .add(calculateBonusInRange(purchasedAmount, rawAmount, e3, e4, 5));
    }

    function calculateBonusInRange(
        uint256 purchasedAmount,
        uint256 rawAmount,
        uint256 bonusBegin,
        uint256 bonusEnd,
        uint256 bonusTier
    )
        public
        constant
        returns (uint256 bonus)
    {
        uint256 sum = purchasedAmount + rawAmount;
        if (purchasedAmount > bonusEnd || sum < bonusBegin) {
            return 0;   // out of this range
        }

        uint256 min = purchasedAmount <= bonusBegin ? bonusBegin : purchasedAmount;
        uint256 max = bonusEnd <= sum ? bonusEnd : sum;
        return max.sub(min) * bonusTier / 100;
    }
}

Contract ABI

[{"constant":true,"inputs":[{"name":"","type":"address"}],"name":"earlyPurchasedAmountBy","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"startDate","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"crowdsaleTokenAmount","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"earlyPurchasesLoaded","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"starbaseTokenAddress","type":"address"},{"name":"StarbaseCrowdsaleAddress","type":"address"}],"name":"setup","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"endedAt","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"numOfLoadedCrowdsalePurchases","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"numOfLoadedEarlyPurchases","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"totalRaisedAmountInCny","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"}],"name":"numOfPurchasedTokensOnEpBy","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"earlyPurchaseTokenAmount","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"crowdsalePurchasesLoaded","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"starbaseEpAmendment","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"}],"name":"crowdsalePurchaseAmountBy","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"}],"name":"numOfPurchasedTokensOnCsBy","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"starbaseCrowdsale","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"owner","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"numOfDeliveredCrowdsalePurchases","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"numOfDeliveredEarlyPurchases","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"isEnded","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"uint256"}],"name":"earlyPurchasers","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"}],"name":"tokenWithdrawn","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"withdrawPurchasedTokens","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"totalAmountOfCrowdsalePurchases","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"starbaseToken","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"totalAmountOfEarlyPurchases","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"numOfPresalePurchases","type":"uint256"}],"name":"loadCrowdsalePurchases","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"purchasedAmount","type":"uint256"},{"name":"rawAmount","type":"uint256"},{"name":"bonusBegin","type":"uint256"},{"name":"bonusEnd","type":"uint256"},{"name":"bonusTier","type":"uint256"}],"name":"calculateBonusInRange","outputs":[{"name":"bonus","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"totalAmountOfCrowdsalePurchasesWithoutBonus","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"totalAmountOfPresalePurchasesWithoutBonus","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"},{"constant":false,"inputs":[],"name":"addEarlyPurchases","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"payable":false,"stateMutability":"nonpayable","type":"fallback"},{"anonymous":false,"inputs":[{"indexed":false,"name":"purchaser","type":"address"},{"indexed":false,"name":"tokenCount","type":"uint256"}],"name":"TokenWithdrawn","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"purchaseIdx","type":"uint256"},{"indexed":false,"name":"rawAmount","type":"uint256"},{"indexed":false,"name":"bonus","type":"uint256"}],"name":"CrowdsalePurchaseBonusLog","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"previousOwner","type":"address"},{"indexed":true,"name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"}]

Contract Creation Code

60606040526006805460ff199081169091556010805490911690555b60008054600160a060020a03191633600160a060020a03161790555b5b61195c806100476000396000f3006060604052361561017a5763ffffffff60e060020a6000350416630400228d811461018d5780630b97bc86146101be5780630dc5bffb146101e35780631ad66d21146102085780632d34ba791461022f5780633d6a71e4146102565780633dc9124e1461027b57806346e4d35d146102a057806348538112146102c55780634d730d51146102ea5780636bef2a941461031b5780636e96bbeb14610340578063715eddda146103675780637a095f9c146103965780637a960154146103c757806389ede784146103f85780638da5cb5b146104275780639e3d063614610456578063a1f8ea3b1461047b578063a4fd6f56146104a0578063a8f959b0146104c7578063b56f4ded146104f9578063becd70271461052c578063c0c4440a14610541578063c9b8020d14610566578063d7a14a0514610595578063db1e0eec146105ba578063dfdded04146105d2578063e156802414610606578063ed505d3e1461062b578063f2fde38b14610650578063feb4ad8914610671575b341561018557600080fd5b5b600080fd5b005b341561019857600080fd5b6101ac600160a060020a0360043516610698565b60405190815260200160405180910390f35b34156101c957600080fd5b6101ac6106aa565b60405190815260200160405180910390f35b34156101ee57600080fd5b6101ac6106b0565b60405190815260200160405180910390f35b341561021357600080fd5b61021b6106bf565b604051901515815260200160405180910390f35b341561023a57600080fd5b61018b600160a060020a03600435811690602435166106c8565b005b341561026157600080fd5b6101ac6109a2565b60405190815260200160405180910390f35b341561028657600080fd5b6101ac6109a8565b60405190815260200160405180910390f35b34156102ab57600080fd5b6101ac6109ae565b60405190815260200160405180910390f35b34156102d057600080fd5b6101ac6109b4565b60405190815260200160405180910390f35b34156102f557600080fd5b6101ac600160a060020a03600435166109d3565b60405190815260200160405180910390f35b341561032657600080fd5b6101ac6109e5565b60405190815260200160405180910390f35b341561034b57600080fd5b61021b6109f4565b604051901515815260200160405180910390f35b341561037257600080fd5b61037a6109fd565b604051600160a060020a03909116815260200160405180910390f35b34156103a157600080fd5b6101ac600160a060020a0360043516610a0c565b60405190815260200160405180910390f35b34156103d257600080fd5b6101ac600160a060020a0360043516610a1e565b60405190815260200160405180910390f35b341561040357600080fd5b61037a610a30565b604051600160a060020a03909116815260200160405180910390f35b341561043257600080fd5b61037a610a3f565b604051600160a060020a03909116815260200160405180910390f35b341561046157600080fd5b6101ac610a4e565b60405190815260200160405180910390f35b341561048657600080fd5b6101ac610a54565b60405190815260200160405180910390f35b34156104ab57600080fd5b61021b610a5a565b604051901515815260200160405180910390f35b34156104d257600080fd5b61037a600435610a7f565b604051600160a060020a03909116815260200160405180910390f35b341561050457600080fd5b61021b600160a060020a0360043516610ab1565b604051901515815260200160405180910390f35b341561053757600080fd5b61018b610ac6565b005b341561054c57600080fd5b6101ac610e65565b60405190815260200160405180910390f35b341561057157600080fd5b61037a610e6b565b604051600160a060020a03909116815260200160405180910390f35b34156105a057600080fd5b6101ac610e7a565b60405190815260200160405180910390f35b34156105c557600080fd5b61018b600435610e80565b005b34156105dd57600080fd5b6101ac600435602435604435606435608435611101565b60405190815260200160405180910390f35b341561061157600080fd5b6101ac611174565b60405190815260200160405180910390f35b341561063657600080fd5b6101ac61117a565b60405190815260200160405180910390f35b341561065b57600080fd5b61018b600160a060020a0360043516611180565b005b341561067c57600080fd5b61021b611219565b604051901515815260200160405180910390f35b60056020526000908152604090205481565b600c5481565b6a6765c793fa10079d00000081565b60065460ff1681565b60005433600160a060020a039081169116146106e357600080fd5b600160a060020a038216158015906107035750600160a060020a03811615155b151561070e57600080fd5b600154600160a060020a03161580156107305750600254600160a060020a0316155b151561073b57600080fd5b60018054600160a060020a0380851673ffffffffffffffffffffffffffffffffffffffff199283161790925560028054848416921691909117908190551663715eddda6000604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b15156107b557600080fd5b6102c65a03f115156107c657600080fd5b50505060405180516003805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a039283161790556002546000925016630b97bc8682604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b151561083a57600080fd5b6102c65a03f1151561084b57600080fd5b5050506040518051905011151561086157600080fd5b600254600160a060020a0316630b97bc866000604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b15156108a957600080fd5b6102c65a03f115156108ba57600080fd5b5050506040518051600c5550600254600090600160a060020a0316633d6a71e482604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b151561091057600080fd5b6102c65a03f1151561092157600080fd5b5050506040518051905011151561093757600080fd5b600254600160a060020a0316633d6a71e46000604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b151561097f57600080fd5b6102c65a03f1151561099057600080fd5b5050506040518051600d55505b5b5050565b600d5481565b60115481565b60095481565b60006109cd600a5460075461165890919063ffffffff16565b90505b90565b60156020526000908152604090205481565b6a295be96e6406697200000081565b60105460ff1681565b600354600160a060020a031681565b600e6020526000908152604090205481565b60146020526000908152604090205481565b600254600160a060020a031681565b600054600160a060020a031681565b600f5481565b60085481565b600254600090600160a060020a0316158015906109cd57506000600d54115b90505b90565b6004805482908110610a8d57fe5b906000526020600020900160005b915054906101000a9004600160a060020a031681565b60136020526000908152604090205460ff1681565b600080600080600080610ad7610a5a565b1515610adf57fe5b60105460ff161515610af057600080fd5b60065460ff161515610afe57fe5b600154600160a060020a03161515610b1257fe5b600160a060020a03331660009081526013602052604090205460ff1615610b3857600080fd5b600160a060020a0333166000908152601360209081526040808320805460ff19166001179055600e9091528120541115610cbc57600160a060020a0333166000908152600e60205260409020549550610b8f6109b4565b610ba46a6765c793fa10079d00000088611672565b811515610bad57fe5b600160a060020a0333166000908152601460205260409020549190049550610bd59086611658565b600160a060020a03338181166000908152601460205260408082209490945560015490921692630ef5a7e0928991516020015260405160e060020a63ffffffff8516028152600160a060020a0390921660048301526024820152604401602060405180830381600087803b1515610c4b57600080fd5b6102c65a03f11515610c5c57600080fd5b505050604051805190501515610c6e57fe5b600f805460010190557fa2bd9fcfcdba69f52bcd9a520846ad4bd685b187483f53efc42d035b2ddebff03386604051600160a060020a03909216825260208201526040908101905180910390a15b600160a060020a0333166000908152600560205260408120541115610e5b57600160a060020a033316600090815260056020526040902054600754909450610d0f6a295be96e6406697200000086611672565b811515610d1857fe5b049250610d236109b4565b610d386a6765c793fa10079d00000086611672565b811515610d4157fe5b049150610d4e8383611658565b600160a060020a033316600090815260156020526040902054909150610d749082611658565b600160a060020a03338181166000908152601560205260408082209490945560015490921692630ef5a7e0928591516020015260405160e060020a63ffffffff8516028152600160a060020a0390921660048301526024820152604401602060405180830381600087803b1515610dea57600080fd5b6102c65a03f11515610dfb57600080fd5b505050604051805190501515610e0d57fe5b6008805460010190557fa2bd9fcfcdba69f52bcd9a520846ad4bd685b187483f53efc42d035b2ddebff03382604051600160a060020a03909216825260208201526040908101905180910390a15b5b5b505050505050565b600a5481565b600154600160a060020a031681565b60075481565b600080548190819081908190819033600160a060020a03908116911614610ea657600080fd5b610eae610a5a565b1515610eb657fe5b60105460ff1615610ec657600080fd5b600254600160a060020a031663810405d66000604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b1515610f0e57600080fd5b6102c65a03f11515610f1f57600080fd5b50505060405180519050955060115494505b8585108015610f42575062030d405a115b156110d057600254600160a060020a0316639beceeca8660006040516080015260405160e060020a63ffffffff84160281526004810191909152602401608060405180830381600087803b1515610f9857600080fd5b6102c65a03f11515610fa957600080fd5b505050604051805190602001805190602001805190602001805190505093509350935086851015610ffb576064601e83025b049050610ff38260125461165890919063ffffffff16565b601255611007565b611004826116a1565b90505b7f6c33d023cecbdd7196dd93d7ec61a6abd788d04db1aaf47f40e1d0d95d5bd63d85838360405180848152602001838152602001828152602001935050505060405180910390a1600160a060020a0384166000908152600e602052604090205482820193506110769084611658565b600160a060020a0385166000908152600e6020526040902055600a546110a2908463ffffffff61165816565b600a55600b546110b8908363ffffffff61165816565b600b556011805460010190555b600190940193610f31565b601154869011156110dd57fe5b8560115414156110f5576010805460ff191660011790555b5b5b5b50505050505050565b600085850181808589118061111557508683105b156111235760009350611168565b868911156111315788611133565b865b9150828611156111435782611145565b855b905060648561115a838563ffffffff6118ce16565b0281151561116457fe5b0493505b50505095945050505050565b600b5481565b60125481565b60005433600160a060020a0390811691161461119b57600080fd5b600160a060020a03811615156111b057600080fd5b600054600160a060020a0380831691167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a36000805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a0383161790555b5b50565b6000805481908190819081908190819033600160a060020a0390811691161461124157600080fd5b60065460ff1615611255576000965061164e565b600354600160a060020a03166336cfe3eb6000604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b151561129d57600080fd5b6102c65a03f115156112ae57600080fd5b50505060405180519050600160a060020a0316633f5174df6000604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b15156112fd57600080fd5b6102c65a03f1151561130e57600080fd5b50505060405180519050955060095494505b8585108015611331575062030d405a115b1561162457600354600160a060020a0316635b9283e78660006040516020015260405160e060020a63ffffffff84160281526004810191909152602401602060405180830381600087803b151561138757600080fd5b6102c65a03f1151561139857600080fd5b50505060405180519050156113bc576113b46009546001611658565b600955611619565b600354600160a060020a0316631eafe00c8660006040516020015260405160e060020a63ffffffff84160281526004810191909152602401602060405180830381600087803b151561140d57600080fd5b6102c65a03f1151561141e57600080fd5b505050604051805190506114a957600354600160a060020a0316632288fad68660006040516060015260405160e060020a63ffffffff84160281526004810191909152602401606060405180830381600087803b151561147d57600080fd5b6102c65a03f1151561148e57600080fd5b50505060405180519060200180519060200180519050611522565b600354600160a060020a0316633f8af40c8660006040516060015260405160e060020a63ffffffff84160281526004810191909152602401606060405180830381600087803b15156114fa57600080fd5b6102c65a03f1151561150b57600080fd5b505050604051805190602001805190602001805190505b5093509350600083111561160857600160a060020a038416600090815260056020526040902054151561158f57600480546001810161156183826118e5565b916000526020600020900160005b8154600160a060020a038089166101009390930a92830292021916179055505b606461159c84600a611672565b8115156115a557fe5b0491506115b28383611658565b600160a060020a0385166000908152600560205260409020549091506115d89082611658565b600160a060020a038516600090815260056020526040902055600754611604908263ffffffff61165816565b6007555b6116156009546001611658565b6009555b600190940193611320565b6009548690111561163157fe5b856009541415611649576006805460ff191660011790555b600196505b5b50505050505090565b60008282018381101561166757fe5b8091505b5092915050565b600082820283158061168e575082848281151561168b57fe5b04145b151561166757fe5b8091505b5092915050565b6000806000806000806116c1601254600b546118ce90919063ffffffff16565b600254909550600160a060020a031663ae136d626000604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b151561170c57600080fd5b6102c65a03f1151561171d57600080fd5b5050506040518051600254909550600160a060020a03169050630ded7f626000604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b151561177257600080fd5b6102c65a03f1151561178357600080fd5b5050506040518051600254909450600160a060020a0316905063e035e1ac6000604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b15156117d857600080fd5b6102c65a03f115156117e957600080fd5b5050506040518051600254909350600160a060020a03169050633bfb3c356000604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b151561183e57600080fd5b6102c65a03f1151561184f57600080fd5b5050506040518051905090506118c161186c868985856005611101565b61189d61187d888b8888600a611101565b61189d61188e8a8d8b8b600f611101565b61189d8b8e60008d6014611101565b9063ffffffff61165816565b9063ffffffff61165816565b9063ffffffff61165816565b95505b5050505050919050565b6000828211156118da57fe5b508082035b92915050565b8154818355818115116119095760008381526020902061190991810190830161190f565b5b505050565b6109d091905b808211156119295760008155600101611915565b5090565b905600a165627a7a7230582094e83aef9d01f224bec13ad43d46b9beba6cc9b87b278970821cbc51e74e70ba0029

Swarm Source

bzzr://94e83aef9d01f224bec13ad43d46b9beba6cc9b87b278970821cbc51e74e70ba
Block Age Transaction Difficulty GasUsed Reward
Block Age Uncle Number Difficulty GasUsed Reward
Loading
Make sure to use the "Vote Down" button for any spammy posts, and the "Vote Up" for interesting conversations.