Refactor using `saleEnded`.

Refactor using `saleEnded`.

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(60 * MAX_TOKENS.div(100), 0, 0, 3 years, 1 days, 0);

        // Kik, 30%
        tokenGrantees.push(KIK_ADDRESS);
        tokenGrants[KIK_ADDRESS] = TokenGrant(30 * MAX_TOKENS.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() {
        if (tokensSold >= MAX_TOKENS_SOLD || now < startTime || now >= endTime) {
            revert();
        }

        _;
    }

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

        _;
    }

    /// @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(60 * MAX_TOKENS.div(100), 0, 0, 3 years, 1 days, 0);

        // Kik, 30%
        tokenGrantees.push(KIK_ADDRESS);
        tokenGrants[KIK_ADDRESS] = TokenGrant(30 * MAX_TOKENS.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 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();
    }
}


symbol was renamed to "DMT"

symbol was renamed to "DMT"

pragma solidity 0.4.18;

import "github.com/OpenZeppelin/zeppelin-solidity/contracts/math/SafeMath.sol";
import "github.com/OpenZeppelin/zeppelin-solidity/contracts/token/ERC20Basic.sol";
import "github.com/OpenZeppelin/zeppelin-solidity/contracts/token/ERC20.sol";
import "github.com/OpenZeppelin/zeppelin-solidity/contracts/ownership/Ownable.sol";

contract ApprovalContract is ERC20 {
    using SafeMath for uint256;

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

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

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

    /**
     * approve should be called when allowed[_spender] == 0. To increment
     * allowed value is better to use this function to avoid 2 calls (and wait until
     * the first transaction is mined)
     * From MonolithDAO Token.sol
     */
    function increaseApproval (address _spender, uint _addedValue) public
    returns (bool success) {
        allowed[msg.sender][_spender] = allowed[msg.sender][_spender].add(_addedValue);
        Approval(msg.sender, _spender, allowed[msg.sender][_spender]);
        return true;
    }

    function decreaseApproval (address _spender, uint _subtractedValue) public
    returns (bool success) {
        uint oldValue = allowed[msg.sender][_spender];
        if (_subtractedValue > oldValue) {
            allowed[msg.sender][_spender] = 0;
        } else {
            allowed[msg.sender][_spender] = oldValue.sub(_subtractedValue);
        }
        Approval(msg.sender, _spender, allowed[msg.sender][_spender]);
        return true;
    }
}

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

    uint256 public hardCap;
    mapping(address => uint256) public balances;

    event Mint(address indexed to, uint256 amount);

    modifier canMint() {
        require(totalSupply == 0);
        _;
    }

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

/**
 * @title Vesting token
 */
contract Vesting is MintableToken {

    event VestingMemberAdded(address indexed _address, uint256 _amount, uint _start, uint _end);

    struct _Vesting {
        uint256 totalSum;     //total amount
        uint256 start;        //start block
        uint256 end;          //end block
        uint256 usedAmount;   //the amount of paid payments
    }

    mapping (address => _Vesting ) public vestingMembers;

    function addVestingMember(
        address _address,
        uint256 _amount,
        uint256 _start,
        uint256 _end
    ) onlyOwner public returns (bool) {
        require(
            _address != address(0) &&
            _amount > 0 &&
            _start < _end &&
            vestingMembers[_address].totalSum == 0 &&
            balances[msg.sender] > _amount
        );

        balances[msg.sender] = balances[msg.sender].sub(_amount);

        vestingMembers[_address].totalSum = _amount;    //total amount
        vestingMembers[_address].start = _start;        //start block
        vestingMembers[_address].end = _end;            //end block
        vestingMembers[_address].usedAmount = 0;        //the amount of paid payments

        VestingMemberAdded(_address, _amount, _start, _end);

        return true;
    }

    function currentPart(address _address) private constant returns (uint256) {
        if (vestingMembers[_address].totalSum == 0 || block.number <= vestingMembers[_address].start) {
            return 0;
        }
        if (block.number >= vestingMembers[_address].end) {
            return vestingMembers[_address].totalSum.sub(vestingMembers[_address].usedAmount);
        }

        return vestingMembers[_address].totalSum
        .mul(block.number - vestingMembers[_address].start)
        .div(vestingMembers[_address].end - vestingMembers[_address].start)
        .sub(vestingMembers[_address].usedAmount);
    }

    function subFromBalance(address _address, uint256 _amount) private returns (uint256) {
        require(_address != address(0));

        if (vestingMembers[_address].totalSum == 0) {
            balances[_address] = balances[_address].sub(_amount);
            return balances[_address];
        }
        uint256 summary = balanceOf(_address);
        require(summary >= _amount);

        if (balances[_address] > _amount) {
            balances[_address] = balances[_address].sub(_amount);
        } else {
            uint256 part = currentPart(_address);
            if (block.number >= vestingMembers[_address].end) {
                vestingMembers[_address].totalSum = 0;          //total amount
                vestingMembers[_address].start = 0;             //start block
                vestingMembers[_address].end = 0;               //end block
                vestingMembers[_address].usedAmount = 0;        //the amount of paid payments
            } else {
                vestingMembers[_address].usedAmount = vestingMembers[_address].usedAmount.add(part);
            }
            balances[_address] = balances[_address].add(part).sub(_amount);
        }

        return balances[_address];
    }

    function balanceOf(address _owner) public constant returns (uint256 balance) {
        if (vestingMembers[_owner].totalSum == 0) {
            return balances[_owner];
        } else {
            return balances[_owner].add(currentPart(_owner));
        }
    }

    function transfer(address _to, uint256 _value) public returns (bool) {
        require(_to != address(0));
        require(_value <= balanceOf(msg.sender));

        subFromBalance(msg.sender, _value);

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

    function transferFrom(address _from, address _to, uint256 _value) public returns (bool) {
        require(_to != address(0));

        uint256 _allowance = allowed[_from][msg.sender];

        subFromBalance(_from, _value);

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

contract DMToken is Vesting {

    string public name = "DMarket Token";
    string public symbol = "DMT";
    uint256 public decimals = 8;

    function DMToken() public {
        hardCap = 15644283100000000;
    }

    function multiTransfer(address[] recipients, uint256[] amounts) public {
        require(recipients.length == amounts.length);
        for (uint i = 0; i < recipients.length; i++) {
            transfer(recipients[i], amounts[i]);
        }
    }

    function multiVesting(
        address[] _address,
        uint256[] _amount,
        uint256[] _start,
        uint256[] _end
    ) public onlyOwner {
        require(
            _address.length == _amount.length &&
            _address.length == _start.length &&
            _address.length == _end.length
        );
        for (uint i = 0; i < _address.length; i++) {
            addVestingMember(_address[i], _amount[i], _start[i], _end[i]);
        }
    }
}

pragma solidity 0.4.18;

import "github.com/OpenZeppelin/zeppelin-solidity/contracts/math/SafeMath.sol";
import "github.com/OpenZeppelin/zeppelin-solidity/contracts/token/ERC20Basic.sol";
import "github.com/OpenZeppelin/zeppelin-solidity/contracts/token/ERC20.sol";
import "github.com/OpenZeppelin/zeppelin-solidity/contracts/ownership/Ownable.sol";

contract ApprovalContract is ERC20 {
    using SafeMath for uint256;

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

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

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

    /**
     * approve should be called when allowed[_spender] == 0. To increment
     * allowed value is better to use this function to avoid 2 calls (and wait until
     * the first transaction is mined)
     * From MonolithDAO Token.sol
     */
    function increaseApproval (address _spender, uint _addedValue) public
    returns (bool success) {
        allowed[msg.sender][_spender] = allowed[msg.sender][_spender].add(_addedValue);
        Approval(msg.sender, _spender, allowed[msg.sender][_spender]);
        return true;
    }

    function decreaseApproval (address _spender, uint _subtractedValue) public
    returns (bool success) {
        uint oldValue = allowed[msg.sender][_spender];
        if (_subtractedValue > oldValue) {
            allowed[msg.sender][_spender] = 0;
        } else {
            allowed[msg.sender][_spender] = oldValue.sub(_subtractedValue);
        }
        Approval(msg.sender, _spender, allowed[msg.sender][_spender]);
        return true;
    }
}

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

    uint256 public hardCap;
    mapping(address => uint256) public balances;

    event Mint(address indexed to, uint256 amount);

    modifier canMint() {
        require(totalSupply == 0);
        _;
    }

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

/**
 * @title Vesting token
 */
contract Vesting is MintableToken {

    event VestingMemberAdded(address indexed _address, uint256 _amount, uint _start, uint _end);

    struct _Vesting {
        uint256 totalSum;     //total amount
        uint256 start;        //start block
        uint256 end;          //end block
        uint256 usedAmount;   //the amount of paid payments
    }

    mapping (address => _Vesting ) public vestingMembers;

    function addVestingMember(
        address _address,
        uint256 _amount,
        uint256 _start,
        uint256 _end
    ) onlyOwner public returns (bool) {
        require(
            _address != address(0) &&
            _amount > 0 &&
            _start < _end &&
            vestingMembers[_address].totalSum == 0 &&
            balances[msg.sender] > _amount
        );

        balances[msg.sender] = balances[msg.sender].sub(_amount);

        vestingMembers[_address].totalSum = _amount;    //total amount
        vestingMembers[_address].start = _start;        //start block
        vestingMembers[_address].end = _end;            //end block
        vestingMembers[_address].usedAmount = 0;        //the amount of paid payments

        VestingMemberAdded(_address, _amount, _start, _end);

        return true;
    }

    function currentPart(address _address) private constant returns (uint256) {
        if (vestingMembers[_address].totalSum == 0 || block.number <= vestingMembers[_address].start) {
            return 0;
        }
        if (block.number >= vestingMembers[_address].end) {
            return vestingMembers[_address].totalSum.sub(vestingMembers[_address].usedAmount);
        }

        return vestingMembers[_address].totalSum
        .mul(block.number - vestingMembers[_address].start)
        .div(vestingMembers[_address].end - vestingMembers[_address].start)
        .sub(vestingMembers[_address].usedAmount);
    }

    function subFromBalance(address _address, uint256 _amount) private returns (uint256) {
        require(_address != address(0));

        if (vestingMembers[_address].totalSum == 0) {
            balances[_address] = balances[_address].sub(_amount);
            return balances[_address];
        }
        uint256 summary = balanceOf(_address);
        require(summary >= _amount);

        if (balances[_address] > _amount) {
            balances[_address] = balances[_address].sub(_amount);
        } else {
            uint256 part = currentPart(_address);
            if (block.number >= vestingMembers[_address].end) {
                vestingMembers[_address].totalSum = 0;          //total amount
                vestingMembers[_address].start = 0;             //start block
                vestingMembers[_address].end = 0;               //end block
                vestingMembers[_address].usedAmount = 0;        //the amount of paid payments
            } else {
                vestingMembers[_address].usedAmount = vestingMembers[_address].usedAmount.add(part);
            }
            balances[_address] = balances[_address].add(part).sub(_amount);
        }

        return balances[_address];
    }

    function balanceOf(address _owner) public constant returns (uint256 balance) {
        if (vestingMembers[_owner].totalSum == 0) {
            return balances[_owner];
        } else {
            return balances[_owner].add(currentPart(_owner));
        }
    }

    function transfer(address _to, uint256 _value) public returns (bool) {
        require(_to != address(0));
        require(_value <= balanceOf(msg.sender));

        subFromBalance(msg.sender, _value);

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

    function transferFrom(address _from, address _to, uint256 _value) public returns (bool) {
        require(_to != address(0));

        uint256 _allowance = allowed[_from][msg.sender];

        subFromBalance(_from, _value);

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

contract RefundContract is Ownable {
    event RefundTokens(address _token, address _refund, uint _value);

    function refundTokens(address _token, address _refund, uint _value) public onlyOwner {
        require(_token != address(this));

        ERC20 token = ERC20(_token);
        token.transfer(_refund, _value);

        RefundTokens(_token, _refund, _value);
    }

}

contract DMToken is Vesting, RefundContract {

    string public name = "DMarket Token";
    string public symbol = "DMC";
    uint256 public decimals = 8;

    function DMToken() public {
        hardCap = 15644283100000000;
    }

    function multiTransfer(address[] recipients, uint256[] amounts) public {
        require(recipients.length == amounts.length);
        for (uint i = 0; i < recipients.length; i++) {
            transfer(recipients[i], amounts[i]);
        }
    }

    function multiVesting(
        address[] _address,
        uint256[] _amount,
        uint256[] _start,
        uint256[] _end
    ) public onlyOwner {
        require(
            _address.length == _amount.length &&
            _address.length == _start.length &&
            _address.length == _end.length
        );
        for (uint i = 0; i < _address.length; i++) {
            addVestingMember(_address[i], _amount[i], _start[i], _end[i]);
        }
    }
}


Remove obsolete comment

Remove obsolete comment

pragma solidity ^0.8.4;

import "@openzeppelin/contracts/token/ERC1155/IERC1155.sol";

uint96 constant CANNOT_UNWRAP = 1;
uint96 constant CANNOT_BURN_FUSES = 2;
uint96 constant CANNOT_TRANSFER = 4;
uint96 constant CANNOT_SET_RESOLVER = 8;
uint96 constant CANNOT_SET_TTL = 16;
uint96 constant CANNOT_CREATE_SUBDOMAIN = 32;
uint96 constant CANNOT_REPLACE_SUBDOMAIN = 64;
uint96 constant CAN_DO_EVERYTHING = 0;

interface INFTFuseWrapper is IERC1155 {
    event Wrap(
        bytes32 indexed parentNode,
        string indexed label,
        address owner,
        uint96 fuses
    );

    event WrapETH2LD(bytes32 indexed labelhash, address owner, uint96 fuses);

    event Unwrap(
        bytes32 indexed parentNode,
        bytes32 indexed labelhash,
        address owner
    );

    event UnwrapETH2LD(
        bytes32 indexed labelhash,
        address registrant,
        address controller
    );

    function wrap(
        bytes32 node,
        string calldata label,
        address wrappedOwner,
        uint96 _fuses
    ) external;

    function wrapETH2LD(
        string calldata label,
        address wrappedOwner,
        uint96 _fuses
    ) external;

    function unwrap(
        bytes32 node,
        bytes32 label,
        address owner
    ) external;

    function setSubnodeRecordAndWrap(
        bytes32 node,
        string calldata label,
        address owner,
        address resolver,
        uint64 ttl,
        uint96 _fuses
    ) external returns (bytes32);

    function setSubnodeOwner(
        bytes32 node,
        bytes32 label,
        address owner
    ) external returns (bytes32);

    function setSubnodeOwnerAndWrap(
        bytes32 node,
        string calldata label,
        address newOwner,
        uint96 _fuses
    ) external returns (bytes32);

    function isOwnerOrApproved(bytes32 node, address addr)
        external

        returns (bool);

    function setResolver(bytes32 node, address resolver) external;

    function setTTL(bytes32 node, uint64 ttl) external;
}

// events for wrapping names, unwrap, setFuses
// Then log the event. parentNode, label (string), fuses, owner


Tweak timing.

Tweak timing.

pragma solidity ^0.4.8;

contract PayForPrivKey {
	// Begin config.
	uint constant min_blocks = 7;
	// End config.

	bool debug = false;
	address public pub_key;
	address public owner;
	uint deposit_amount;
	struct CommitInfo
	{
		bytes32 solution_hash;
		uint block_height;
		bool is_valid;
    }

    uint public commit_no;
	mapping(uint => CommitInfo) public commitments;

	// Solution.
	struct Solution
	{
		bytes32 h1;
		uint8 v1;
		bytes32 r1;
		bytes32 s1;
		bytes32 h2;
		bytes32 s2;
		bool is_valid;
	}
	Solution public solution;

	uint start_chain_height;

	function PayForPrivKey(address _pub_key) payable
	{
		pub_key = _pub_key;
		owner = msg.sender; // Not used.
		deposit_amount = msg.value;
		start_chain_height = block.number;
	}

	function refund() public payable
	{
		// Expired - allow contract to be destroyed.
		if(block.number - start_chain_height >= min_blocks * 20 || debug)
		{
			if(msg.sender == owner)
			{
				suicide(owner);
			}
		}
	}

	function get_solution() public returns (bytes32, uint8, bytes32, bytes32, bytes32, bytes32, bool){
		return (solution.h1, solution.v1, solution.r1, solution.s1, solution.h2, solution.s2, solution.is_valid);
	}

	function get_commit_no() public returns (uint){
		return commit_no;
	}

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

	function CommitSolutionHash(bytes32 _solution_hash) public returns (uint)
	{
		// Don't allow new submissions after a certain timeout.
		if(block.number - start_chain_height >= min_blocks * 10 && !debug)
		{
			throw;
		}

		commit_no = commit_no++;
		commitments[commit_no] = CommitInfo(_solution_hash, block.number, true);

		return commit_no;
	}

	function ProvePrivKey(bytes32 h1, uint8 v1, bytes32 r1, bytes32 s1, bytes32 h2, bytes32 s2, address destination, uint index) public payable returns(address)
	{
		// Don't allow new submissions after a certain timeout.
		if(block.number - start_chain_height >= min_blocks * 10 && !debug)
		{
			throw;
		}

	    // Check this is a commitment first.
	    bytes32 solution_hash = sha3(h1, v1, r1, s1, h2, s2, toBytes(destination));
	    if(commitments[index].solution_hash != solution_hash)
	    {
			throw;
	    }

	    // Now this is important -- check enough block have passed since the commitment was made.
	    // This is necessary for security reasons (race conditions from malicious observers)
	    if(block.number - commitments[index].block_height < min_blocks && !debug)
	    {
	        throw;
	    }

		// Sig values must be unique.
		if(s1 == s2)
		{
			throw;
		}

		// Hash values must be unique.
		// Well they should be if s* is but we'll check anyway.
		if(h1 == h2)
		{
			throw;
		}

		// Recover the first public key and check it.
		address pub_key_1 = ecrecover(h1, v1, r1, s1);
		if(pub_key_1 == 0x0)
		{
			throw;
		}

		// Recover the second public key and check it.
		address pub_key_2 = ecrecover(h2, v1, r1, s2);
		if(pub_key_2 == 0x0)
		{
			throw;
		}

		// Check recovered public key is for the target key.
		if(pub_key_1 == pub_key_2 && pub_key_2 == pub_key)
		{
			// Send the Ether to their provided address.
			if(!destination.send(deposit_amount))
			{
			    throw;
			}

			// Save solution.
			solution.v1 = v1;
			solution.r1 = r1;
			solution.h1 = h1;
			solution.h2 = h2;
			solution.s1 = s1;
			solution.s2 = s2;
			solution.is_valid = true;

			return pub_key_1;
		}
		else
		{
			throw;
		}
	}

}

pragma solidity ^0.4.8;

contract PayForPrivKey {
	// Begin config.
	uint constant min_blocks = 7;
	// End config.

	bool debug = false;
	address public pub_key;
	address public owner;
	uint deposit_amount;
	struct CommitInfo
	{
		bytes32 solution_hash;
		uint block_height;
		bool is_valid;
    }

    uint public commit_no;
	mapping(uint => CommitInfo) public commitments;

	// Solution.
	struct Solution
	{
		bytes32 h1;
		uint8 v1;
		bytes32 r1;
		bytes32 s1;
		bytes32 h2;
		bytes32 s2;
		bool is_valid;
	}
	Solution public solution;

	uint start_chain_height;

	function PayForPrivKey(address _pub_key) payable
	{
		pub_key = _pub_key;
		owner = msg.sender; // Not used.
		deposit_amount = msg.value;
		start_chain_height = block.number;
	}

	function refund() public payable
	{
		// Expired - allow contract to be destroyed.
		if(block.number - start_chain_height >= min_blocks * 4 || debug)
		{
			if(msg.sender == owner)
			{
				suicide(owner);
			}
		}
	}

	function get_solution() public returns (bytes32, uint8, bytes32, bytes32, bytes32, bytes32, bool){
		return (solution.h1, solution.v1, solution.r1, solution.s1, solution.h2, solution.s2, solution.is_valid);
	}

	function get_commit_no() public returns (uint){
		return commit_no;
	}

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

	function CommitSolutionHash(bytes32 _solution_hash) public returns (uint)
	{
		// Don't allow new submissions after a certain timeout.
		if(block.number - start_chain_height >= min_blocks * 2 && !debug)
		{
			throw;
		}

		commit_no = commit_no++;
		commitments[commit_no] = CommitInfo(_solution_hash, block.number, true);

		return commit_no;
	}

	function ProvePrivKey(bytes32 h1, uint8 v1, bytes32 r1, bytes32 s1, bytes32 h2, bytes32 s2, address destination, uint index) public payable returns(address)
	{
		// Don't allow new submissions after a certain timeout.
		if(block.number - start_chain_height >= min_blocks * 2 && !debug)
		{
			throw;
		}

	    // Check this is a commitment first.
	    bytes32 solution_hash = sha3(h1, v1, r1, s1, h2, s2, toBytes(destination));
	    if(commitments[index].solution_hash != solution_hash)
	    {
			throw;
	    }

	    // Now this is important -- check enough block have passed since the commitment was made.
	    // This is necessary for security reasons (race conditions from malicious observers)
	    if(block.number - commitments[index].block_height < min_blocks && !debug)
	    {
	        throw;
	    }

		// Sig values must be unique.
		if(s1 == s2)
		{
			throw;
		}

		// Hash values must be unique.
		// Well they should be if s* is but we'll check anyway.
		if(h1 == h2)
		{
			throw;
		}

		// Recover the first public key and check it.
		address pub_key_1 = ecrecover(h1, v1, r1, s1);
		if(pub_key_1 == 0x0)
		{
			throw;
		}

		// Recover the second public key and check it.
		address pub_key_2 = ecrecover(h2, v1, r1, s2);
		if(pub_key_2 == 0x0)
		{
			throw;
		}

		// Check recovered public key is for the target key.
		if(pub_key_1 == pub_key_2 && pub_key_2 == pub_key)
		{
			// Send the Ether to their provided address.
			if(!destination.send(deposit_amount))
			{
			    throw;
			}

			// Save solution.
			solution.v1 = v1;
			solution.r1 = r1;
			solution.h1 = h1;
			solution.h2 = h2;
			solution.s1 = s1;
			solution.s2 = s2;
			solution.is_valid = true;

			return pub_key_1;
		}
		else
		{
			throw;
		}
	}

}


Added replay attack notice to SignatureBouncer. (#1434)

pragma solidity ^0.4.24;

import "../access/roles/SignerRole.sol";
import "../cryptography/ECDSA.sol";

/**
 * @title SignatureBouncer
 * @author PhABC, Shrugs and aflesher
 * @dev SignatureBouncer allows users to submit a signature as a permission to
 * do an action.
 * If the signature is from one of the authorized signer addresses, the
 * signature is valid.
 * Note that SignatureBouncer offers no protection against replay attacks, users
 * must add this themselves!
 *
 * Signer addresses can be individual servers signing grants or different
 * users within a decentralized club that have permission to invite other
 * members. This technique is useful for whitelists and airdrops; instead of
 * putting all valid addresses on-chain, simply sign a grant of the form
 * keccak256(abi.encodePacked(`:contractAddress` + `:granteeAddress`)) using a
 * valid signer address.
 * Then restrict access to your crowdsale/whitelist/airdrop using the
 * `onlyValidSignature` modifier (or implement your own using _isValidSignature).
 * In addition to `onlyValidSignature`, `onlyValidSignatureAndMethod` and
 * `onlyValidSignatureAndData` can be used to restrict access to only a given
 * method or a given method with given parameters respectively.
 * See the tests in SignatureBouncer.test.js for specific usage examples.
 *
 * @notice A method that uses the `onlyValidSignatureAndData` modifier must make
 * the _signature parameter the "last" parameter. You cannot sign a message that
 * has its own signature in it so the last 128 bytes of msg.data (which
 * represents the length of the _signature data and the _signaature data itself)
 * is ignored when validating. Also non fixed sized parameters make constructing
 * the data in the signature much more complex.
 * See https://ethereum.stackexchange.com/a/50616 for more details.
 */
contract SignatureBouncer is SignerRole {
  using ECDSA for bytes32;

  // Function selectors are 4 bytes long, as documented in
  // https://solidity.readthedocs.io/en/v0.4.24/abi-spec.html#function-selector
  uint256 private constant _METHOD_ID_SIZE = 4;
  // Signature size is 65 bytes (tightly packed v + r + s), but gets padded to 96 bytes
  uint256 private constant _SIGNATURE_SIZE = 96;

  constructor() internal {}

  /**
   * @dev requires that a valid signature of a signer was provided
   */
  modifier onlyValidSignature(bytes signature)
  {
    require(_isValidSignature(msg.sender, signature));
    _;
  }

  /**
   * @dev requires that a valid signature with a specifed method of a signer was provided
   */
  modifier onlyValidSignatureAndMethod(bytes signature)
  {
    require(_isValidSignatureAndMethod(msg.sender, signature));
    _;
  }

  /**
   * @dev requires that a valid signature with a specifed method and params of a signer was provided
   */
  modifier onlyValidSignatureAndData(bytes signature)
  {
    require(_isValidSignatureAndData(msg.sender, signature));
    _;
  }

  /**
   * @dev is the signature of `this + sender` from a signer?
   * @return bool
   */
  function _isValidSignature(address account, bytes signature)
    internal
    view
    returns (bool)
  {
    return _isValidDataHash(
      keccak256(abi.encodePacked(address(this), account)),
      signature
    );
  }

  /**
   * @dev is the signature of `this + sender + methodId` from a signer?
   * @return bool
   */
  function _isValidSignatureAndMethod(address account, bytes signature)
    internal
    view
    returns (bool)
  {
    bytes memory data = new bytes(_METHOD_ID_SIZE);
    for (uint i = 0; i < data.length; i++) {
      data[i] = msg.data[i];
    }
    return _isValidDataHash(
      keccak256(abi.encodePacked(address(this), account, data)),
      signature
    );
  }

  /**
    * @dev is the signature of `this + sender + methodId + params(s)` from a signer?
    * @notice the signature parameter of the method being validated must be the "last" parameter
    * @return bool
    */
  function _isValidSignatureAndData(address account, bytes signature)
    internal
    view
    returns (bool)
  {
    require(msg.data.length > _SIGNATURE_SIZE);
    bytes memory data = new bytes(msg.data.length - _SIGNATURE_SIZE);
    for (uint i = 0; i < data.length; i++) {
      data[i] = msg.data[i];
    }
    return _isValidDataHash(
      keccak256(abi.encodePacked(address(this), account, data)),
      signature
    );
  }

  /**
   * @dev internal function to convert a hash to an eth signed message
   * and then recover the signature and check it against the signer role
   * @return bool
   */
  function _isValidDataHash(bytes32 hash, bytes signature)
    internal
    view
    returns (bool)
  {
    address signer = hash
      .toEthSignedMessageHash()
      .recover(signature);

    return signer != address(0) && isSigner(signer);
  }
}

pragma solidity ^0.4.24;

import "../access/roles/SignerRole.sol";
import "../cryptography/ECDSA.sol";

/**
 * @title SignatureBouncer
 * @author PhABC, Shrugs and aflesher
 * @dev SignatureBouncer allows users to submit a signature as a permission to do an action.
 * If the signature is from one of the authorized signer addresses, the signature
 * is valid.
 * Signer addresses can be individual servers signing grants or different
 * users within a decentralized club that have permission to invite other members.
 * This technique is useful for whitelists and airdrops; instead of putting all
 * valid addresses on-chain, simply sign a grant of the form
 * keccak256(abi.encodePacked(`:contractAddress` + `:granteeAddress`)) using a valid signer address.
 * Then restrict access to your crowdsale/whitelist/airdrop using the
 * `onlyValidSignature` modifier (or implement your own using _isValidSignature).
 * In addition to `onlyValidSignature`, `onlyValidSignatureAndMethod` and
 * `onlyValidSignatureAndData` can be used to restrict access to only a given method
 * or a given method with given parameters respectively.
 * See the tests in SignatureBouncer.test.js for specific usage examples.
 * @notice A method that uses the `onlyValidSignatureAndData` modifier must make the _signature
 * parameter the "last" parameter. You cannot sign a message that has its own
 * signature in it so the last 128 bytes of msg.data (which represents the
 * length of the _signature data and the _signaature data itself) is ignored when validating.
 * Also non fixed sized parameters make constructing the data in the signature
 * much more complex. See https://ethereum.stackexchange.com/a/50616 for more details.
 */
contract SignatureBouncer is SignerRole {
  using ECDSA for bytes32;

  // Function selectors are 4 bytes long, as documented in
  // https://solidity.readthedocs.io/en/v0.4.24/abi-spec.html#function-selector
  uint256 private constant _METHOD_ID_SIZE = 4;
  // Signature size is 65 bytes (tightly packed v + r + s), but gets padded to 96 bytes
  uint256 private constant _SIGNATURE_SIZE = 96;

  constructor() internal {}

  /**
   * @dev requires that a valid signature of a signer was provided
   */
  modifier onlyValidSignature(bytes signature)
  {
    require(_isValidSignature(msg.sender, signature));
    _;
  }

  /**
   * @dev requires that a valid signature with a specifed method of a signer was provided
   */
  modifier onlyValidSignatureAndMethod(bytes signature)
  {
    require(_isValidSignatureAndMethod(msg.sender, signature));
    _;
  }

  /**
   * @dev requires that a valid signature with a specifed method and params of a signer was provided
   */
  modifier onlyValidSignatureAndData(bytes signature)
  {
    require(_isValidSignatureAndData(msg.sender, signature));
    _;
  }

  /**
   * @dev is the signature of `this + sender` from a signer?
   * @return bool
   */
  function _isValidSignature(address account, bytes signature)
    internal
    view
    returns (bool)
  {
    return _isValidDataHash(
      keccak256(abi.encodePacked(address(this), account)),
      signature
    );
  }

  /**
   * @dev is the signature of `this + sender + methodId` from a signer?
   * @return bool
   */
  function _isValidSignatureAndMethod(address account, bytes signature)
    internal
    view
    returns (bool)
  {
    bytes memory data = new bytes(_METHOD_ID_SIZE);
    for (uint i = 0; i < data.length; i++) {
      data[i] = msg.data[i];
    }
    return _isValidDataHash(
      keccak256(abi.encodePacked(address(this), account, data)),
      signature
    );
  }

  /**
    * @dev is the signature of `this + sender + methodId + params(s)` from a signer?
    * @notice the signature parameter of the method being validated must be the "last" parameter
    * @return bool
    */
  function _isValidSignatureAndData(address account, bytes signature)
    internal
    view
    returns (bool)
  {
    require(msg.data.length > _SIGNATURE_SIZE);
    bytes memory data = new bytes(msg.data.length - _SIGNATURE_SIZE);
    for (uint i = 0; i < data.length; i++) {
      data[i] = msg.data[i];
    }
    return _isValidDataHash(
      keccak256(abi.encodePacked(address(this), account, data)),
      signature
    );
  }

  /**
   * @dev internal function to convert a hash to an eth signed message
   * and then recover the signature and check it against the signer role
   * @return bool
   */
  function _isValidDataHash(bytes32 hash, bytes signature)
    internal
    view
    returns (bool)
  {
    address signer = hash
      .toEthSignedMessageHash()
      .recover(signature);

    return signer != address(0) && isSigner(signer);
  }
}


Add blind-auction.sol

Add blind-auction.sol

pragma solidity ^0.4.11;

contract SimpleAuction {
  // Parameters of the auction. Times are either
  // absolute unix timestamps (seconds since 1970-01-01)
  // or time periods in seconds.
  address public beneficiary;
  uint public auctionStart;
  uint public biddingTime;

  // Current state of the auction.
  address public highestBidder;
  uint public highestBid;

  // Allowed withdrawals of previous bids
  mapping(address => uint) pendingReturns;

  // Set to true at the end, disallows any change
  bool ended;

  // Events that will be fired on changes.
  event HighestBidIncreased(address bidder, uint amount);
  event AuctionEnded(address winner, uint amount);

  // The following is a so-called natspec comment,
  // recognizable by the three slashes.
  // It will be shown when the user is asked to
  // confirm a transaction.

  /// Create a simple auction with `_biddingTime`
  /// seconds bidding time on behalf of the
  /// beneficiary address `_beneficiary`.
  function SimpleAuction(
                         uint _biddingTime,
                                 address _beneficiary
                         ) {
    beneficiary = _beneficiary;
    auctionStart = now;
    biddingTime = _biddingTime;
  }

  /// Bid on the auction with the value sent
  /// together with this transaction.
  /// The value will only be refunded if the
  /// auction is not won.
  function bid() payable {
    // No arguments are necessary, all
    // information is already part of
    // the transaction. The keyword payable
    // is required for the function to
    // be able to receive Ether.

    // Revert the call if the bidding
    // period is over.
    require(now <= (auctionStart + biddingTime));

    // If the bid is not higher, send the
    // money back.
    require(msg.value > highestBid);

    if (highestBidder != 0) {
      // Sending back the money by simply using
      // highestBidder.send(highestBid) is a security risk
      // because it could execute an untrusted contract.
      // It is always safer to let the recipients
      // withdraw their money themselves.
      pendingReturns[highestBidder] += highestBid;
    }
    highestBidder = msg.sender;
    highestBid = msg.value;
    HighestBidIncreased(msg.sender, msg.value);
  }

  /// Withdraw a bid that was overbid.
  function withdraw() returns (bool) {
    uint amount = pendingReturns[msg.sender];
    if (amount > 0) {
      // It is important to set this to zero because the recipient
      // can call this function again as part of the receiving call
      // before `send` returns.
      pendingReturns[msg.sender] = 0;

      if (!msg.sender.send(amount)) {
        // No need to call throw here, just reset the amount owing
        pendingReturns[msg.sender] = amount;
        return false;
      }
    }
    return true;
  }

  /// End the auction and send the highest bid
  /// to the beneficiary.
  function auctionEnd() {
    // It is a good guideline to structure functions that interact
    // with other contracts (i.e. they call functions or send Ether)
    // into three phases:
    // 1. checking conditions
    // 2. performing actions (potentially changing conditions)
    // 3. interacting with other contracts
    // If these phases are mixed up, the other contract could call
    // back into the current contract and modify the state or cause
    // effects (ether payout) to be performed multiple times.
    // If functions called internally include interaction with external
    // contracts, they also have to be considered interaction with
    // external contracts.

    // 1. Conditions
    require(now >= (auctionStart + biddingTime)); // auction did not yet end
    require(!ended); // this function has already been called

    // 2. Effects
    ended = true;
    AuctionEnded(highestBidder, highestBid);

    // 3. Interaction
    beneficiary.transfer(highestBid);
  }
}

error: pathspec 'examples/solidity.readthedocs.io/solidity-by-example/blind-auction.sol' did not match any file(s) known to git


Continued to work on the list of consenttemplates

pragma solidity ^0.4.11;

/*
 * This file contains a set of contracts used to handle consents between a company
 * and a person.
 *
 * Copyright (c) 2017, Tomas Stenlund, All rights reserved
 */

/*
 * This is the contract that handles consent templates for a specific purpouse. It is used
 * when a person or entity wants to get a consent from another user. The consent is then
 * generated from this template.
 *
 * It basically provides a textual description of the consent.
 *
 * Copyright (c) 2017, Tomas Stenlund, All rights reserved
 *
 */
contract ConsentTemplate {

  address private owner;        /* The owner of the template */
  string  private purpouse;     /* What purpouse the template is for */
  uint16  private version;      /* Version of the purpouse, i.e. if the text or title changes for the same purpouse */
  string  private title;        /* The title of the consent */
  string  private text;         /* The text that describes the purpouse of the consent */
  string  private languageCountry;       /* The language and country the consent template that it is valid for
					  *
					  * Standard country-language code according to ISO 639 and ISO 3166-1 alpha 2
					  * separated by a dash, so for swedish in Sweden it is "sv-SE" */

  /* Creates the contract and set the values of the contract. */
  function ConsentTemplate (string _purpouse, uint16 _version, string _title, string _text, string _languageCountry) public
  {
    owner = msg.sender;
    purpouse = _purpouse;
    version = _version;
    title = _title;
    text = _text;
    languageCountry = _languageCountry;
  }

  /* Getters for the contract */
  function getVersion () constant returns (uint16)
  {
    return version;
  }

  function getTitle () constant returns (string)
  {
    return title;
  }

  function getText () constant returns (string)
  {
    return text;
  }

}

/*
 * This is the contract that handles consents for a specific purpouse given by a
 * user (giver) to another user (owner).
 *
 * It basically provides a textual description  that is either accepted or denied by a user.
 *
 * Copyright (c) 2017, Tomas Stenlund, All rights reserved
 *
 */
contract Consent {

    /* Enumeration for the state of the consent */
  enum Status {denied,    /* The giver has denied the consent */
	       accepted,  /* The giver has accepted the consent */
	       requested, /* The company has requested a consent, user has not yet responded */
	       cancelled  /* The company has cancelled the consent because he no longer needs it */
  }

  /* State variables for the contract */
  address private owner;  /* Who issues to consent form */
  address private giver;  /* Who gives the consent, address to the account. */
  Status  private status; /* The status of the consent */
  address private consentTemplate; /* The template this consent is based on */

  /* Event to signal that the status has changed */
  event ConsentStatusChanged (address indexed owner, address indexed giver, address consent, Status status);

  /* This function is executed at initialization and sets the owner and the giver of the consent */
  /* as well as what it contains */
  function Consent(address _giver, address _consentTemplate) public
  {
    giver = _giver;
    owner = msg.sender;
    consentTemplate = _consentTemplate;
    status = Status.requested;
  }

  /* Sets the status of the consent, this can only be done by the giver. Should have a modifier for that. */
  function setStatus(Status _status)
  {
    status = _status;
    ConsentStatusChanged (owner, giver, this, _status);
  }

  /* Cancels a consent, this can only be done by the company who created the consent. Should have a modifier for that. */
  function cancelConsent ()
  {
    status = Status.cancelled;
    ConsentStatusChanged (owner, giver, this, Status.cancelled);
  }

  /* Returns the status of the consent */
  function getStatus() constant returns (Status)
  {
    return status;
  }

  /* Returns the consent template that this consent is based on */
  function getTemplate() constant returns (ConsentTemplate)
  {
    return ConsentTemplate(consentTemplate);
  }

  /* Function to recover the funds on the contract */
  function kill() { if (msg.sender == owner) selfdestruct(owner); }
}

/*
 * This a list of consents that are offered to a specific account.
 *
 * This contains a list of consents that a specific user has been
 * offered. Regardless if it is deined, approved or has no decision.
 *
 * Copyright (c) 2017, Tomas Stenlund, All rights reserved
 *
 */
contract ConsentFile {

  /* The owner of the file */
  address private owner;

  /* The list of all consents */
  address[] private listOfConsents;

  /* Events that are sent when things happen */
  event ConsentFileConsentAdded (address indexed user, address consent);

  /* The constructor of the file. Also attaches it to an owner */
  function ConsentFile (address _owner)
  {
    owner = _owner;
  }

  /* Adds a new consent to the file */
  function addConsent (address _consent)
  {
    listOfConsents.push (_consent);
    ConsentFileConsentAdded (owner,  _consent);
  }

  /* Retrieve a list of all consents in the file */
  function getListOfConsents () constant returns (address[])
  {
    return listOfConsents;
  }

  /* Retrieves the owner */
  function getOwner () constant returns (address)
  {
    return owner;
  }

}

/*
 * This is the consent factory contract that handles consents and version of
 * consents.
 *
 * It basically provides an interface to be able to create consents based on
 * a specific purpouse for a specific user. And always using the latest version
 * and always puts newly generated consents into a persons consent file.
 *
 * Copyright (c) 2017, Tomas Stenlund, All rights reserved
 *
 */
contract ConsentFactory {

  /* Enumeration for errors */
  enum Error {no_such_template /* If no such template exists for the purpouse, language and country */
  }

  /* The owner of this contract */
  address private owner;  /* Who owns this Consent Facotory, this is a company */

  /* Contains a map from language and country according to ISO 639 and ISO 3166-1 alpha 2 separated by a dash to
   * consent template. For example swedish in Sweden is written sv-SE */
  struct ConsentLanguageCountry {
    bool exist;                                                 /* If there exists any consents, true if yes, false otherwsie */
    mapping (string => ConsentTemplate[]) consentTemplates;     /* An array of templates keyed to language and country */
    string[] languagesAndCountries;                               /* An array containing all languages and countries in the mapping */
  }

  /* A dynamic array that contains all purpouses that this factory handles */
  string[] private purpouses;

  /* Contains a map from purpouse to language and country mapping */
  mapping (string => ConsentLanguageCountry) private consentPurpouses;

  /* Events generated when the consent has been created */
  event ConsentFactoryConsentCreatedEvent(address indexed owner, address indexed user, address indexed file, address consent);
  event ConsentFactoryFileCreatedEvent(address indexed owner, address indexed user, address file);
  event ConsentFactoryFailedEvent(address indexed owner, address indexed user, Error error);
  event ConsentFactoryTemplateAdded (address indexed owner, address indexed factory, address template);

  /* Constructor for the consent factory */
  function ConsentFactory() public
  {
    owner = msg.sender;
  }

  /* Adds a consent template to the factory to be used for consent generation. */
  function addConsentTemplate (string _purpouse, uint16 _version, string _title, string _text, string _languageCountry)
  {
    /* Add the template last, i.e. the newest template, for the specific language, country and purpouse */
    if (!consentPurpouses[_purpouse].exist)
      purpouses.push (_purpouse);
    consentPurpouses[_purpouse].exist = true;
    ConsentTemplate consentTemplate = new ConsentTemplate (_purpouse, _version, _title, _text, _languageCountry);
    if (consentPurpouses[_purpouse].consentTemplates[_languageCountry].length==0)
      consentPurpouses[_purpouse].languagesAndCountries.push (_languageCountry);
    consentPurpouses[_purpouse].consentTemplates[_languageCountry].push (consentTemplate);
    ConsentFactoryTemplateAdded (owner, this, consentTemplate);
  }

  function getNumberOfPurpouses() constant returns (uint length)
  {
    return purpouses.length;
  }

  function getNumberOfLanguagesAndCountries(uint index) constant returns (uint length)
  {
    if (consentPurpouses[purpouses[index]].exist) {
      return  consentPurpouses[purpouses[index]].languagesAndCountries.length;
    } else {
      return 0;
    }
  }

  function getConsentTemplates(uint purpouseIndex, uint languageAndCountryIndex) constant returns (ConsentTemplate[])
  {
    ConsentTemplate[] memory ctl;
    if (consentPurpouses[purpouses[purpouseIndex]].exist)
      ctl =  consentPurpouses[purpouses[purpouseIndex]].consentTemplates[consentPurpouses[purpouses[purpouseIndex]].languagesAndCountries[languageAndCountryIndex]];
    return ctl;
  }

  /* Create a file that holds a users all consents
   *
   * This is the file that holds all consents regardless of their state.
   */
  function createConsentFile (address _user)
  {
    address file = new ConsentFile (_user);
    ConsentFactoryFileCreatedEvent(owner, _user, file);
  }

  /* Create a consent for a specific purpouse of the latest version, language and country.
   *
   * Country and Purpouse must exist otherwise it will fail, if language is not there it will
   * default to countrys default language if it exists otherwise it will fail. It adds
   * the consent to the users file as well.
   */
  function createConsent (address _file, string _purpouse, string _languageCountry)
  {
    ConsentFile cf = ConsentFile (_file);
    ConsentTemplate ct = getTemplate (_purpouse, _languageCountry);
    if (ct != address(0)) {

      /* We got a template so generate the consent and put it into the consent file */
      Consent consent = new Consent (cf.getOwner(), ct);
      ConsentFile(_file).addConsent (consent);
      ConsentFactoryConsentCreatedEvent(owner, cf.getOwner(), _file, consent);

    } else {

      ConsentFactoryFailedEvent(owner, cf.getOwner(), Error.no_such_template);

    }
  }

  /* This function checks to see that there is a consent to be generated */
  function hasConsent (string _purpouse, string _languageCountry) constant returns (bool)
  {
    ConsentTemplate ct = getTemplate (_purpouse, _languageCountry);
    return (ct != address(0));
  }

  /* This function tests wether a consent for a specific purpouse exists or not */
  function getTemplate (string _purpouse, string _languageCountry) constant internal returns (ConsentTemplate)
  {
    ConsentTemplate ct; /* Holds the found template */
    uint256 len; /* Holds the length of the template array so we can take the last one */

    /* Get the consents for a specific purpouse */
    ConsentLanguageCountry clc = consentPurpouses[_purpouse];
    if (clc.exist) {

      /* Get the specific consent for the language and country */
      len = clc.consentTemplates[_languageCountry].length;
      if (len == 0) {

	/* Fallback here is to only go for the default language of the country */
	/* So we need to strip the language from the country */
	bytes memory b = bytes (_languageCountry);
	if (b.length==5) {
	  if (b[2] == 45) {
	    bytes memory c = new bytes(2);

	    /* Get the country */
	    c[0] = b[3];
	    c[1] = b[4];
	    len = clc.consentTemplates[string(c)].length;

	    /* Get the last consent */
	    if (len > 0)
	      ct = clc.consentTemplates[string(c)][len-1];
	  }
	}
      } else {
	ct = clc.consentTemplates[_languageCountry][len-1];
      }
    }

    return ct;
  }

  /* Function to recover the funds on the contract */
  function kill() { if (msg.sender == owner) selfdestruct(owner); }
}

/*
 * END
 */

pragma solidity ^0.4.11;

/*
 * This file contains a set of contracts used to handle consents between a company
 * and a person.
 *
 * Copyright (c) 2017, Tomas Stenlund, All rights reserved
 */

/*
 * This is the contract that handles consent templates for a specific purpouse. It is used
 * when a person or entity wants to get a consent from another user. The consent is then
 * generated from this template.
 *
 * It basically provides a textual description of the consent.
 *
 * Copyright (c) 2017, Tomas Stenlund, All rights reserved
 *
 */
contract ConsentTemplate {

  address private owner;        /* The owner of the template */
  string  private purpouse;     /* What purpouse the template is for */
  uint16  private version;      /* Version of the purpouse, i.e. if the text or title changes for the same purpouse */
  string  private title;        /* The title of the consent */
  string  private text;         /* The text that describes the purpouse of the consent */
  string  private languageCountry;       /* The language and country the consent template is valid for
					  *
					  * Standard country-language code according to ISO 639 and ISO 3166-1 alpha 2
					  * separated by a dash, so for swedish in Sweden it is sv-SE */

  /* Creates the contract and set the values of the contract. */
  function ConsentTemplate (string _purpouse, uint16 _version, string _title, string _text, string _languageCountry) public
  {
    owner = msg.sender;
    purpouse = _purpouse;
    version = _version;
    title = _title;
    text = _text;
    languageCountry = _languageCountry;
  }

  /* Getters for the contract */
  function getVersion () constant returns (uint16)
  {
    return version;
  }

  function getTitle () constant returns (string)
  {
    return title;
  }

  function getText () constant returns (string)
  {
    return text;
  }

}

/*
 * This is the contract that handles consents for a specific purpouse given by a
 * user (giver) to another user (owner).
 *
 * It basically provides a textual description  that is either accepted or denied by a user.
 *
 * Copyright (c) 2017, Tomas Stenlund, All rights reserved
 *
 */
contract Consent {

    /* Enumeration for the state of the consent */
  enum Status {denied,    /* The giver has denied the consent */
	       accepted,  /* The giver has accepted the consent */
	       requested, /* The company has requested a consent, user has not yet responded */
	       cancelled  /* The company has cancelled the consent because he no longer needs it */
  }

  /* State variables for the contract */
  address private owner;  /* Who issues to consent form */
  address private giver;  /* Who gives the consent, address to the account. */
  Status  private status; /* The status of the consent */
  address private consentTemplate; /* The template this consent is based on */

  /* Event to signal that the status has changed */
  event ConsentStatusChanged (address indexed owner, address indexed giver, address consent, Status status);

  /* This function is executed at initialization and sets the owner and the giver of the consent */
  /* as well as what it contains */
  function Consent(address _giver, address _consentTemplate) public
  {
    giver = _giver;
    owner = msg.sender;
    consentTemplate = _consentTemplate;
    status = Status.requested;
  }

  /* Sets the status of the consent, this can only be done by the giver. Should have a modifier for that. */
  function setStatus(Status _status)
  {
    status = _status;
    ConsentStatusChanged (owner, giver, this, _status);
  }

  /* Cancels a consent, this can only be done by the company who created the consent. Should have a modifier for that. */
  function cancelConsent ()
  {
    status = Status.cancelled;
    ConsentStatusChanged (owner, giver, this, Status.cancelled);
  }

  /* Returns the status of the consent */
  function getStatus() constant returns (Status)
  {
    return status;
  }

  /* Returns the consent template that this consent is based on */
  function getTemplate() constant returns (ConsentTemplate)
  {
    return ConsentTemplate(consentTemplate);
  }

  /* Function to recover the funds on the contract */
  function kill() { if (msg.sender == owner) selfdestruct(owner); }
}

/*
 * This a list of consents that are offered to a specific account.
 *
 * This contains a list of consents that a specific user has been
 * offered. Regardless if it is deined, approved or has no decision.
 *
 * Copyright (c) 2017, Tomas Stenlund, All rights reserved
 *
 */
contract ConsentFile {

  /* The owner of the file */
  address private owner;

  /* The list of all consents */
  address[] private listOfConsents;

  /* Events that are sent when things happen */
  event ConsentFileConsentAdded (address indexed user, address consent);

  /* The constructor of the file. Also attaches it to an owner */
  function ConsentFile (address _owner)
  {
    owner = _owner;
  }

  /* Adds a new consent to the file */
  function addConsent (address _consent)
  {
    listOfConsents.push (_consent);
    ConsentFileConsentAdded (owner,  _consent);
  }

  /* Retrieve a list of all consents in the file */
  function getListOfConsents () constant returns (address[])
  {
    return listOfConsents;
  }

  /* Retrieves the owner */
  function getOwner () constant returns (address)
  {
    return owner;
  }

}

/*
 * This is the consent factory contract that handles consents and version of
 * consents.
 *
 * It basically provides an interface to be able to create consents based on
 * a specific purpouse for a specific user. And always using the latest version
 * and always puts newly generated consents into a persons consent file.
 *
 * Copyright (c) 2017, Tomas Stenlund, All rights reserved
 *
 */
contract ConsentFactory {

  /* Enumeration for errors */
  enum Error {no_such_template /* If no such template exists for the purpouse, language and country */
  }

  /* The owner of this contract */
  address private owner;  /* Who owns this Consent Facotory, this is a company */

  /* Contains a map from language and country according to ISO 639 and ISO 3166-1 alpha 2 separated by a dash to
   * consent template. For example swedish in Sweden is written sv-SE */
  struct ConsentLanguageCountry {
    bool exist; /* If there exists any consents, true if yes, false otherwsie */
    mapping (string => ConsentTemplate) consentTemplates;
  }

  /* Contains a map from purpouse to language and country mapping */
  mapping (string => ConsentLanguageCountry) private consentPurpouses;

  /* Events generated when the consent has been created */
  event ConsentFactoryConsentCreatedEvent(address indexed owner, address indexed user, address indexed file, address consent);
  event ConsentFactoryFileCreatedEvent(address indexed owner, address indexed user, address file);
  event ConsentFactoryFailedEvent(address indexed owner, address indexed user, Error error);
  event ConsentFactoryTemplateAdded (address indexed owner, address indexed factory, address template);

  /* Debugging stuff */
  event ConsentFactoryDebug (string text, uint16 value, bool flag);

  /* Constructor for the consent factory */
  function ConsentFactory() public
  {
    owner = msg.sender;
  }

  /* Adds a consent template to the factory to be used for futre consent generation. */
  function addConsentTemplate (string _purpouse, uint16 _version, string _title, string _text, string _languageCountry)
  {
    consentPurpouses[_purpouse].exist = true;
    ConsentTemplate consentTemplate = new ConsentTemplate (_purpouse, _version, _title, _text, _languageCountry);
    consentPurpouses[_purpouse].consentTemplates[_languageCountry] = consentTemplate;
    ConsentFactoryTemplateAdded (owner, this, consentTemplate);
  }

  /* Create a file that holds a users all consents
   *
   * This is the file that holds all consents regardless of their state.
   */
  function createConsentFile (address _user)
  {
    address file;

    file = new ConsentFile (_user);
    ConsentFactoryFileCreatedEvent(owner, _user, file);
  }

  /* Create a consent for a specific purpouse of the latest version, language and country.
   *
   * Country and Purpouse must exist otherwise it will fail, if language is not there it will
   * default to countrys default language if it exists otherwise it will fail. It adds
   * the consent to the users file as well.
   */
  function createConsent (address _file, string _purpouse, string _languageCountry)
  {
    ConsentFile cf = ConsentFile (_file);
    ConsentTemplate ct = getTemplate (_purpouse, _languageCountry);
    if (ct != address(0)) {

      Consent consent = new Consent (cf.getOwner(), ct);
      ConsentFile(_file).addConsent (consent);
      ConsentFactoryConsentCreatedEvent(owner, cf.getOwner(), _file, consent);

    } else {

      ConsentFactoryFailedEvent(owner, cf.getOwner(), Error.no_such_template);

    }
  }

  /* This function checks to see that there is a consent to be generated */
  function hasConsent (string _purpouse, string _languageCountry) constant returns (bool)
  {
    ConsentTemplate ct = getTemplate (_purpouse, _languageCountry);
    return (ct != address(0));
  }

  /* This function tests wether a consent for a specific purpouse exists or not */
  function getTemplate (string _purpouse, string _languageCountry) constant internal returns (ConsentTemplate)
  {
    /* Get the consents for a specific purpouse */
    ConsentLanguageCountry clc = consentPurpouses[_purpouse];
    if (clc.exist) {

      /* Get the specific consent for the language and country */
      ConsentTemplate ct = clc.consentTemplates[_languageCountry];
      if (ct == address(0)) {

	/* Fallback here is to only go for the default language of the country */
	/* So we need to strip the language from the country */
	bytes memory b = bytes (_languageCountry);
	if (b.length==5) {
	  if (b[2] == 45) {
	    bytes memory c = new bytes(2);
	    c[0] = b[3];
	    c[1] = b[4];
	    ct = clc.consentTemplates[string(c)];
	  }
	}
      }
    }

    /* Return with the found template */
    return ct;
  }

  /* Function to recover the funds on the contract */
  function kill() { if (msg.sender == owner) selfdestruct(owner); }
}

/*
 * END
 */