Fix comment.

Fix comment.

pragma solidity ^0.4.15;

import './SafeMath.sol';
import './Ownable.sol';
import './TokenHolder.sol';
import './KinToken.sol';
import './VestingTrustee.sol';

/// @title Kin token sale contract.
contract KinTokenSale is Ownable, TokenHolder {
    using SafeMath for uint256;

    // External parties:

    // KIN token contract.
    KinToken public kin;

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

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

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

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

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

    // Wei to 1 USD ratio.
    //
    // TODO update to the real ETH price before sale launch.
    uint256 public constant WEI_PER_USD = uint256(1 ether) / 360;

    // KIN to 1 USD ratio,
    // such MAX_TOKENS_SOLD * KIN_PER_USD is the $75M cap.
    uint256 public constant KIN_PER_USD = 6829 * TOKEN_UNIT;

    // KIN to 1 wei ratio.
    uint256 public constant KIN_PER_WEI = KIN_PER_USD / WEI_PER_USD;

    // Sale start and end timestamps.
    uint256 public constant SALE_DURATION = 14 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 = 100000 * WEI_PER_USD;
    uint256 public constant TIER_2_CAP = uint256(-1); // Maximum uint256 value

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

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

    // Maximum amount ANYBODY is currently allowed to contribute.
    uint256 public hardParticipationCap = 5000 * WEI_PER_USD;

    // 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;

    // Post-TDE multisig addresses.
    //
    // TODO: add real addresses here.
    address public constant KIN_FOUNDATION_ADDRESS = 0xa8F769B88d6D74FB2Bd3912F6793F75625228baF;
    address public constant KIK_ADDRESS = 0x7a029DC995f87B5cA060975b9A8A1b4bdB33cDC5;

    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 KinTokenSale(address _fundingRecipient, uint256 _startTime) {
        require(_fundingRecipient != address(0));
        require(_startTime > now);

        // Deploy new KinToken contract.
        kin = new KinToken();

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

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

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

    /// @dev Initialize token grants.
    ///
    /// TODO: add real values here.
    function initTokenGrants() private onlyOwner {
        // Issue the remaining 60% to Kin Foundation's multisig wallet. In a few days, after the token sale is
        // finalized, these tokens will be loaded into the KinVestingTrustee smart contract, according to the white
        // paper. Please note, that this is implied by setting a 0% vesting percent.
        tokenGrantees.push(KIN_FOUNDATION_ADDRESS);
        tokenGrants[KIN_FOUNDATION_ADDRESS] = TokenGrant(MAX_TOKENS.mul(60).div(100), 0, 0, 3 years, 1 days, 0);

        // Kik, 30%
        tokenGrantees.push(KIK_ADDRESS);
        tokenGrants[KIK_ADDRESS] = TokenGrant(MAX_TOKENS.mul(30).div(100), 0, 0, 120 weeks, 12 weeks, 100);
    }

    /// @dev Adds a Kin 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 Kin 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 Add a list of participants to tier #2.
    /// @param _participants address[] The list of participant addresses.
    function setTier2Participants(address[] _participants) external onlyOwner {
        setParticipationCap(_participants, TIER_2_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(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(KIN_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(KIN_PER_WEI);
        if (tokensLeftInSale.sub(tokensToIssue) < KIN_PER_WEI) {
            // If purchase would cause less than KIN_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 (!kin.isMinting()) {
            revert();
        }

        require(lastGrantedIndex == tokenGrantees.length);

        // Finish minting.
        kin.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.mul(tokensSold).div(MAX_TOKENS_SOLD);
            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 Kin token contract to mint the requested tokens for the buyer.
        kin.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 Kin token contract to a new owner.
    /// @param _newOwnerCandidate address The address to transfer ownership to.
    ///
    /// NOTE:
    ///   1. The new owner will need to call Kin 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 Kin token contract can issue new tokens.
    function requestKinTokenOwnershipTransfer(address _newOwnerCandidate) external onlyOwner {
        kin.requestOwnershipTransfer(_newOwnerCandidate);
    }

    /// @dev Accepts new ownership on behalf of the Kin token contract.
    // This can be used by the sale contract itself to claim back ownership of the Kin token contract.
    function acceptKinTokenOwnership() external onlyOwner {
        kin.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();
    }
}

pragma solidity ^0.4.15;

import './SafeMath.sol';
import './Ownable.sol';
import './TokenHolder.sol';
import './KinToken.sol';
import './VestingTrustee.sol';

/// @title Kin token sale contract.
contract KinTokenSale is Ownable, TokenHolder {
    using SafeMath for uint256;

    // External parties:

    // KIN token contract.
    KinToken public kin;

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

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

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

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

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

    // Wei to 1 USD ratio.
    //
    // TODO update to the real ETH price before sale launch.
    uint256 public constant WEI_PER_USD = uint256(1 ether) / 360;

    // KIN to 1 USD ratio,
    // such MAX_TOKENS_SOLD * KIN_PER_USD is the $75M cap.
    uint256 public constant KIN_PER_USD = 6829 * TOKEN_UNIT;

    // KIN to 1 wei ratio.
    uint256 public constant KIN_PER_WEI = KIN_PER_USD / WEI_PER_USD;

    // Sale start and end time.
    uint256 public constant SALE_DURATION = 14 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 = 100000 * WEI_PER_USD;
    uint256 public constant TIER_2_CAP = uint256(-1); // Maximum uint256 value

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

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

    // Maximum amount ANYBODY is currently allowed to contribute.
    uint256 public hardParticipationCap = 5000 * WEI_PER_USD;

    // 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;

    // Post-TDE multisig addresses.
    //
    // TODO: add real addresses here.
    address public constant KIN_FOUNDATION_ADDRESS = 0xa8F769B88d6D74FB2Bd3912F6793F75625228baF;
    address public constant KIK_ADDRESS = 0x7a029DC995f87B5cA060975b9A8A1b4bdB33cDC5;

    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 KinTokenSale(address _fundingRecipient, uint256 _startTime) {
        require(_fundingRecipient != address(0));
        require(_startTime > now);

        // Deploy new KinToken contract.
        kin = new KinToken();

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

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

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

    /// @dev Initialize token grants.
    ///
    /// TODO: add real values here.
    function initTokenGrants() private onlyOwner {
        // Issue the remaining 60% to Kin Foundation's multisig wallet. In a few days, after the token sale is
        // finalized, these tokens will be loaded into the KinVestingTrustee smart contract, according to the white
        // paper. Please note, that this is implied by setting a 0% vesting percent.
        tokenGrantees.push(KIN_FOUNDATION_ADDRESS);
        tokenGrants[KIN_FOUNDATION_ADDRESS] = TokenGrant(MAX_TOKENS.mul(60).div(100), 0, 0, 3 years, 1 days, 0);

        // Kik, 30%
        tokenGrantees.push(KIK_ADDRESS);
        tokenGrants[KIK_ADDRESS] = TokenGrant(MAX_TOKENS.mul(30).div(100), 0, 0, 120 weeks, 12 weeks, 100);
    }

    /// @dev Adds a Kin 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 Kin 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 Add a list of participants to tier #2.
    /// @param _participants address[] The list of participant addresses.
    function setTier2Participants(address[] _participants) external onlyOwner {
        setParticipationCap(_participants, TIER_2_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(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(KIN_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(KIN_PER_WEI);
        if (tokensLeftInSale.sub(tokensToIssue) < KIN_PER_WEI) {
            // If purchase would cause less than KIN_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 (!kin.isMinting()) {
            revert();
        }

        require(lastGrantedIndex == tokenGrantees.length);

        // Finish minting.
        kin.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.mul(tokensSold).div(MAX_TOKENS_SOLD);
            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 Kin token contract to mint the requested tokens for the buyer.
        kin.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 Kin token contract to a new owner.
    /// @param _newOwnerCandidate address The address to transfer ownership to.
    ///
    /// NOTE:
    ///   1. The new owner will need to call Kin 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 Kin token contract can issue new tokens.
    function requestKinTokenOwnershipTransfer(address _newOwnerCandidate) external onlyOwner {
        kin.requestOwnershipTransfer(_newOwnerCandidate);
    }

    /// @dev Accepts new ownership on behalf of the Kin token contract.
    // This can be used by the sale contract itself to claim back ownership of the Kin token contract.
    function acceptKinTokenOwnership() external onlyOwner {
        kin.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();
    }
}


MarketAgent bug fixes

MarketAgent bug fixes

import 'agent_storage.sol';
import 'spec_token.sol';
import 'market.sol';

contract MarketAgent is Mortal {
    HumanAgentStorage agentStorage;
    Market public market;
    Token public credits;

    Lot public lot;
    bool public lotIsSet = false;

    function MarketAgent(HumanAgentStorage _storage, Market _market, Token _credits) {
        agentStorage = _storage;
        market  = _market;
        credits = _credits;
    }

    /**
     * @dev Place lot on the market
     * @notice market agent can place only one lot, for more create more agents
     * @param _name traded item term name
     * @param _token traded token
     * @param _value how much items traded
     * @param _price one item price
     * @return placed lot address for tracking
     */
    function placeLot(string _name, SpecToken _token,
                      uint _value,  uint _price) onlyOwner returns (Lot) {
        // Only one lot can be placed
        if (lotIsSet) throw;

        // Check knowledge consistence
        var spec = agentStorage.getKnowledgeByName(_name);
        if (!spec.isEqual(_token.specification()))
            throw;

        // Check traded token balance
        if (_token.getBalance(msg.sender) < _value)
            throw;

        // Transfer traded token for self and approve credits
        _token.transferFrom(msg.sender, this, _value);
        credits.approve(msg.sender, _value * _price);

        lot = new Lot(_token, credits, _value, _price);
        market.appendLot(lot);

        lotIsSet = true;
        return lot;
    }

    /**
     * @dev Get market lot with traded item name
     * @param _index lot position
     * @return traded item description, lot address
     */
    function marketGet(uint _index) constant returns (Knowledge, Lot) {
        if (_index >= market.size()) throw;

        var lot = Lot(market.lots(_index));
        var saleToken = SpecToken(lot.sale());
        var saleSpec = saleToken.specification();

        for (uint i = 0; i < agentStorage.knowledgesLength(); i += 1) {
            var knowledge = agentStorage.getKnowledge(i);
            if (knowledge.isEqual(saleSpec))
                return (knowledge, lot);
        }
        return (Knowledge(0), lot);
    }
}

import 'agent_storage.sol';
import 'spec_token.sol';
import 'market.sol';

contract MarketAgent is Mortal {
    HumanAgentStorage agentStorage;
    Market public market;
    Token public credits;

    Lot public lot;
    bool public lotIsSet = false;

    function MarketAgent(HumanAgentStorage _storage, Market _market, Token _credits) {
        agentStorage = _storage;
        market  = _market;
        credits = _credits;
    }

    /**
     * @dev Place lot on the market
     * @notice market agent can place only one lot, for more create more agents
     * @param _name traded item term name
     * @param _token traded token
     * @param _value how much items traded
     * @param _price one item price
     * @return placed lot address for tracking
     */
    function placeLot(string _name, SpecToken _token,
                      uint _value,  uint _price) onlyOwner returns (Lot) {
        // Only one lot can be placed
        if (lotIsSet) throw;

        // Check knowledge consistence
        var spec = agentStorage.getKnowledgeByName(_name);
        if (!spec.isEqual(_token.specification()))
            return Lot(0);

        // Check traded token balance
        if (_token.getBalance(msg.sender) < _value)
            return Lot(0);

        // Transfer traded token for self and approve credits
        _token.transferFrom(msg.sender, this, _value);
        credits.approve(msg.sender, _value * _price);

        lot = new Lot(_token, credits, _value, _price);
        market.appendLot(lot);

        lotIsSet = true;
        return lot;
    }

    /**
     * @dev Take a best deal from market with knowledge term check
     * @param _name traded item term name
     * @param _token items for the search
     * @param _value how much items
     */
    function bestDeal(string _name, SpecToken _token, uint _value) constant
            returns (Lot) {
        // Check knowledge consistence
        var spec = agentStorage.getKnowledgeByName(_name);
        if (!spec.isEqual(_token.specification()))
            return Lot(0);

        // Search best deal on market
        return market.bestDeal(_token, credits, _value);
    }

    /**
     * @dev Get market lot with traded item name
     * @param _index lot position
     * @return traded item description, lot address
     */
    function marketGet(uint _index) returns (Knowledge, Lot) {
        if (_index >= market.size()) throw;

        var lot = Lot(market.lots(_index));
        var saleToken = SpecToken(lot.sale());
        var saleSpec = saleToken.specification();

        for (uint i = 0; i < agentStorage.knowledgesLength(); i += 1) {
            var knowledge = agentStorage.getKnowledge(i);
            if (knowledge.isEqual(saleSpec))
                return (knowledge, lot);
        }
        return (Knowledge(0), lot);
    }
}


to timestamp

to timestamp

pragma solidity ^0.4.11;

import './ethereum-api/oraclizeAPI.sol';
import './helpers.sol';

contract Bet is usingOraclize {
  enum BET_STATES {
    OPEN,
    TEAM_ONE_WON,
    TEAM_TWO_WON,
    DRAW,
    ORACLE_UNDECIDED
    }

  BET_STATES bet_state = BET_STATES.OPEN;
  address public resolver;
  bool public is_featured;
  string public title;
  string public description;
  string public category;
  string public team_0; // Team 0 identifier
  string public team_1; // Team 1 identifier
  uint public team_0_bet_sum;
  uint public team_1_bet_sum;
  mapping (address => uint) public bets_to_team_0;
  mapping (address => uint) public bets_to_team_1;

  uint public timestamp_match_begin;
  uint public timestamp_match_end;
  uint public timestamp_hard_deadline; // Hard deadline to end bet
  uint public timestamp_terminate_deadline; // Self-destruct deadline > hard_deadline (this must be big, so people can withdraw their funds)

  string url_oraclize;

  event new_betting(bool for_team, address from, uint amount);
  event new_winner_declared(BET_STATES winner);

  function Bet(address _resolver, string _title, string _category,
               string _team_0, string _team_1, uint _timestamp_match_begin,
               uint _timestamp_match_end, uint _timestamp_hard_deadline,
               uint _timestamp_terminate_deadline, string _url_oraclize) {
    resolver = _resolver;
    title = _title;
    category = _category;
    team_0 = _team_0;
    team_1 = _team_1;
    timestamp_match_begin = _timestamp_match_begin;
    timestamp_match_end = _timestamp_match_end;
    timestamp_terminate_deadline = _timestamp_terminate_deadline;
    url_oraclize = _url_oraclize;
  }

  function arbitrate(BET_STATES result) {
    require(block.timestamp >= timestamp_hard_deadline);
    require(bet_state == BET_STATES.ORACLE_UNDECIDED);
    require(result != BET_STATES.ORACLE_UNDECIDED);
    require(result != BET_STATES.OPEN);

    bet_state = result;
    new_winner_declared(result);
  }

  function __callback(bytes32 myid, string result) {
    // Cannot call after hard deadline
    require(block.timestamp < timestamp_hard_deadline);
    // Oraclize should call this
    require(msg.sender == oraclize_cbAddress());
    // Must be called after the bet ends
    require(block.timestamp >= timestamp_match_end);

    if (Helpers.string_equal(result, team_0))
      bet_state = BET_STATES.TEAM_ONE_WON;
    else if (Helpers.string_equal(result, team_1))
      bet_state = BET_STATES.TEAM_TWO_WON;
    else
      bet_state = BET_STATES.ORACLE_UNDECIDED;

    new_winner_declared(bet_state);
  }

  function update_result() payable {
    // Can call only when bet is open or undecided
    require(bet_state == BET_STATES.OPEN || bet_state == BET_STATES.ORACLE_UNDECIDED);
    require(block.timestamp >= timestamp_match_end);

    oraclize_query('URL', url_oraclize);
  }

  function toggle_featured() {
    require(msg.sender == resolver);
    is_featured = !is_featured;
  }

  //
  function bet(bool for_team) payable {
    require(block.timestamp < timestamp_match_begin);
    if (for_team)

    if (for_team) {
      // Cannot bet in two teams
      require(bets_to_team_1[msg.sender] == 0);
      team_0_bet_sum += msg.value;
      bets_to_team_0[msg.sender] += msg.value;
    }
    else {
      // Cannot bet in two teams
      require(bets_to_team_0[msg.sender] == 0);
      team_1_bet_sum += msg.value;
      bets_to_team_1[msg.sender] += msg.value;
    }

    new_betting(for_team, msg.sender, msg.value);
  }

  // Called by the user to collect his reward
  function collect_profit() {

  }

  // If the oracle fails or is not able to get the right answer
  function resolve_conflict(uint8 for_team_idx) {
    require(msg.sender == resolver);

  }
}

pragma solidity ^0.4.11;

import './ethereum-api/oraclizeAPI.sol';
import './helpers.sol';

contract Bet is usingOraclize {
  enum BET_STATES {
    OPEN,
    TEAM_ONE_WON,
    TEAM_TWO_WON,
    DRAW,
    ORACLE_UNDECIDED
    }

  BET_STATES bet_state = BET_STATES.OPEN;
  address public resolver;
  bool public is_featured;
  string public title;
  string public description;
  string public category;
  string public team_0; // Team 0 identifier
  string public team_1; // Team 1 identifier
  uint public team_0_bet_sum;
  uint public team_1_bet_sum;
  mapping (address => uint) public bets_to_team_0;
  mapping (address => uint) public bets_to_team_1;

  uint public timestamp_match_begin;
  uint public timestamp_match_end;
  uint public timestamp_hard_deadline; // Hard deadline to end bet
  uint public timestamp_terminate_deadline; // Self-destruct deadline > hard_deadline (this must be big, so people can withdraw their funds)

  string url_oraclize;

  event new_betting(bool for_team, address from, uint amount);
  event new_winner_declared(BET_STATES winner);

  function Bet(address _resolver, string _title, string _category,
               string _team_0, string _team_1, uint _block_match_begin,
               uint _block_match_end, uint _block_hard_deadline,
               uint _block_terminate_deadline, string _url_oraclize) {
    resolver = _resolver;
    title = _title;
    category = _category;
    team_0 = _team_0;
    team_1 = _team_1;
    block_match_begin = _block_match_begin;
    block_match_end = _block_match_end;
    block_terminate_deadline = _block_terminate_deadline;
    url_oraclize = _url_oraclize;
  }

  function arbitrate(BET_STATES result) {
    require(block.timestamp >= timestamp_hard_deadline);
    require(bet_state == BET_STATES.ORACLE_UNDECIDED);
    require(result != BET_STATES.ORACLE_UNDECIDED);
    require(result != BET_STATES.OPEN);

    bet_state = result;
    new_winner_declared(result);
  }

  function __callback(bytes32 myid, string result) {
    // Cannot call after hard deadline
    require(block.timestamp < timestamp_hard_deadline);
    // Oraclize should call this
    require(msg.sender == oraclize_cbAddress());
    // Must be called after the bet ends
    require(block.timestamp >= block_match_end);

    if (Helpers.string_equal(result, team_0))
      bet_state = BET_STATES.TEAM_ONE_WON;
    else if (Helpers.string_equal(result, team_1))
      bet_state = BET_STATES.TEAM_TWO_WON;
    else
      bet_state = BET_STATES.ORACLE_UNDECIDED;

    new_winner_declared(bet_state);
  }

  function update_result() payable {
    // Can call only when bet is open or undecided
    require(bet_state == BET_STATES.OPEN || bet_state == BET_STATES.ORACLE_UNDECIDED);
    require(block.timestamp >= timestamp_match_end);

    oraclize_query('URL', url_oraclize);
  }

  function toggle_featured() {
    require(msg.sender == resolver);
    is_featured = !is_featured;
  }

  //
  function bet(bool for_team) payable {
    require(block.timestamp < timestamp_match_begin);
    if (for_team)

    if (for_team) {
      // Cannot bet in two teams
      require(bets_to_team_1[msg.sender] == 0);
      team_0_bet_sum += msg.value;
      bets_to_team_0[msg.sender] += msg.value;
    }
    else {
      // Cannot bet in two teams
      require(bets_to_team_0[msg.sender] == 0);
      team_1_bet_sum += msg.value;
      bets_to_team_1[msg.sender] += msg.value;
    }

    new_betting(for_team, msg.sender, msg.value);
  }

  // Called by the user to collect his reward
  function collect_profit() {

  }

  // If the oracle fails or is not able to get the right answer
  function resolve_conflict(uint8 for_team_idx) {
    require(msg.sender == resolver);

  }
}


limit the operation of the consensus node

pragma solidity ^0.4.11;

import "./strings.sol";
import "./node_interface.sol";

contract NodeManager is NodeInterface {
    using strings for *;

    // the enum prob: default: Close
    enum NodeStatus { Close, Ready, Start }

    // the status of the node: ready, start, not in list/close, maybe there is more
    mapping(address => NodeStatus) public status;
    // admin
    mapping (address => bool) admins;
    // recode the operation of the block
    mapping(uint => bool) block_op;

    // consensus node list
    address[] nodes;

    event NewNode(address _node);
    event ApproveNode(address _node);
    event DeleteNode(address _node);
    event AddAdmin(address indexed _node, address indexed _sender);

    modifier onlyAdmin {
        if (admins[msg.sender]) {
            _;
        } else {
            revert();
        }
    }

    // should operate one time in a block
    modifier oneOperate {
        if (!block_op[block.number]) {
            _;
        } else {
            revert();
        }
    }

    // setup
    function NodeManager(address[] _nodes, address[] _admins) {
        // initialize the address to Start
        for (uint i = 0; i < _nodes.length; i++) {
            status[_nodes[i]] = NodeStatus.Start;
            nodes.push(_nodes[i]);
        }
        // initialize the address of admins
        for (uint j = 0; j < _admins.length; j++)
            admins[_admins[j]] = true;
    }

    function addAdmin(address _node) onlyAdmin returns (bool) {
        admins[_node] = true;
        AddAdmin(_node, msg.sender);
        return true;
    }

    // apply to be consensus node. status will be ready
    function newNode(address _node) returns (bool) {
        // should not add the started node, what about the already added node
        // require(status[_node] == NodeStatus.Close);
        if (status[_node] == NodeStatus.Ready || status[_node] == NodeStatus.Start) {
            return false;
        }

        status[_node] = NodeStatus.Ready;
        NewNode(_node);
        // test
        // assert(status[_node] == NodeStatus.Ready);
        return true;
    }

    // approve to be consensus node. status will be start
    function approveNode(address _node) onlyAdmin oneOperate returns (bool) {
        // the status should be ready
        // require(status[_node] == NodeStatus.Ready);
        if (status[_node] != NodeStatus.Ready) {
            return false;
        }

        status[_node] = NodeStatus.Start;
        block_op[block.number] = true;
        nodes.push(_node);
        ApproveNode(_node);
        // assert(status[_node] == NodeStatus.Start);
        return true;
    }

    // delete the consensus node from the list
    // which means delete the node whoes status is Start
    function deleteNode(address _node) onlyAdmin oneOperate returns (bool) {
        // require(status[_node] == NodeStatus.Start);
        if (status[_node] != NodeStatus.Start) {
            return false;
        }

        var index = nodeIndex(_node);
        // not found
        if (index >= nodes.length) {
            return false;
        }

        status[_node] = NodeStatus.Close;
        // remove the gap
        for (uint i = index; i < nodes.length - 1; i++) {
            nodes[i] = nodes[i + 1];
        }
        // also delete the last element
        delete nodes[nodes.length - 1];
        nodes.length--;
        block_op[block.number] = false;
        DeleteNode(_node);
        // assert(status[_node] == NodeStatus.Close);
        return true;
    }

    // list the node of the Start
    function listNode() constant returns (string) {
        return concatNodes(nodes);
    }

    // get the status of the node
    function getStatus(address _node) constant returns (uint8) {
        return uint8(status[_node]);
    }

    function isAdmin(address _node) constant returns (bool) {
        return admins[_node];
    }

    // interface: link address to a long string
    function concatNodes(address[] _add) internal returns (string nodeList) {
        if (_add.length > 0) {
            nodeList = toString(_add[0]);
        }

        for (uint i = 1; i < _add.length; i++) {
            nodeList = nodeList.toSlice().concat(toString(_add[i]).toSlice());
        }
    }

    // interface: get the index in the nodes_of_start array
    function nodeIndex(address _node) internal returns (uint) {
        // find the index of the member
        for (uint i = 0; i < nodes.length; i++) {
            if (_node == nodes[i]) {
                return i;
            }
        }
        // if i == length, means not find
        return i;
    }

    // interface: address to string
    // the returned string is ABI encoded
    function toString(address x) internal returns (string) {
        bytes memory b = new bytes(20);

        for (uint i = 0; i < 20; i++) {
            b[i] = byte(uint8(uint(x) / (2**(8*(19 - i)))));
        }

        return string(b);
    }
}

pragma solidity ^0.4.11;

import "./strings.sol";
import "./node_interface.sol";

contract NodeManager is NodeInterface {
    using strings for *;

    // the enum prob: default: Close
    enum NodeStatus { Close, Ready, Start }

    // the status of the node: ready, start, not in list/close, maybe there is more
    mapping(address => NodeStatus) public status;
    // admin
    mapping (address => bool) admins;

    // consensus node list
    address[] nodes;

    event NewNode(address _node);
    event ApproveNode(address _node);
    event DeleteNode(address _node);
    event AddAdmin(address indexed _node, address indexed _sender);

    modifier onlyAdmin {
        if (admins[msg.sender]) {
            _;
        } else {
            revert();
        }
    }
    // setup
    function NodeManager(address[] _nodes, address[] _admins) {
        // initialize the address to Start
        for (uint i = 0; i < _nodes.length; i++) {
            status[_nodes[i]] = NodeStatus.Start;
            nodes.push(_nodes[i]);
        }
        // initialize the address of admins
        for (uint j = 0; j < _admins.length; j++)
            admins[_admins[j]] = true;
    }

    function addAdmin(address _node) onlyAdmin returns (bool) {
        admins[_node] = true;
        AddAdmin(_node, msg.sender);
        return true;
    }

    // apply to be consensus node. status will be ready
    function newNode(address _node) returns (bool) {
        // should not add the started node, what about the already added node
        // require(status[_node] == NodeStatus.Close);
        if (status[_node] == NodeStatus.Ready || status[_node] == NodeStatus.Start) {
            return false;
        }

        status[_node] = NodeStatus.Ready;
        NewNode(_node);
        // test
        // assert(status[_node] == NodeStatus.Ready);
        return true;
    }

    // approve to be consensus node. status will be start
    function approveNode(address _node) onlyAdmin returns (bool) {
        // the status should be ready
        // require(status[_node] == NodeStatus.Ready);
        if (status[_node] != NodeStatus.Ready) {
            return false;
        }

        status[_node] = NodeStatus.Start;
        nodes.push(_node);
        ApproveNode(_node);
        // assert(status[_node] == NodeStatus.Start);
        return true;
    }

    // delete the consensus node from the list
    // which means delete the node whoes status is Start
    function deleteNode(address _node) onlyAdmin returns (bool) {
        // require(status[_node] == NodeStatus.Start);
        if (status[_node] != NodeStatus.Start) {
            return false;
        }

        var index = nodeIndex(_node);
        // not found
        if (index >= nodes.length) {
            return false;
        }

        status[_node] = NodeStatus.Close;
        // remove the gap
        for (uint i = index; i < nodes.length - 1; i++) {
            nodes[i] = nodes[i + 1];
        }
        // also delete the last element
        delete nodes[nodes.length - 1];
        nodes.length--;
        DeleteNode(_node);
        // assert(status[_node] == NodeStatus.Close);
        return true;
    }

    // list the node of the Start
    function listNode() constant returns (string) {
        return concatNodes(nodes);
    }

    // get the status of the node
    function getStatus(address _node) constant returns (uint8) {
        return uint8(status[_node]);
    }

    function isAdmin(address _node) constant returns (bool) {
        return admins[_node];
    }

    // interface: link address to a long string
    function concatNodes(address[] _add) internal returns (string nodeList) {
        if (_add.length > 0) {
            nodeList = toString(_add[0]);
        }

        for (uint i = 1; i < _add.length; i++) {
            nodeList = nodeList.toSlice().concat(toString(_add[i]).toSlice());
        }
    }

    // interface: get the index in the nodes_of_start array
    function nodeIndex(address _node) internal returns (uint) {
        // find the index of the member
        for (uint i = 0; i < nodes.length; i++) {
            if (_node == nodes[i]) {
                return i;
            }
        }
        // if i == length, means not find
        return i;
    }

    // interface: address to string
    // the returned string is ABI encoded
    function toString(address x) internal returns (string) {
        bytes memory b = new bytes(20);

        for (uint i = 0; i < 20; i++) {
            b[i] = byte(uint8(uint(x) / (2**(8*(19 - i)))));
        }

        return string(b);
    }
}


Add gas limiting on eval calls

Add gas limiting on eval calls

import "BulletinBoard.sol";

/**
 * This contract performs an "eval" on arbitrary contracts but only with the
 * consent of all participants named.
 */
contract UnanimousConsent {

	enum ConsentState {
		NONE,
		CONSENTED,
		EXECUTED
	}

	// Records the current state of consent for a given hash and address
	mapping (bytes32 =>
			mapping (address => ConsentState)) consentStates;

	// Holds all of the participants in the current UnanimousConsent contract
	address[] participants;

	// Holds the BulletinBoard for counterfactual addressing
	BulletinBoard public bulletinBoard;

	modifier onlySelf {
		if (msg.sender == address(this)) {
			_
		} else {
			throw;
		}
	}

	/**
	 * Creates a new UnanimousConsent contract.
	 *
	 * _participants: The initial participants in the contract
	 */
	function UnanimousConsent(address[] _participants) {
		participants = _participants;
		bulletinBoard = new BulletinBoard(this);
	}

	/**
	 * Evaluates arbitrary functions of contracts, but only with universal
	 * consent. Note that any `eval` sub-calls should `throw` in the event that
	 * there is a contract execution failure (such as if a precondition isn't
	 * met or if a verification of some sort fails) to prevent this call from
	 * finishing.
	 *
	 * _calledContracts: The addresses of the called contracts
	 * _methodSignatures: The method signatures of the functions
	 * _argumentLengths: The lengths of the arguments for each function call
	 * _arguments: The arguments of all function calls concatenated
	 * _values: Amount of Ether to send for each respective call
	 * _gases: Amount of gas to put into the call, 0 means unbounded usage
	 */
	function eval(
		address[] _calledContracts,
		bytes4[] _methodSignatures,
		uint[] _argumentLengths,
		bytes32[] _arguments,
		uint[] _values,
		uint[] _gases
	) {
		if (
			_calledContracts.length != _methodSignatures.length ||
			_calledContracts.length != _argumentLengths.length ||
			_calledContracts.length != _values.length ||
			_calledContracts.length != _gases.length
		) {
			throw;
		}

		uint i;
		uint j;
		bytes32 hash = sha3(_calledContracts, _methodSignatures, _argumentLengths, _arguments, _values, _gases);

		for (i = 0; i < participants.length; i++) {
			if (consentStates[hash][participants[i]] == ConsentState.CONSENTED) {
				consentStates[hash][participants[i]] = ConsentState.EXECUTED;
			} else {
				throw;
			}
		}

		uint argumentsIndex = 0;
		for (i = 0; i < _calledContracts.length; i++) {

			bytes32[] memory arguments = new bytes32[](_argumentLengths[i]);
			for (j = 0; j < _argumentLengths[i]; j++) {
				arguments[j] = _arguments[argumentsIndex++];
			}

			if (_gases[i] == 0) {
				if (!_calledContracts[i].call.value(_values[i])(_methodSignatures[i], arguments[i])) {
					throw;
				}
			} else {
				if (!_calledContracts[i].call.value(_values[i]).gas(_gases[i])(_methodSignatures[i], arguments[i])) {
					throw;
				}
			}
		}
	}

	/**
	 * Provides consent for the hash of an execution call for the sender of the
	 * message.
	 *
	 * _hash: The hash of the execution call
	 *
	 * returns: `true` if successful, otherwise `false`
	 */
	function consent(bytes32 _hash) returns (bool) {
		if (consentStates[_hash][msg.sender] == ConsentState.NONE) {
			consentStates[_hash][msg.sender] = ConsentState.CONSENTED;
			return true;
		} else {
			return false;
		}
	}

	/**
	 * Sends the Ether stored in the currenct contract. Intended to only be
	 * called by this contract's `eval`.
	 *
	 * _recipient: The recipient of the Ether.
	 * _amount: The amount of Ether to send.
	 */
	function sendEther(address _recipient, uint _amount) external onlySelf {
		if (!_recipient.send(_amount)) {
			throw;
		}
	}

	/**
	 * Changes the participants in the current contract. Intended to only be
	 * called by this contract's `eval`.
	 *
	 * _participants: The new participants in the contract
	 */
	function changeParticipants(address[] _participants) external onlySelf {
		participants = _participants;
	}

	/**
	 * Cleans up previously approved consents. Intended to only be called by
	 * this contract's `eval`.
	 *
	 * _hashes: The list of hashes to clean
	 * _participants: The list of address whose hashes should be cleaned
	 */
	function clean(bytes32[] _hashes, address[] _participants) external onlySelf {
		for (uint i = 0; i < _hashes.length; i++) {
			for (uint j = 0; j < _participants.length; j++) {
				delete consentStates[_hashes[i]][_participants[j]];
			}
		}
	}

	/**
	 * Kills the current contract. Intended to only be called by this contract's
	 * eval.
	 *
	 * _recipient: The recipient of funds from the `selfdestruct` call
	 */
	function kill(address _recipient) external onlySelf {
		selfdestruct(_recipient);
	}
}

import "BulletinBoard.sol";

/**
 * This contract performs an "eval" on arbitrary contracts but only with the
 * consent of all participants named.
 */
contract UnanimousConsent {

	enum ConsentState {
		NONE,
		CONSENTED,
		EXECUTED
	}

	// Records the current state of consent for a given hash and address
	mapping (bytes32 =>
			mapping (address => ConsentState)) consentStates;

	// Holds all of the participants in the current UnanimousConsent contract
	address[] participants;

	// Holds the BulletinBoard for counterfactual addressing
	BulletinBoard public bulletinBoard;

	modifier onlySelf {
		if (msg.sender == address(this)) {
			_
		} else {
			throw;
		}
	}

	/**
	 * Creates a new UnanimousConsent contract.
	 *
	 * _participants: The initial participants in the contract
	 */
	function UnanimousConsent(address[] _participants) {
		participants = _participants;
		bulletinBoard = new BulletinBoard(this);
	}

	/**
	 * Evaluates arbitrary functions of contracts, but only with universal
	 * consent. Note that any `eval` sub-calls should `throw` in the event that
	 * there is a contract execution failure (such as if a precondition isn't
	 * met or if a verification of some sort fails) to prevent this call from
	 * finishing.
	 *
	 * _calledContracts: The addresses of the called contracts
	 * _methodSignatures: The method signatures of the functions
	 * _argumentLengths: The lengths of the arguments for each function call
	 * _arguments: The arguments of all function calls concatenated
	 * _values: Amount of Ether to send for each respective call
	 */
	function eval(
		address[] _calledContracts,
		bytes4[] _methodSignatures,
		uint[] _argumentLengths,
		bytes32[] _arguments,
		uint[] _values
	) {
		if (
			_calledContracts.length != _methodSignatures.length ||
			_calledContracts.length != _argumentLengths.length ||
			_calledContracts.length != _values.length
		) {
			throw;
		}

		uint i;
		uint j;
		bytes32 hash = sha3(_calledContracts, _methodSignatures, _argumentLengths, _arguments, _values);

		for (i = 0; i < participants.length; i++) {
			if (consentStates[hash][participants[i]] == ConsentState.CONSENTED) {
				consentStates[hash][participants[i]] = ConsentState.EXECUTED;
			} else {
				throw;
			}
		}

		uint argumentsIndex = 0;
		for (i = 0; i < _calledContracts.length; i++) {

			bytes32[] memory arguments = new bytes32[](_argumentLengths[i]);
			for (j = 0; j < _argumentLengths[i]; j++) {
				arguments[j] = _arguments[argumentsIndex++];
			}

			if (!_calledContracts[i].call.value(_values[i])(_methodSignatures[i], arguments[i])) {
				throw;
			}
		}
	}

	/**
	 * Provides consent for the hash of an execution call for the sender of the
	 * message.
	 *
	 * _hash: The hash of the execution call
	 *
	 * returns: `true` if successful, otherwise `false`
	 */
	function consent(bytes32 _hash) returns (bool) {
		if (consentStates[_hash][msg.sender] == ConsentState.NONE) {
			consentStates[_hash][msg.sender] = ConsentState.CONSENTED;
			return true;
		} else {
			return false;
		}
	}

	/**
	 * Sends the Ether stored in the currenct contract. Intended to only be
	 * called by this contract's `eval`.
	 *
	 * _recipient: The recipient of the Ether.
	 * _amount: The amount of Ether to send.
	 */
	function sendEther(address _recipient, uint _amount) external onlySelf {
		if (!_recipient.send(_amount)) {
			throw;
		}
	}

	/**
	 * Changes the participants in the current contract. Intended to only be
	 * called by this contract's `eval`.
	 *
	 * _participants: The new participants in the contract
	 */
	function changeParticipants(address[] _participants) external onlySelf {
		participants = _participants;
	}

	/**
	 * Cleans up previously approved consents. Intended to only be called by
	 * this contract's `eval`.
	 *
	 * _hashes: The list of hashes to clean
	 * _participants: The list of address whose hashes should be cleaned
	 */
	function clean(bytes32[] _hashes, address[] _participants) external onlySelf {
		for (uint i = 0; i < _hashes.length; i++) {
			for (uint j = 0; j < _participants.length; j++) {
				delete consentStates[_hashes[i]][_participants[j]];
			}
		}
	}

	/**
	 * Kills the current contract. Intended to only be called by this contract's
	 * eval.
	 *
	 * _recipient: The recipient of funds from the `selfdestruct` call
	 */
	function kill(address _recipient) external onlySelf {
		selfdestruct(_recipient);
	}
}


Make operators more specific

Make operators more specific

contract Adjudicator {

	uint constant UINT_MAX = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF;

	bool public frozen = false;
	uint nonce = 0;
	uint lastTimestamp = 0;
	address owner;
	uint timeout;
	bytes32 public stateHash;

	modifier onlyOwner {
		if (msg.sender == owner) {
			_
		} else {
			throw;
		}
	}

	modifier notFrozen {
		if (frozen) {
			throw;
		} else {
			_
		}
	}

	function Adjudicator(address _owner, uint _timeout) {
		owner = _owner;
		timeout = _timeout;
	}

	function submit(uint _newNonce, bytes32 _stateHash)
		external
		onlyOwner
		notFrozen
		returns (bool)
	{
		if (_newNonce > nonce) {
			nonce = _newNonce;
			stateHash = _stateHash;
			return true;
		} else {
			return false;
		}
	}

	function unfreeze() external onlyOwner returns (bool) {
		if (frozen && nonce != UINT_MAX) {
			lastTimestamp = 0;
			frozen = false;
			return true;
		} else {
			return false;
		}
	}

	function finalize() external notFrozen returns (bool) {
		if (nonce == UINT_MAX || (lastTimestamp != 0 && now > lastTimestamp + timeout)) {
			frozen = true;
			return true;
		} else {
			return false;
		}
	}

	function kill(address _recipient) external onlyOwner {
		selfdestruct(_recipient);
	}
}

contract Adjudicator {

	uint constant UINT_MAX = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF;

	bool public frozen = false;
	uint nonce = 0;
	uint lastTimestamp = 0;
	address owner;
	uint timeout;
	bytes32 public stateHash;

	modifier onlyOwner {
		if (msg.sender == owner) {
			_
		} else {
			throw;
		}
	}

	modifier notFrozen {
		if (frozen) {
			throw;
		} else {
			_
		}
	}

	function Adjudicator(address _owner, uint _timeout) {
		owner = _owner;
		timeout = _timeout;
	}

	function submit(uint _newNonce, bytes32 _stateHash)
		external
		onlyOwner
		notFrozen
		returns (bool)
	{
		if (_newNonce > nonce) {
			nonce = _newNonce;
			stateHash = _stateHash;
			return true;
		} else {
			return false;
		}
	}

	function unfreeze() external onlyOwner returns (bool) {
		if (frozen && nonce < UINT_MAX) {
			lastTimestamp = 0;
			frozen = false;
			return true;
		} else {
			return false;
		}
	}

	function finalize() external notFrozen returns (bool) {
		if (nonce == UINT_MAX || (lastTimestamp > 0 && now > lastTimestamp + timeout)) {
			frozen = true;
			return true;
		} else {
			return false;
		}
	}

	function kill(address _recipient) external onlyOwner {
		selfdestruct(_recipient);
	}
}


fix upd rebate rate function

fix upd rebate rate function

contract coin {}

contract issuer {
    address public issuerAddr;
    address public coinAddr;
    coin public pluton;
    uint dayBtcVolume;
    uint volumeUpdateTimestamp;

    struct Rebate {
        uint plutonRewardRate;
        uint maxPlutonRewardRate;
        uint minPlutonRewardRate;
        uint minDayVolumeForReduce;
        uint dayRebateRateChange;
        uint plutonRewardRateReduceStep;
        uint plutonRewardRateReduce;
        uint baseUnitForRebate;
    }
    Rebate public rebate;

    modifier ownerCheck { if (msg.sender == issuerAddr) _ }

    /*Initial */
    function issuer(address _issuer, coin _plutonAddr) {
        issuerAddr = _issuer;
        coinAddr = _plutonAddr;

        rebate.baseUnitForRebate = 1000; // accrual 0,1%
        rebate.maxPlutonRewardRate = 30; // 3%
        rebate.plutonRewardRate = rebate.maxPlutonRewardRate; // 3%
        rebate.minPlutonRewardRate = 10; // 1%
        rebate.minDayVolumeForReduce = 500; // 500 BTC
        rebate.plutonRewardRateReduce = 1; // reduce 0,1% from every 100 BTC
        rebate.plutonRewardRateReduceStep = 100; // reduce step 100 BTC
        rebate.dayRebateRateChange = 0; // Initial data

        dayBtcVolume = 0;
        volumeUpdateTimestamp = now;

        pluton = coin(_plutonAddr);
    }

    /* issuer functions */

    function updRebateRate(uint _lastDayBtcVolume) returns(uint plutonRewardRate) {
        if(_lastDayBtcVolume > dayBtcVolume)
        {
            rebate.dayRebateRateChange = (_lastDayBtcVolume - dayBtcVolume) / rebate.plutonRewardRateReduceStep * rebate.plutonRewardRateReduce;
            if(rebate.plutonRewardRate - rebate.dayRebateRateChange <= rebate.minPlutonRewardRate) {rebate.plutonRewardRate = rebate.minPlutonRewardRate; dayBtcVolume = _lastDayBtcVolume;}
                else {rebate.plutonRewardRate = rebate.plutonRewardRate - rebate.dayRebateRateChange;  dayBtcVolume = _lastDayBtcVolume;}
        } else {
            rebate.dayRebateRateChange = (dayBtcVolume - _lastDayBtcVolume) / rebate.plutonRewardRateReduceStep * rebate.plutonRewardRateReduce;
            if(rebate.dayRebateRateChange + rebate.plutonRewardRate >= rebate.maxPlutonRewardRate) {rebate.plutonRewardRate = rebate.maxPlutonRewardRate;  dayBtcVolume = _lastDayBtcVolume;}
                else {rebate.plutonRewardRate = rebate.plutonRewardRate + rebate.dayRebateRateChange;  dayBtcVolume = _lastDayBtcVolume;}
        }

        return(rebate.plutonRewardRate);

    }

    function getRebate() ownerCheck returns(uint plutonReward) {
        return(rebate.plutonRewardRate);
         //   pluton.emmision(plutonReward);
        //    pluton.transfer(plutonReward, _btcSeller);
    }

}

contract coin {}

contract issuer {
    address public issuerAddr;
    address public coinAddr;
    coin public pluton;
    uint dayBtcVolume;
    uint volumeUpdateTimestamp;

    struct Rebate {
        uint plutonRewardRate;
        uint maxPlutonRewardRate;
        uint minPlutonRewardRate;
        uint minDayVolumeForReduce;
        uint dayRebateRateChange;
        uint plutonRewardRateReduceStep;
        uint plutonRewardRateReduce;
        uint baseUnitForRebate;
    }
    Rebate public rebate;

    modifier ownerCheck { if (msg.sender == issuerAddr) _ }

    /*Initial */
    function issuer(address _issuer, coin _plutonAddr) {
        issuerAddr = _issuer;
        coinAddr = _plutonAddr;

        rebate.baseUnitForRebate = 1000; // accrual 0,1%
        rebate.maxPlutonRewardRate = 30; // 3%
        rebate.plutonRewardRate = rebate.maxPlutonRewardRate; // 3%
        rebate.minPlutonRewardRate = 10; // 1%
        rebate.minDayVolumeForReduce = 500; // 500 BTC
        rebate.plutonRewardRateReduce = 1; // reduce 0,1% from every 100 BTC
        rebate.plutonRewardRateReduceStep = 100; // reduce step 100 BTC
        rebate.dayRebateRateChange = 0; // Initial data

        dayBtcVolume = 0;
        volumeUpdateTimestamp = now;

        pluton = coin(_plutonAddr);
    }

    /* issuer functions */

    function updRebateRate(uint _lastDayBtcVolume) returns(uint plutonRewardRate) {
        if(_lastDayBtcVolume > dayBtcVolume)
        {
            rebate.dayRebateRateChange = (_lastDayBtcVolume - dayBtcVolume) / rebate.plutonRewardRateReduceStep * rebate.plutonRewardRateReduce;
            if(rebate.dayRebateRateChange - rebate.plutonRewardRate < rebate.minPlutonRewardRate) {rebate.plutonRewardRate = rebate.minPlutonRewardRate;}
                else rebate.plutonRewardRate = rebate.plutonRewardRate - rebate.minPlutonRewardRate;
        } else {
            rebate.dayRebateRateChange = (dayBtcVolume - _lastDayBtcVolume) / rebate.plutonRewardRateReduceStep * rebate.plutonRewardRateReduce;
            if(rebate.dayRebateRateChange + rebate.plutonRewardRate > rebate.maxPlutonRewardRate) {rebate.plutonRewardRate = rebate.maxPlutonRewardRate;}
                else rebate.plutonRewardRate = rebate.plutonRewardRate + rebate.minPlutonRewardRate;
        }

        return(rebate.plutonRewardRate);

    }

    function getRebate(uint _btcAmount, string txID, address _btcSeller) ownerCheck returns(uint plutonReward) {

         //   pluton.emmision(plutonReward);
        //    pluton.transfer(plutonReward, _btcSeller);
    }

}


Swap SimpleToken with Target

Swap SimpleToken with Target

pragma solidity ^0.4.0;
import './PullPayment.sol';

/*
 * Bounty
 * This bounty will pay out if you can cause a SimpleToken's balance
 * to be lower than its totalSupply, which would mean that it doesn't
 * have sufficient ether for everyone to withdraw.
 */

contract Target {
  function checkInvarient() returns(bool){
    return true;
  }
}

contract Bounty is PullPayment {
  Target target;
  bool public claimed;
  mapping(address => address) public researchers;

  function() {
    if (claimed) throw;
  }

  function createTarget() returns(Target) {
    target = new Target();
    researchers[target] = msg.sender;
    return target;
  }

  function checkInvarient() returns(bool){
    return target.checkInvarient();
  }

  function claim(Target target) {
    address researcher = researchers[target];
    if (researcher == 0) throw;
    // Check Target contract invariants
    // Customize this to the specifics of your contract
    if (!target.checkInvarient()) {
      throw;
    }
    asyncSend(researcher, this.balance);
    claimed = true;
  }

}

pragma solidity ^0.4.0;
import './PullPayment.sol';
import './token/SimpleToken.sol';

/*
 * Bounty
 * This bounty will pay out if you can cause a SimpleToken's balance
 * to be lower than its totalSupply, which would mean that it doesn't
 * have sufficient ether for everyone to withdraw.
 */
contract Bounty is PullPayment {

  bool public claimed;
  mapping(address => address) public researchers;

  function() {
    if (claimed) throw;
  }

  function createTarget() returns(SimpleToken) {
    SimpleToken target = new SimpleToken();
    researchers[target] = msg.sender;
    return target;
  }

  function checkInvarient() returns(bool){
    return true;
  }

  function claim(SimpleToken target) {
    address researcher = researchers[target];
    if (researcher == 0) throw;
    // Check SimpleToken contract invariants
    // Customize this to the specifics of your contract
    if (target.totalSupply() == target.balance) {
      throw;
    }
    asyncSend(researcher, this.balance);
    claimed = true;
  }

}


#2 Implement ERC20 Interface to UTCoin

#2 Implement ERC20 Interface to UTCoin

pragma solidity ^0.4.11;

import "./ERC20Interface.sol";

contract UTCoin is ERC20Interface {
    string public constant symbol = "UTC";
    string public constant name = "UTCoin";
    uint8 public constant decimals = 18;
    uint256 _totalSupply = 1000000;

    // Owner of this contract
    address public owner;

    // Balances for each account
    mapping(address => uint256) balances;

    // Owner of account approves the transfer of an amount to another account
    mapping(address => mapping (address => uint256)) allowed;

    // Blacklist
    mapping (address => bool) public blacklist;

    // Events
    event TransferOwnership(address _old_addr, address _new_addr);
    event Blacklisted(address indexed _target);
    event DeleteFromBlacklist(address indexed _target);

    // Functions with this modifier can only be executed by the owner
    modifier onlyOwner() {
        require(msg.sender == owner);
        _;
    }

    // Constructor
    function UTCoin() {
        owner = msg.sender;
        balances[owner] = _totalSupply;
    }

    function totalSupply() constant returns (uint256 totalSupply) {
        totalSupply = _totalSupply;
    }

    // What is the balance of a particular account?
    function balanceOf(address _owner) constant returns (uint256 balance) {
        return balances[_owner];
    }

    // Transfer the balance from owner's account to another account
    function transfer(address _to, uint256 _amount) returns (bool success) {
        require(blacklist[msg.sender] == false);
        require(blacklist[_to] == false);

        if (balances[msg.sender] >= _amount
            && _amount > 0
            && balances[_to] + _amount > balances[_to]) {
            balances[msg.sender] -= _amount;
            balances[_to] += _amount;
            Transfer(msg.sender, _to, _amount);
            return true;
        } else {
            return false;
        }
    }

    // Send _value amount of tokens from address _from to address _to
    // The transferFrom method is used for a withdraw workflow, allowing contracts to send
    // tokens on your behalf, for example to "deposit" to a contract address and/or to charge
    // fees in sub-currencies; the command should fail unless the _from account has
    // deliberately authorized the sender of the message via some mechanism; we propose
    // these standardized APIs for approval:
    function transferFrom(address _from, address _to, uint256 _amount) returns (bool success) {
        require(blacklist[_from] == false);
        require(blacklist[_to] == false);

        if (balances[_from] >= _amount
            && allowed[_from][msg.sender] >= _amount
            && _amount > 0
            && balances[_to] + _amount > balances[_to]) {
            balances[_from] -= _amount;
            allowed[_from][msg.sender] -= _amount;
            balances[_to] += _amount;
            Transfer(_from, _to, _amount);
            return true;
        } else {
            return false;
        }
    }

    // Allow _spender to withdraw from your account, multiple times, up to the _value amount.
    // If this function is called again it overwrites the current allowance with _value.
    function approve(address _spender, uint256 _amount) returns (bool success) {
        allowed[msg.sender][_spender] = _amount;
        Approval(msg.sender, _spender, _amount);
        return true;
    }

    function allowance(address _owner, address _spender) constant returns (uint256 remaining) {
        return allowed[_owner][_spender];
    }

    /**
     * アドレスをブラックリストに登録
     * @param _addr 対象のアドレス
     */
    function blacklisting(address _addr) onlyOwner {
        blacklist[_addr] = true;
        Blacklisted(_addr);
    }

    /**
     * アドレスをブラックリストから削除
     * @param _addr 対象のアドレス
     */
    function deleteFromBlacklist(address _addr) onlyOwner {
        blacklist[_addr] = false;
        DeleteFromBlacklist(_addr);
    }

    /**
     * オーナーを移転
     * @param _new_addr 移転先のアドレス
     */
    function transferOwnership(address _new_addr) onlyOwner {
        address old_addr = owner;
        owner = _new_addr;
        TransferOwnership(old_addr, owner);
    }
}

pragma solidity ^0.4.4;

import "./Owned.sol";
import "./ConvertLib.sol";

contract UTCoin is Owned {
    uint256 public totalSupply = 10000; // トークンの総量
    mapping (address => uint) balances; // 各アドレスの残高
    mapping (address => bool) public blacklist; // ブラックリスト

    // イベント通知
    event Transfer(address indexed from, address indexed to, uint256 value);
    event Blacklisted(address indexed target);
    event DeleteFromBlacklist(address indexed target);

    /**
     * コンストラクタ
     */
    function UTCoin() {
        balances[msg.sender] = totalSupply;
    }

    /**
     * アドレスをブラックリストに登録
     * @param addr 対象のアドレス
     */
    function blacklisting(address addr) onlyOwner {
        blacklist[addr] = true;
        Blacklisted(addr);
    }

    /**
     * アドレスをブラックリストから削除
     * @param addr 対象のアドレス
     */
    function deleteFromBlacklist(address addr) onlyOwner {
        blacklist[addr] = false;
        DeleteFromBlacklist(addr);
    }

    /**
     * 送金
     * @param receiver 受信アドレス
     * @param amount 送金量
     * @return sufficient
     */
    function sendCoin(address receiver, uint amount) returns(bool sufficient) {
        // 不正送金チェック
        require(balances[msg.sender] >= amount);
        require(balances[receiver] + amount >= balances[receiver]);

        // ブラックリストチェック
        require(blacklist[msg.sender] == false);
        require(blacklist[receiver] == false);

        // 送信アドレスと受信アドレスの残高を更新
        balances[msg.sender] -= amount;
        balances[receiver] += amount;

        // イベント通知
        Transfer(msg.sender, receiver, amount);

        return true;
    }

    /**
     * ETH balance を返す
     * address の持っている UTCoin balance を2倍にして返す。この時 ConvertLib contract が呼ばれる。
     * @param addr アドレス
     * @return ETH balance
     */
    function getBalanceInEth(address addr) returns(uint){
        return ConvertLib.convert(getBalance(addr),2);
    }

    /**
     * UTCoin balance を返す
     * @param addr アドレス
     * @return UTCoin balance
     */
    function getBalance(address addr) returns(uint) {
        return balances[addr];
    }
}


Fixed contract template

Fixed contract template

pragma solidity ^0.4.1;

contract <%= name.capitalize %> {
}


Removing unrequired `_burn()` override (#1373)

* signing prefix added

* Minor improvement

* Tests changed

* Successfully tested

* Minor improvements

* Minor improvements

* Revert "Dangling commas are now required. (#1359)"

This reverts commit a6889776f46adca374b6ebf014aa7b0038112a9d.

* updates

* fixes #1371

* Removed extra whitespace

(cherry picked from commit f3888bb0b0a2eba5282a1bd5828135910b65bc8d)

pragma solidity ^0.4.24;

import "./ERC20.sol";

/**
 * @title Burnable Token
 * @dev Token that can be irreversibly burned (destroyed).
 */
contract ERC20Burnable is ERC20 {

  /**
   * @dev Burns a specific amount of tokens.
   * @param value The amount of token to be burned.
   */
  function burn(uint256 value) public {
    _burn(msg.sender, value);
  }

  /**
   * @dev Burns a specific amount of tokens from the target address and decrements allowance
   * @param from address The address which you want to send tokens from
   * @param value uint256 The amount of token to be burned
   */
  function burnFrom(address from, uint256 value) public {
    _burnFrom(from, value);
  }
}

pragma solidity ^0.4.24;

import "./ERC20.sol";

/**
 * @title Burnable Token
 * @dev Token that can be irreversibly burned (destroyed).
 */
contract ERC20Burnable is ERC20 {

  /**
   * @dev Burns a specific amount of tokens.
   * @param value The amount of token to be burned.
   */
  function burn(uint256 value) public {
    _burn(msg.sender, value);
  }

  /**
   * @dev Burns a specific amount of tokens from the target address and decrements allowance
   * @param from address The address which you want to send tokens from
   * @param value uint256 The amount of token to be burned
   */
  function burnFrom(address from, uint256 value) public {
    _burnFrom(from, value);
  }

  /**
   * @dev Overrides ERC20._burn in order for burn and burnFrom to emit
   * an additional Burn event.
   */
  function _burn(address who, uint256 value) internal {
    super._burn(who, value);
  }
}