contract: bump solidity to 0.4.8

contract: bump solidity to 0.4.8

//! Fundraiser contract. Just records who sent what.
//! By Parity Technologies, 2017.
//! Released under the Apache Licence 2.
//! Modified by the Interchain Foundation.

pragma solidity ^0.4.8;

/// Will accept Ether "contributions" and record each both as a log and in a
/// queryable record.
contract Fundraiser {

    // How much is enough?
    uint public constant dust = 1 finney; // XXX: change for production

    // Special addresses:
    //  administrator can halt/unhalt/kill/adjustRate;
    //  treasury receives all the funds
    address public admin;
    address public treasury;

    // Begin and end block for the fundraising period
    uint public beginBlock;
    uint public endBlock;

    // Number of wei per atom
    uint public weiPerAtom;

    // Are contributions abnormally halted?
    bool public isHalted = false;

    // The `record` mapping maps cosmos addresses to the amount of atoms.
    // The `returnAddresses` mapping maps cosmos addresses to their ethereum return addresses.
    // NOTE: We could use a struct instead but would currently
    // save only one SSLOAD/SSTORE and at the expense
    // of relying on solidity type packing :o !
    mapping (address => uint) public record;
    mapping (address => address) public returnAddresses;

    // The total amount of ether raised
    uint public totalWei = 0;
    // The total amount of atoms suggested for allocation
    uint public totalAtom = 0;

    /// Constructor. `_admin` has the ability to pause the
    /// contribution period and, eventually, kill this contract. `_treasury`
    /// receives all funds. `_beginBlock` and `_endBlock` define the begin and
    /// end of the period. `_weiPerAtom` is the ratio of atoms to ether.
    function Fundraiser(address _admin, address _treasury, uint _beginBlock, uint _endBlock, uint _weiPerAtom) {
        admin = _admin;
        treasury = _treasury;
        beginBlock = _beginBlock;
        endBlock = _endBlock;
	weiPerAtom = _weiPerAtom;
    }

    // Can only be called by _admin.
    modifier only_admin { if (msg.sender != admin) throw; _; }
    // Can only be called by prior to the period.
    modifier only_before_period { if (block.number >= beginBlock) throw; _; }
    // Can only be called during the period when not halted.
    modifier only_during_period { if (block.number < beginBlock || block.number >= endBlock || isHalted) throw; _; }
    // Can only be called during the period when halted.
    modifier only_during_halted_period { if (block.number < beginBlock || block.number >= endBlock || !isHalted) throw; _; }
    // Can only be called after the period.
    modifier only_after_period { if (block.number < endBlock) throw; _; }
    // The value of the message must be sufficiently large to not be considered dust.
    modifier is_not_dust { if (msg.value < dust) throw; _; }

    /// Some contribution `amount` received from `recipient` at rate of `currentRate`.
    event Received(address indexed recipient, uint amount, uint currentRate);
    /// Period halted abnormally.
    event Halted();
    /// Period restarted after abnormal halt.
    event Unhalted();

    /// Receive a contribution for a donor cosmos address.
    /// Also store returnAddress just-in-case.
    function donate(address _donor, address _returnAddress, bytes32 checksum) payable only_during_period is_not_dust {
	// checksum is the sha3 of the xor of the bytes32 versions of the cosmos address and the return address
	if (!(sha3(bytes32(_donor)^bytes32(_returnAddress)) == checksum)) throw;

	// forward the funds to the treasurer
        if (!treasury.send(msg.value)) throw;

	// calculate the number of atoms at the current rate
	var atoms = msg.value / weiPerAtom;

	// update the donor details
        record[_donor] += atoms;

	// only set return address on first donation
	if ( returnAddresses[_donor] == address(0x0) ) {
        	returnAddresses[_donor] = _returnAddress;
	}

	// update the totals
        totalWei += msg.value;
	totalAtom += atoms;

        Received(_donor, msg.value, weiPerAtom);
    }

    /// Adjust the weiPerAtom
    function adjustRate(uint newRate) only_admin {
	weiPerAtom = newRate;
    }

    /// Halt the contribution period. Any attempt at contributing will fail.
    function halt() only_admin only_during_period {
        isHalted = true;
        Halted();
    }

    /// Unhalt the contribution period.
    function unhalt() only_admin only_during_halted_period {
        isHalted = false;
        Unhalted();
    }

    /// Kill this contract.
    function kill() only_admin only_after_period {
        suicide(treasury);
    }
}

//! Fundraiser contract. Just records who sent what.
//! By Parity Technologies, 2017.
//! Released under the Apache Licence 2.
//! Modified by the Interchain Foundation.

pragma solidity ^0.4.7;

/// Will accept Ether "contributions" and record each both as a log and in a
/// queryable record.
contract Fundraiser {

    // How much is enough?
    uint public constant dust = 1 finney; // XXX: change for production

    // Special addresses:
    //  administrator can halt/unhalt/kill/adjustRate;
    //  treasury receives all the funds
    address public admin;
    address public treasury;

    // Begin and end block for the fundraising period
    uint public beginBlock;
    uint public endBlock;

    // Number of wei per atom
    uint public weiPerAtom;

    // Are contributions abnormally halted?
    bool public isHalted = false;

    // The `record` mapping maps cosmos addresses to the amount of atoms.
    // The `returnAddresses` mapping maps cosmos addresses to their ethereum return addresses.
    // NOTE: We could use a struct instead but would currently
    // save only one SSLOAD/SSTORE and at the expense
    // of relying on solidity type packing :o !
    mapping (address => uint) public record;
    mapping (address => address) public returnAddresses;

    // The total amount of ether raised
    uint public totalWei = 0;
    // The total amount of atoms suggested for allocation
    uint public totalAtom = 0;

    /// Constructor. `_admin` has the ability to pause the
    /// contribution period and, eventually, kill this contract. `_treasury`
    /// receives all funds. `_beginBlock` and `_endBlock` define the begin and
    /// end of the period. `_weiPerAtom` is the ratio of atoms to ether.
    function Fundraiser(address _admin, address _treasury, uint _beginBlock, uint _endBlock, uint _weiPerAtom) {
        admin = _admin;
        treasury = _treasury;
        beginBlock = _beginBlock;
        endBlock = _endBlock;
	weiPerAtom = _weiPerAtom;
    }

    // Can only be called by _admin.
    modifier only_admin { if (msg.sender != admin) throw; _; }
    // Can only be called by prior to the period.
    modifier only_before_period { if (block.number >= beginBlock) throw; _; }
    // Can only be called during the period when not halted.
    modifier only_during_period { if (block.number < beginBlock || block.number >= endBlock || isHalted) throw; _; }
    // Can only be called during the period when halted.
    modifier only_during_halted_period { if (block.number < beginBlock || block.number >= endBlock || !isHalted) throw; _; }
    // Can only be called after the period.
    modifier only_after_period { if (block.number < endBlock) throw; _; }
    // The value of the message must be sufficiently large to not be considered dust.
    modifier is_not_dust { if (msg.value < dust) throw; _; }

    /// Some contribution `amount` received from `recipient` at rate of `currentRate`.
    event Received(address indexed recipient, uint amount, uint currentRate);
    /// Period halted abnormally.
    event Halted();
    /// Period restarted after abnormal halt.
    event Unhalted();

    /// Receive a contribution for a donor cosmos address.
    /// Also store returnAddress just-in-case.
    function donate(address _donor, address _returnAddress, bytes32 checksum) payable only_during_period is_not_dust {
	// checksum is the sha3 of the xor of the bytes32 versions of the cosmos address and the return address
	if (!(sha3(bytes32(_donor)^bytes32(_returnAddress)) == checksum)) throw;

	// forward the funds to the treasurer
        if (!treasury.send(msg.value)) throw;

	// calculate the number of atoms at the current rate
	var atoms = msg.value / weiPerAtom;

	// update the donor details
        record[_donor] += atoms;

	// only set return address on first donation
	if ( returnAddresses[_donor] == address(0x0) ) {
        	returnAddresses[_donor] = _returnAddress;
	}

	// update the totals
        totalWei += msg.value;
	totalAtom += atoms;

        Received(_donor, msg.value, weiPerAtom);
    }

    /// Adjust the weiPerAtom
    function adjustRate(uint newRate) only_admin {
	weiPerAtom = newRate;
    }

    /// Halt the contribution period. Any attempt at contributing will fail.
    function halt() only_admin only_during_period {
        isHalted = true;
        Halted();
    }

    /// Unhalt the contribution period.
    function unhalt() only_admin only_during_halted_period {
        isHalted = false;
        Unhalted();
    }

    /// Kill this contract.
    function kill() only_admin only_after_period {
        suicide(treasury);
    }
}


Create UnanimousConsentSignatureProxy.sol

import "UnanimousConsent.sol";

/**
* This contract will call consent from the UnanimousConsent
* contract if and only if the signer has signed all of the hashes
**/
contract ECDSASignatureProxy {
    address signer;
    UnanimousConsent unanimousConsent;

    function ECDSASignatureProxy(address _signer, UnanimousConsent _unanimousConsent) {
        signer = _signer;
        unanimousConsent = _unanimousConsent;
    }

    function forward(bytes32[] hashes, uint8[] v, bytes32[] r, bytes32[] s) returns(bool) {
        uint length = hashes.length;
        for (uint i = length - 1; i <= 0; --i) {
            if (ecrecover(hashes[i], v[i], r[i], s[i]) != signer) {
                return false;
            }
        }
        return unanimousConsent.call(bytes4(sha3("consent(bytes32)")), hashes);
    }
}

error: pathspec 'contracts/ECDSASignatureProxy.sol' did not match any file(s) known to git


WIP Rewards

WIP Rewards

pragma solidity ^0.4.2;

import "dev.oraclize.it/api.sol";

import "math.sol"

/*
*/

contract NewCCCoin is usingOraclize {

    // Voting shard definition:
    struct VoteShard {
        address owner;
        string name;
        string options;
        bool status;

	address[] public prev_voted;
	address[] public voted;

	uint num_pending_votes;
	mapping (address => uint) pending_votes_per_user;

	uint num_pending_submits;
	mapping (address => uint) pending_submits_per_user;

	string[] pending_votes;

	mapping (string => uint) user_and_vote_to_old_reward; // total LOCK for this post at time when vote was made.

	mapping (string => uint) item_total_rewards; // total rewards on item.

	mapping (string => address[]) early_voters; // {item_id:[voter_1, voter_2, ...]}

	string[] pending_items;
	mapping (string => address[]) pending_votes;// {item_id:[voter_1, voter_2, ...]}

	uint tot_pending_power;
	mapping (string => uint) pending_power; // {item_id:power}

	//

	uint global_votes_num;

	mapping (string => mapping (string => uint)) all_votes_mapping; // {item_id:{voter:int}}
	mapping (string => uint) all_votes_num;                         // {item_id:int}
	mapping (string => uint) all_votes_power;                       // {item_id:int}
	mapping (string => uint) last_rewards_time;                     // {item_id:int}

	mapping (string => address[50]) all_votes_first;                // {item_id:[voter, voter, voter]}
	mapping (string => address[50]) all_votes_last;                  // {item_id:[voter, voter, voter]}

	global_rewards_today = 0;

    }

    // Storing vote to event log:
    event StoreVote(string votestring);

    // Public VoteShard called vs:
    VoteShard public vs;

    //
    mapping (address => item_id) voters_to_items;

    // Setup this voting shard:
    function NewVoteShard(string x_options, string x_name, uint _votelimit) {
        vs.owner = msg.sender;
        vs.title = x_name;
        vs.options = x_options;

	//ScheduleAlarm();
    }

    // Recurring token minting and rewards calculations. TODO: Note, not so trustless:
    function ScheduleAlarm() {
       oraclize_query(10 * minutes, "URL", "");
    }

    // Callback for alarm oracle:
    function __callback(bytes32 myid, string result) {
        if (msg.sender != oraclize_cbAddress()) throw;

	// Minting & Rewards:

	portion = 100 / tot_pending_power;

	for (i = 0; i < pending_items.length; i++){

	    x_item = pending_items[i];

	    for (j = 0; j < early_voters[x_item].length; i++){

		x_voter = early_voters[x_item][j];

		balances[x_voter] += portion * pending_power[x_item];
	    }

	}

	// Recurse:

	ScheduleAlarm();
    }

    // Store vote in event logs, to be later interpreted by web app:
    // direction == 1: upvote
    // direction == 0: cancel upvote
    function vote(string item_id, bool direction) returns (bool) {

	// NOTE: Not yet ready.

	voter_id = msg.sender;

	// Accept or reject vote, based on user's LOCK balance:

	if (vs.lock_balances[voter_id] < ((1 * vs.pending_votes_per_user[voter_id]) ** 3) + 100) {
	    // Reject vote, not enough LOCK.
	    return false;
	}

	// Accept vote:

        vs.num_pending_votes += 1;

	vs.pending_votes_per_user[voter_id] += 1;

	// Distribute rewards, to first 50 and last 50:

	if (all_votes_mapping[item_id][voter_id] == 0){

	    if (all_votes_first[item_id].length < 50) {
		// First 50 voters:
		all_votes_first[item_id].push(voter_id);
	    }
	    else {
		// Last 50 voters:
		all_votes_last[item_id][all_votes_num[item_id] % 50] = voter_id;
	    }

	    all_votes_power[item_id] += lock_balances[msg.sender];
	    pending_votes_power[item_id] += lock_balances[msg.sender];
	    pending_global_power += lock_balances[msg.sender];
	    median_daily_curation_rewards = 100 * 10;
	    all_votes_num[item_id] += 1;
	    global_votes_num += 1;

	    // Calcuate total rewards for this item:

	    this_hour = Math.floor(now / 60 / 60);

	    one_day = 60 * 60 * 24;

	    end_of_day = Math.floor(now + one_day)

	    // TODO, about to swap for another:

	    this_reward =  ((end_of_day - now) / one_day) / (all_power_pending[item_id] / global_pending_power) / (global_rewards_today / median_daily_curation_rewards);

	    // Distribute rewards, every: max(50 votes, 10 minutes):

	    if ((all_votes_num[item_id] % 50 == 0) && (now - last_rewards_time[item_id] > 60 * 10)){

		// iterate voters:

		for (i = 0; i < all_votes_first[item_id].length; i++){

		    xvoter = all_votes_first[item_id][i];
		    user_power = all_votes_power_first[item_id][i];
		    total_power = all_votes_power[item_id];

		    // Voter didn't delete vote:

		    if (xvoter != 0){

			lock_balances[xvoter] += (xpower / this_reward);

			pending_global_power -= xpower;
			pending_votes_power[item_id] -= xpower;
		    }
		}

		last_rewards_time[item_id] = now;

		global_rewards_today += this_reward;

	    }

	}

	// Emit vote event:

	string votestring = item_id;

        StoreVote(votestring);

        return true;
    }

    //
    function createHumanStandardToken(uint256 _initialAmount, string _name, uint8 _decimals, string _symbol) returns (address) {

        HumanStandardToken newToken = (new HumanStandardToken(_initialAmount, _name, _decimals, _symbol));
        created[msg.sender].push(address(newToken));
        isHumanToken[address(newToken)] = true;
        newToken.transfer(msg.sender, _initialAmount); //the factory will own the created tokens. You must transfer them.
        return address(newToken);
    }

    function transferOwnership(address newOwner) {
        if (msg.sender != vs.owner) {
	    return;
	}
        vs.owner = newOwner;
    }

}

pragma solidity ^0.4.2;

import "dev.oraclize.it/api.sol";

import "math.sol"

/*
*/

contract NewCCCoin is usingOraclize {

    // Voting shard definition:
    struct VoteShard {
        address owner;
        string name;
        string options;
        bool status;

	address[] public prev_voted;
	address[] public voted;

	uint num_pending_votes;
	mapping (address => uint) pending_votes_per_user;

	uint num_pending_submits;
	mapping (address => uint) pending_submits_per_user;

	string[] pending_votes;

	mapping (string => uint) user_and_vote_to_old_reward; // total LOCK for this post at time when vote was made.

	mapping (string => uint) item_total_rewards; // total rewards on item.

	mapping (string => address[]) early_voters; // {item_id:[voter_1, voter_2, ...]}

	string[] pending_items;
	mapping (string => address[]) pending_votes;// {item_id:[voter_1, voter_2, ...]}

	uint tot_pending_power;
	mapping (string => uint) pending_power; // {item_id:power}

	//

	uint global_votes_num;

	mapping (string => mapping (string => uint)) all_votes_mapping; // {item_id:{voter:int}}
	mapping (string => uint) all_votes_num;                         // {item_id:int}
	mapping (string => uint) all_votes_power;                       // {item_id:int}
	mapping (string => uint) last_rewards_time;                     // {item_id:int}

	mapping (string => address[50]) all_votes_first;                // {item_id:[voter, voter, voter]}
	mapping (string => address[50]) all_votes_last;                  // {item_id:[voter, voter, voter]}

    }

    // Storing vote to event log:
    event StoreVote(string votestring);

    // Public VoteShard called vs:
    VoteShard public vs;

    //
    mapping (address => item_id) voters_to_items;

    // Setup this voting shard:
    function NewVoteShard(string x_options, string x_name, uint _votelimit) {
        vs.owner = msg.sender;
        vs.title = x_name;
        vs.options = x_options;

	//ScheduleAlarm();
    }

    // Recurring token minting and rewards calculations. TODO: Note, not so trustless:
    function ScheduleAlarm() {
       oraclize_query(10 * minutes, "URL", "");
    }

    // Callback for alarm oracle:
    function __callback(bytes32 myid, string result) {
        if (msg.sender != oraclize_cbAddress()) throw;

	// Minting & Rewards:

	portion = 100 / tot_pending_power;

	for (i = 0; i < pending_items.length; i++){

	    x_item = pending_items[i];

	    for (j = 0; j < early_voters[x_item].length; i++){

		x_voter = early_voters[x_item][j];

		balances[x_voter] += portion * pending_power[x_item];
	    }

	}

	// Recurse:

	ScheduleAlarm();
    }

    // Store vote in event logs, to be later interpreted by web app:
    // direction == 1: upvote
    // direction == 0: cancel upvote
    function vote(string item_id, bool direction) returns (bool) {

	// NOTE: Not yet ready.

	voter_id = msg.sender;

	// Accept or reject vote, based on user's LOCK balance:

	if (vs.lock_balances[voter_id] < ((1 * vs.pending_votes_per_user[voter_id]) ** 3) + 100) {
	    // Reject vote, not enough LOCK.
	    return false;
	}

	// Accept vote:

        vs.num_pending_votes += 1;

	vs.pending_votes_per_user[voter_id] += 1;

	// Distribute rewards, to first 50 and last 50:

	if (all_votes_mapping[item_id][voter_id] == 0){

	    if (all_votes_first[item_id].length < 50) {
		// First 50 voters:
		all_votes_first[item_id].push(voter_id);
	    }
	    else {
		// Last 50 voters:
		all_votes_last[item_id][all_votes_num[item_id] % 50] = voter_id;
	    }

	    all_votes_power[item_id] += lock_balances[msg.sender];
	    pending_votes_power[item_id] += lock_balances[msg.sender];
	    pending_global_power += lock_balances[msg.sender];
	    all_votes_num[item_id] += 1;
	    global_votes_num += 1;

	    // Calcuate total rewards for this item:

	    this_hour = int(now / 60 / 60);

	    one_day = 60 * 60 * 24;

	    end_of_day = int(now + one_day)

	    this_reward = (all_power_pending[item_id] / global_pending_power) / ((end_of_day - now) / one_day) / (target_daily_curation_rewards / median_daily_curation_rewards);

	    // Distribute rewards, every: max(50 votes, 10 minutes):

	    if ((all_votes_num[item_id] % 50 == 0) && (now - last_rewards_time[item_id] > 60 * 10)){

		// iterate voters:

		for (i = 0; i < all_votes_first[item_id].length; i++){

		    xvoter = all_votes_first[item_id][i];
		    user_power = all_votes_power_first[item_id][i];
		    total_power = all_votes_power[item_id];

		    // Voter didn't delete vote:

		    if (xvoter != 0){

			lock_balances[xvoter] += (xpower / this_reward);

			pending_global_power -= xpower;
			pending_votes_power[item_id] -= xpower;
		    }
		}

		last_rewards_time[item_id] = now;

	    }

	}

	// Emit vote event:

	string votestring = item_id;

        StoreVote(votestring);

        return true;
    }

    //
    function createHumanStandardToken(uint256 _initialAmount, string _name, uint8 _decimals, string _symbol) returns (address) {

        HumanStandardToken newToken = (new HumanStandardToken(_initialAmount, _name, _decimals, _symbol));
        created[msg.sender].push(address(newToken));
        isHumanToken[address(newToken)] = true;
        newToken.transfer(msg.sender, _initialAmount); //the factory will own the created tokens. You must transfer them.
        return address(newToken);
    }

    function transferOwnership(address newOwner) {
        if (msg.sender != vs.owner) {
	    return;
	}
        vs.owner = newOwner;
    }

}


implement partial withdrawal before / after audit (50 / 50)

pragma solidity ^0.4.13;

contract Voting {

    enum Role { OWNER, COMPANY, RESIDENT, AUDITOR }
    enum State { INITIAL, FUNDED, OPEN, APPROVED, INSTALLIING, AUDITED, CLOSED }

    mapping (address => Role) roles;
    State public state;

    event Funded(address addr, uint amount);
    event VotingOpened(uint threshold);
    event Approved(address addr, uint total);
    event VotingClosedSuccess(uint total);
    //event VotingClosedFailure();
    event Withdrawn(address addr, uint amount);
    event Audited();
    event Closed();

    mapping (address => bool) approved;
    uint numApproved;   // number of residents who approved
    uint threshold;     // required support in persent (1 to 100)
    uint firtWithdrawalShare = 50;     // share that company withdraws before installation

	// Addresses generated from seed.txt
    address[] private testAddresses;

    function assignTestAddresses(bool isRpc) internal {
        if (isRpc) {
    		testAddresses.push(0x0120fe6e3aa2c936e6d2f88062b266c46c408f98);
    		testAddresses.push(0xa8fc189694dc8ba03c027d470b77c09b7d13471e);
    		testAddresses.push(0xdbf73038f3e4a5d27e38004c36dc6ce82165794f);
    		testAddresses.push(0x692b50dc6d0021a73ec50fcd3ad78d3c121be360);
    		testAddresses.push(0xc396dfc357c849c5e4fbbe1f130eb469675af895);
    		testAddresses.push(0x07efc80760137f58a43e44a9bede15da8053d730);
    		testAddresses.push(0xfe8699b505180f51966e56f118e66544dea311bd);
    		testAddresses.push(0x276ae02aa2710bebc571f3647d64d9b440f998d6);
    		testAddresses.push(0x43882f2be5ccf7ba1cf848e202683385d5fb93bb);
    		testAddresses.push(0x76c780eb591481c086e1a0574b16c4f52e5aa352);
        } else {
            testAddresses.push(0xca35b7d915458ef540ade6068dfe2f44e8fa733c);
            testAddresses.push(0x14723a09acff6d2a60dcdf7aa4aff308fddc160c);
            testAddresses.push(0x4b0897b0513fdc7c541b6d9d7e929c4e5364d2db);
            testAddresses.push(0x583031d1113ad414f02576bd6afabfb302140225);
            testAddresses.push(0xdd870fa1b7c4700f2bd7f44238821c26f7392148);
        }
    }

	function assignRoles() internal {
	    require(msg.sender == testAddresses[0]);
	    require(testAddresses.length > 3);
		roles[testAddresses[0]] = Role.OWNER;
		roles[testAddresses[1]] = Role.COMPANY;
		roles[testAddresses[2]] = Role.AUDITOR;
		for (uint8 i = 3; i < testAddresses.length; i++) {
		    roles[testAddresses[i]] = Role.RESIDENT;
		}
	}

	function Voting(bool isRpc) {
	    assignTestAddresses(isRpc);
	    assignRoles();
	    state = State.INITIAL;
	}

	function () payable {
	    require(roles[msg.sender] == Role.OWNER);
	    require(state == State.INITIAL);
	    state = State.FUNDED;
	    Funded(msg.sender, msg.value);
	}

	// TODO: add deadline
	function startVoting(uint _thresholdPercent) {
	    require(roles[msg.sender] == Role.OWNER);
	    require(_thresholdPercent > 0 && _thresholdPercent <= 100);
	    require(state == State.FUNDED);
	    threshold = (_thresholdPercent * (testAddresses.length - 2) / 100) + 1;
	    state = State.OPEN;
	    VotingOpened(threshold);
	}

	function approve() {
	    require(roles[msg.sender] == Role.RESIDENT);
	    require(state == State.OPEN);
	    approved[msg.sender] = true;
	    numApproved += 1;
	    Approved(msg.sender, numApproved);
	    if (numApproved >= threshold) {
	        state = State.APPROVED;
	        VotingClosedSuccess(numApproved);
	    }
	}

	function withdraw(uint amount) internal {
	    msg.sender.transfer(amount);
	    Withdrawn(msg.sender, amount);
	}

	function withdrawFirst() {
	    require(roles[msg.sender] == Role.COMPANY);
	    require(state == State.APPROVED);
	    withdraw(this.balance * firtWithdrawalShare / 100);
	    state = State.INSTALLIING;
	}

	function auditConfirm() {
	    require(roles[msg.sender] == Role.AUDITOR);
	    require(state == State.INSTALLIING);
	    state = State.AUDITED;
	    Audited();
	}

	function withdrawSecond() {
	    require(roles[msg.sender] == Role.COMPANY);
	    require(state == State.AUDITED);
	    withdraw(this.balance);
	    state = State.CLOSED;
	    Closed();
	}

}

pragma solidity ^0.4.13;

contract Voting {

    enum Role { OWNER, COMPANY, RESIDENT}
    enum State { INITIAL, FUNDED, OPEN, APPROVED, CLOSED }

    mapping (address => Role) roles;
    State public state;

    event Funded(address addr, uint amount);
    event VotingOpened(uint threshold);
    event Approved(address addr, uint total);
    event VotingClosedSuccess(uint total);
    //event VotingClosedFailure();
    event Withdrawn(address addr, uint amount);

    mapping (address => bool) approved;
    uint numApproved;   // number of residents who approved
    uint threshold;     // required support in persent (1 to 100)

	// Addresses generated from seed.txt
    address[] private testAddresses;

    function assignTestAddresses(bool isRpc) internal {
        if (isRpc) {
    		testAddresses.push(0x0120fe6e3aa2c936e6d2f88062b266c46c408f98);
    		testAddresses.push(0xa8fc189694dc8ba03c027d470b77c09b7d13471e);
    		testAddresses.push(0xdbf73038f3e4a5d27e38004c36dc6ce82165794f);
    		testAddresses.push(0x692b50dc6d0021a73ec50fcd3ad78d3c121be360);
    		testAddresses.push(0xc396dfc357c849c5e4fbbe1f130eb469675af895);
    		testAddresses.push(0x07efc80760137f58a43e44a9bede15da8053d730);
    		testAddresses.push(0xfe8699b505180f51966e56f118e66544dea311bd);
    		testAddresses.push(0x276ae02aa2710bebc571f3647d64d9b440f998d6);
    		testAddresses.push(0x43882f2be5ccf7ba1cf848e202683385d5fb93bb);
    		testAddresses.push(0x76c780eb591481c086e1a0574b16c4f52e5aa352);
        } else {
            testAddresses.push(0xca35b7d915458ef540ade6068dfe2f44e8fa733c);
            testAddresses.push(0x14723a09acff6d2a60dcdf7aa4aff308fddc160c);
            testAddresses.push(0x4b0897b0513fdc7c541b6d9d7e929c4e5364d2db);
            testAddresses.push(0x583031d1113ad414f02576bd6afabfb302140225);
            testAddresses.push(0xdd870fa1b7c4700f2bd7f44238821c26f7392148);
        }
    }

	function assignRoles() internal {
	    require(msg.sender == testAddresses[0]);
	    require(testAddresses.length > 2);
		roles[testAddresses[0]] = Role.OWNER;
		roles[testAddresses[1]] = Role.COMPANY;
		for (uint8 i = 2; i < testAddresses.length; i++) {
		    roles[testAddresses[i]] = Role.RESIDENT;
		}
	}

	function Voting(bool isRpc) {
	    assignTestAddresses(isRpc);
	    assignRoles();
	    state = State.INITIAL;
	}

	function fund() payable {
	    require(roles[msg.sender] == Role.OWNER);
	    require(state == State.INITIAL);
	    state = State.FUNDED;
	    Funded(msg.sender, msg.value);
	}

	// TODO: add deadline
	function startVoting(uint _thresholdPercent) {
	    require(roles[msg.sender] == Role.OWNER);
	    require(_thresholdPercent > 0 && _thresholdPercent <= 100);
	    require(state == State.FUNDED);
	    threshold = (_thresholdPercent * (testAddresses.length - 2) / 100) + 1;
	    state = State.OPEN;
	    VotingOpened(threshold);
	}

	function approve() {
	    require(roles[msg.sender] == Role.RESIDENT);
	    require(state == State.OPEN);
	    approved[msg.sender] = true;
	    numApproved += 1;
	    Approved(msg.sender, numApproved);
	    if (numApproved >= threshold) {
	        state = State.APPROVED;
	        VotingClosedSuccess(numApproved);
	    }
	}

	function withdraw() {
	    require(roles[msg.sender] == Role.COMPANY);
	    require(state == State.APPROVED);
	    msg.sender.transfer(this.balance);
	    state = State.CLOSED;
	    Withdrawn(msg.sender, this.balance);
	}

}


fix getRebate function

fix getRebate function

contract coin {}

contract issuer {
    address public issuerAddr;
    address public coinAddr;
    coin public pluton;

    struct Rebate {
        uint plutonRewardRate;
        uint plutonRewardRateReduceStep;
        uint plutonRewardRateReduce;
        uint reqieredExchangeSpeed;
        uint currentExchangeSpeedRate;
        uint lastTimestamp;
        uint baseUnitForRebate;
        uint minPlutonRewardRate;
        uint currentExchangeSpeed;
    }
    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.plutonRewardRate = 30; // 3%
        rebate.minPlutonRewardRate = 10; // 1%

        rebate.plutonRewardRateReduce = 1; // reduce 0,1% from every plutonRewardRateReduceStep more in action more in action

        rebate.reqieredExchangeSpeed = 10; // 10 BTC/sec
        rebate.plutonRewardRateReduceStep = 1; // for example: every 1 BTC/sec more in action reduce rate on plutonRewardRateReduce

        rebate.lastTimestamp = now;
        pluton = coin(_plutonAddr);
    }

    /* issuer functions */

    function getRebate(uint _btcAmount, string txID, address _btcSeller) ownerCheck returns(uint plutonReward) {
        rebate.currentExchangeSpeed =  _btcAmount / (now - rebate.lastTimestamp);
        uint reduce;
        reduce = (rebate.currentExchangeSpeed -  rebate.reqieredExchangeSpeed) / rebate.plutonRewardRateReduceStep * rebate.plutonRewardRateReduce;
        if(reduce > rebate.currentExchangeSpeed) {rebate.plutonRewardRate = rebate.minPlutonRewardRate;}
        else if(rebate.currentExchangeSpeed > rebate.reqieredExchangeSpeed) {
                rebate.plutonRewardRate = rebate.plutonRewardRate - reduce;}
                else {rebate.plutonRewardRate = rebate.plutonRewardRate + reduce;}

        plutonReward = _btcAmount * rebate.plutonRewardRate;
         //   pluton.emmision(plutonReward);
        //    pluton.transfer(plutonReward, _btcSeller);
    }

}

contract coin {}

contract issuer {
    address public issuerAddr;
    address public coinAddr;
    coin public pluton;

    struct Rebate {
        uint plutonRewardRate;
        uint reqieredExchangeSpeed;
        uint currentExchangeSpeedRate;
        uint lastTimestamp;
        uint baseUnitForRebate;
    }
    Rebate public rebate;

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

    /*Initial */
    function issuer(address _issuer, coin _plutonAddr) {
        issuerAddr = _issuer;
        coinAddr = _plutonAddr;
        rebate.plutonRewardRate = 3; // 3%
        rebate.baseUnitForRebate = 10;
        pluton = coin(_plutonAddr);
    }

    /* issuer functions */

    function getRebate(uint _btcAmount, string txID, address _btcSeller) ownerCheck returns(uint plutonReward) {
        rebate.currentExchangeSpeedRate =  _btcAmount / (now - rebate.lastTimestamp) / rebate.reqieredExchangeSpeed;
        rebate.plutonRewardRate = rebate.plutonRewardRate * rebate.currentExchangeSpeedRate / rebate.baseUnitForRebate;
        plutonReward = _btcAmount * rebate.plutonRewardRate;
         //  pluton.emmision(plutonReward);
        //    pluton.transfer(plutonReward, _btcSeller);
    }

}


Fixed merge

Fixed merge

contract Master
{
  //Initialize master data store
  mapping (address => uint) tokenBalance;
  mapping (address => string) tagName;
  mapping (string => address) tagAddressFromName;
  mapping (address => address[]) achievements;
  mapping (address => bool) availability;
  mapping (address => address) users;

  function Master()
  {
    tokenBalance[address(this)] = 1;
    address[] a;
    uint useless = addTag("account", a);
  }

  function mapTokenBalance(address user, uint balance)
  {
    tokenBalance[user] = balance;
  }
  function mapTagName(address tagAddress, string name)
  {
    tagName[tagAddress] = name;
  }
  function mapTagAddressFromName(string name, address tagAddress)
  {
    tagAddressFromName[name] = tagAddress;
  }
  function mapAchievement(address user, address achievment)
  {
    achievements[user].push(achievment);
  }
  function mapAvailability(address user, bool availability)
  {
    availability[user] = availability;
  }

  function getTokenBalance(address user) returns(uint)
  {
    return tokenBalance[user];
  }
  function getTagName(address tagAddress) returns(string)
  {
    return tagName[tagAddress];
  }
  function getTagAddressFromName(string name) returns(address)
  {
    return tagAddressFromName[name];
  }
  function getAchievement(address user) returns(address[])
  {
    return achievements[user];
  }
  function getNumberOfachievments(address user) returns(uint)
  {
    return achievments[user].length;
  }
  function getAvailability(address user) returns(bool)
  {
    return availability[user] = true;
  }

  function addUser()
  {
    User newUser = new User(msg.sender, address(this));
    Tag(tagAddressFromName["account"]).startAssessment(address(newUser),5);
  }

  function addTag(string name, address[] parentList) returns(uint) //Creates a new tag contract
  {
    uint response = 0;
    address[] parents;
    if(tokenBalance[msg.sender] < 1)
    {
      response += 1;
    }
    if(tagAddressFromName[name] == 0)
    {
      response += 10;
    }
    if(response==0)
    {
      for(uint i=0; i<= parentList.length; i++) //adds all the given parents
      {
        if(parentList[i]==0)
        {
          response += 100*(10**i);
        }
        else
        {
          parents.push(parentList[i]);
        }
      }
      Tag newTag = new Tag(name, parents, address(this));
      address newTagAddress = address(newTag);
      tagName[newTagAddress] = name;
      tagAddressFromName[name] = newTagAddress;
      tokenBalance[msg.sender] -= 1;
    }
    return response;
  }
}

//Defines the meta-contract for a Tag
contract Tag
{
  address[] parentTags;
  address master;
  string name;
  address[] owners; //Those who have earned the tag
  mapping(address => address[]) assessmentHistory; //All assessments completed
  mapping(address => uint) scores; //All positive assessements scores

  function Tag(string tagName, address[] parents, address masterAddress)
  {
    name = tagName;
    parentTags = parents;
    master = masterAddress;
  }

  function setAssessorPool(address tagAddress, address assessment)
  {
    for(uint i = 0; i < Tag(tagAddress).owners.length && Assessment(assessment).poolSizeRemaining != 0; i++)
    {
      if(pool.length < .1*Tag(tagAddress).owners.length)
      {
        address random = Tag(tagAddress).owners[getRandom(Tag(tagAddress).owners.length)];
        if(Master(master).getAvailability(random) == true)
        {
          Assessment(assessment).addToAssessorPool();
          Assessment(assessment).poolSizeRemaining--;
        }
      }
      else
      {
        for(uint j = 0; j < Tag(tagAddress).parentTags.length; j++)
        {
          setAssessorPool(Tag(tagAddress).parentTags[j], assessment);
        }
      }
      if(Assessment(assessment).poolSizeRemaining =< 0)
      {
        Assessment(assessment).setAssessors();
      }
    }
  }

  function startAssessment(address assessee, uint size)
  {
    Assessment newAssessment = new Assessment(assessee, address.this);
    newAssessment.setNumberOfAssessors(size);
    newAssessment.setAssessmentPoolSize(size*20)
    setAssessorPool(address(this), address(newAssessment));
  }

  function finishAssessment(bool result, uint score, address assessee, address assessment) returns(bool)
  {
    if(result == true)
    {
      owners.push(assessee);
      scores[assessee] = score;
      Master(master).mapAchievement(assessee,address(this));
    }
    assessmentHistory[assessee].push(assessment);
    return result;
  }
  function getRandom(uint i) returns(uint)
  {
    return 12;
  }
}

//Defines the meta-contract for an assessment
contract Assessment
{
  address assessee; //We need a better word for this
  address[] assessorPool;
  address[] assessors;
  address tag;
  uint poolSizeRemaining;
  uint numberOfAssessors;
  struct Results
  {
    bool pass;
    uint score;
  }
  mapping(address => string) assessmentQuestions; //Given by the assessors as IPFS hashes
  mapping(address => string) assessmentAnswers; //Given by the assessee as IPFS hashes
  mapping(address => Results) assessmentResults; //Pass/Fail and Score given by assessors
  uint finalScore;
  bool finalResult;

  function Assessment(address assesseeAddress, address tagAddress)
  {
    assessee = assesseeAddress;
    tag = tagAddress;
  }

  function setNumberOfAssessors(uint number)
  {
    numberOfAssessors = number;
  }

  function setAssessmentPoolSize(uint sizeRemaining)
  {
    poolSizeRemaining = sizeRemaining;
  }
  function addToAssessorPool(address potentialAddress)
  {
    assessorPool.push(potentialAddress);
  }

  function setAssessors()
  {
    for(uint i = 0, i < numberOfAssessors, i++)
    {
      assessors.push(assessorPool[getRandom(assessorPool.length)]);
    }
  }

  function getRandom(uint i) returns(uint)
  {
    return 12;
  }
  function setQuestion(address assessorAddress, uint[] data)
  {
    assessmentQuestions[assessorAddress] = data;
  }

  function getQuestion(address assessorAddress) returns(uint[])
  {
    return assessmentQuestions[assessorAddress];
  }

  function setAnswer(address assesseeAddress, uint[] data)
  {
    assessmentAnswers[assesseeAddress] = data;
  }

  function getAnswer(address assesseeAddress) returns(uint[])
  {
    return assessmentAnswers[assesseeAddress];
  }

  function setResult(address assessorAddress, bool pass, uint score)
  {
    Results memory results;
    results.pass = pass;
    results.score = score;
    assessmentResults[a] = results;
  }

  function assess()
  {

  }

  function calculateResult()
  {

  }

  function returnResults()
  {
    Tag(tag).finishAssessment(finalResult, finalScore, assessee, address(this));
  }

  function cashout()
  {

  }
}

contract User
{
  address user;
  address master;
  address[] acheivements;
  string userData;

  function User(address userAddress, address masterAddress, string ipfsHash)
  {
    user = userAddress;
    master = masterAddress;
    userData = ipfsHash;
  }

  function setUserData(string hash)
  {
    userData hash;
  }

  function getUserData() returns(string)
  {
      return userData;
  }
}

contract Master
{
  //Initialize master data store
  mapping (address => uint) tokenBalance;
  mapping (address => string) tagName;
  mapping (string => address) tagAddressFromName;
  mapping (address => address[]) achievements;
  mapping (address => bool) availability;
  mapping (address => address) users;

  function Master()
  {
    tokenBalance[address(this)] = 1;
    address[] a;
    uint useless = addTag("account", a);
  }

  function mapTokenBalance(address user, uint balance)
  {
    tokenBalance[user] = balance;
  }
  function mapTagName(address tagAddress, string name)
  {
    tagName[tagAddress] = name;
  }
  function mapTagAddressFromName(string name, address tagAddress)
  {
    tagAddressFromName[name] = tagAddress;
  }
  function mapAchievement(address user, address achievment)
  {
    achievements[user].push(achievment);
  }
  function mapAvailability(address user, bool availability)
  {
    availability[user] = availability;
  }

  function getTokenBalance(address user) returns(uint)
  {
    return tokenBalance[user];
  }
  function getTagName(address tagAddress) returns(string)
  {
    return tagName[tagAddress];
  }
  function getTagAddressFromName(string name) returns(address)
  {
    return tagAddressFromName[name];
  }
  function getAchievement(address user) returns(address[])
  {
    return achievements[user];
  }
  function getNumberOfachievments(address user) returns(uint)
  {
    return achievments[user].length;
  }
  function getAvailability(address user) returns(bool)
  {
    return availability[user] = true;
  }

  function addUser()
  {
    User newUser = new User(msg.sender, address(this));
    Tag(tagAddressFromName["account"]).startAssessment(address(newUser),5);
  }

  function addTag(string name, address[] parentList) returns(uint) //Creates a new tag contract
  {
    uint response = 0;
    address[] parents;
    if(tokenBalance[msg.sender] < 1)
    {
      response += 1;
    }
    if(tagAddressFromName[name] == 0)
    {
      response += 10;
    }
    if(response==0)
    {
      for(uint i=0; i<= parentList.length; i++) //adds all the given parents
      {
        if(parentList[i]==0)
        {
          response += 100*(10**i);
        }
        else
        {
          parents.push(parentList[i]);
        }
      }
      Tag newTag = new Tag(name, parents, address(this));
      address newTagAddress = address(newTag);
      tagName[newTagAddress] = name;
      tagAddressFromName[name] = newTagAddress;
      tokenBalance[msg.sender] -= 1;
    }
    return response;
  }
}

//Defines the meta-contract for a Tag
contract Tag
{
  address[] parentTags;
  address master;
  string name;
  address[] owners; //Those who have earned the tag
  mapping(address => address[]) assessmentHistory; //All assessments completed
  mapping(address => uint) scores; //All positive assessements scores

  function Tag(string tagName, address[] parents, address masterAddress)
  {
    name = tagName;
    parentTags = parents;
    master = masterAddress;
  }

  function setAssessorPool(address tagAddress, address assessment)
  {
    for(uint i = 0; i < Tag(tagAddress).owners.length && Assessment(assessment).poolSizeRemaining != 0; i++)
    {
      if(pool.length < .1*Tag(tagAddress).owners.length)
      {
        address random = Tag(tagAddress).owners[getRandom(Tag(tagAddress).owners.length)];
        if(Master(master).getAvailability(random) == true)
        {
          Assessment(assessment).addToAssessorPool();
          Assessment(assessment).poolSizeRemaining--;
        }
      }
      else
      {
        for(uint j = 0; j < Tag(tagAddress).parentTags.length; j++)
        {
          setAssessorPool(Tag(tagAddress).parentTags[j], assessment);
        }
      }
      if(Assessment(assessment).poolSizeRemaining =< 0)
      {
        Assessment(assessment).setAssessors();
      }
    }
  }

  function startAssessment(address assessee, uint size)
  {
    Assessment newAssessment = new Assessment(assessee, address.this);
    newAssessment.setNumberOfAssessors(size);
    newAssessment.setAssessmentPoolSize(size*20)
    setAssessorPool(address(this), address(newAssessment));
  }

  function finishAssessment(bool result, uint score, address assessee, address assessment) returns(bool)
  {
    if(result == true)
    {
      owners.push(assessee);
      scores[assessee] = score;
      Master(master).mapAchievement(assessee,address(this));
    }
    assessmentHistory[assessee].push(assessment);
    return result;
  }
  function getRandom(uint i) returns(uint)
  {
    return 12;
  }
}

//Defines the meta-contract for an assessment
contract Assessment
{
  address assessee; //We need a better word for this
  address[] assessorPool;
  address[] assessors;
  address tag;
  uint poolSizeRemaining;
  uint numberOfAssessors;
  struct Results
  {
    bool pass;
    uint score;
  }
  mapping(address => string) assessmentQuestions; //Given by the assessors as IPFS hashes
  mapping(address => string) assessmentAnswers; //Given by the assessee as IPFS hashes
  mapping(address => Results) assessmentResults; //Pass/Fail and Score given by assessors
  uint finalScore;
  bool finalResult;

  function Assessment(address assesseeAddress, address tagAddress)
  {
    assessee = assesseeAddress;
    tag = tagAddress;
  }

  function setNumberOfAssessors(uint number)
  {
    numberOfAssessors = number;
  }

  function setAssessmentPoolSize(uint sizeRemaining)
  {
    poolSizeRemaining = sizeRemaining;
  }
  function addToAssessorPool(address potentialAddress)
  {
    assessorPool.push(potentialAddress);
  }

  function setAssessors()
  {
    for(uint i = 0, i < numberOfAssessors, i++)
    {
      assessors.push(assessorPool[getRandom(assessorPool.length)]);
    }
  }
<<<<<<< HEAD

  function setQuestion(address assessorAddress, uint[] data)
=======
  function getRandom(uint i) returns(uint)
  {
    return 12;
  }
  function setQuestion(address a, uint[] data)
>>>>>>> 61c1a726e1d14df3ac21e8924e1029ac230d9559
  {
    assessmentQuestions[assessorAddress] = data;
  }

  function getQuestion(address assessorAddress) returns(uint[])
  {
    return assessmentQuestions[assessorAddress];
  }

  function setAnswer(address assesseeAddress, uint[] data)
  {
    assessmentAnswers[assesseeAddress] = data;
  }

  function getAnswer(address assesseeAddress) returns(uint[])
  {
    return assessmentAnswers[assesseeAddress];
  }

  function setResult(address assessorAddress, bool pass, uint score)
  {
    Results memory results;
    results.pass = pass;
    results.score = score;
    assessmentResults[a] = results;
  }

  function assess()
  {

  }

  function calculateResult()
  {

  }

  function returnResults()
  {
    Tag(tag).finishAssessment(finalResult, finalScore, assessee, address(this));
  }

  function cashout()
  {

  }
}

contract User
{
  address user;
  address master;
  address[] acheivements;
  string userData;

<<<<<<< HEAD
  function User(address userAddress, address masterAddress, string ipfsHash)
  {
    user = userAddress;
    master = masterAddress;
    userData = ipfsHash;
  }

=======
  function User(address u, address m)
  {
    user = u;
    master = m;
  }

  function setUserData(string hash)
  {
    userData hash;
  }

  function getUserData() returns(string)
  {
      return userData;
  }
>>>>>>> 61c1a726e1d14df3ac21e8924e1029ac230d9559
}


Modified set task for the new 1 on 1 sequence model of assessments. Jared microwaved an egg

contract Master
{
  //Initialize master data store
  mapping (address => uint) tokenBalance;
  mapping (address => string) tagName;
  mapping (string => address) tagAddressFromName;
  mapping (address => address[]) achievements;
  mapping (address => bool) availability;
  mapping (address => address) users;

  event TagCreation
  ( string _tagName,
    address _tagAddress,
    address[] _parents);

  function Master()
  {
    tokenBalance[address(this)] = 1;
    address[] memory a;
    uint useless = addTag("account", a);
  }

  function mapTokenBalance(address user, uint balance)
  {
    if(tagAddressFromName[tagName[msg.sender]] == 0)
    {
      tokenBalance[user] = balance;
    }
  }
  function mapTagName(address tagAddress, string name)
  {
    tagName[tagAddress] = name;
  }
  function mapTagAddressFromName(string name, address tagAddress)
  {
    tagAddressFromName[name] = tagAddress;
  }
  function mapAchievement(address user, address achievment)
  {
    achievements[user].push(achievment);
  }
  function mapAvailability(address user, bool available)
  {
    availability[user] = available;
  }

  function getTokenBalance(address user) returns(uint)
  {
    return tokenBalance[user];
  }
  function getTagName(address tagAddress) returns(string)
  {
    return tagName[tagAddress];
  }
  function getTagAddressFromName(string name) returns(address)
  {
    return tagAddressFromName[name];
  }
  function getAchievement(address user) returns(address[])
  {
    return achievements[user];
  }
  function getNumberOfachievments(address user) returns(uint)
  {
    return achievements[user].length;
  }
  function getAvailability(address user) returns(bool)
  {
    return availability[user] = true;
  }
  function getTagDescription(string nameOfTag) returns(string tagDescription)
  {
    return Tag(tagAddressFromName[nameOfTag]).getDescription();
  }

  function addUser()
  {
    User newUser = new User(msg.sender, address(this));
    Tag(tagAddressFromName["account"]).startAssessment(address(newUser),5);
  }

  function addTag(string name, address[] parentList, string description) returns(uint) //Creates a new tag contract
  {
    uint response = 0;
    address[] parents;
    if(tokenBalance[msg.sender] < 1)
    {
      response += 1;
    }
    if(tagAddressFromName[name] == 0)
    {
      response += 10;
    }
    if(response==0)
    {
      for(uint i=0; i<= parentList.length; i++) //adds all the given parents
      {
        if(parentList[i]==0)
        {
          response += 100*(10**i);
        }
        else
        {
          parents.push(parentList[i]);
        }
      }
      Tag newTag = new Tag(name, parents, address(this), description);
      address newTagAddress = address(newTag);
      tagName[newTagAddress] = name;
      tagAddressFromName[name] = newTagAddress;
      tokenBalance[msg.sender] -= 1;
      TagCreation(name, newTagAddress, parents);
    }
    return response;
  }
}

//Defines the meta-contract for a Tag
contract Tag
{
  address[] parentTags;
  address master;
  string name;
  string description;
  address[] owners; //Those who have earned the tag
  mapping(address => address[]) assessmentHistory; //All assessments completed
  mapping(address => uint) scores; //All positive assessements scores
  event CompletedAssessment
  ( address _assessee,
    bool _pass,
    uint _score,
    address _assessment);

  function Tag(string tagName, address[] parents, address masterAddress, string tagDescription)
  {
    name = tagName;
    parentTags = parents;
    master = masterAddress;
    description = tagDescription;
  }

  function getDescription() returns(string)
  {
    return description;
  }

  function getOwners() returns(address[])
  {
    return owners;
  }

  function getOwnerLength() returns(uint)
  {
    return owners.length;
  }

  function getOwner(uint index) returns(address)
  {
      return owners[index];
  }

  function getParents() returns(address[])
  {
    return parentTags;
  }

  function getParentsLength() returns(uint)
  {
    return parentTags.length;
  }

  function getParent(uint index) returns(address)
  {
      return parentTags[index];
  }

  function setAssessorPool(address tagAddress, address assessment)
  {
    for(uint i = 0; i < Tag(tagAddress).getOwnerLength() && Assessment(assessment).getAssessmentPoolSize() != 0; i++)
    {
      if(Assessment(assessment).getAssessorPoolLength() < Tag(tagAddress).getOwnerLength()/10)
      {
        address random = Tag(tagAddress).getOwner(getRandom(Tag(tagAddress).getOwnerLength()-1));
        if(Master(master).getAvailability(random) == true)
        {
          Assessment(assessment).addToAssessorPool(random);
          Assessment(assessment).setAssessmentPoolSize(Assessment(assessment).getAssessmentPoolSize() -1);
        }
      }
      else
      {
        for(uint j = 0; j < Tag(tagAddress).getParentsLength(); j++)
        {
          setAssessorPool(Tag(tagAddress).getParent(j), assessment);
        }
      }
      if(Assessment(assessment).getAssessmentPoolSize() <= 0)
      {
        Assessment(assessment).setPotentialAssessors(Assessment(assessment).getNumberOfAssessors());
      }
    }
  }

  function startAssessment(address assessee, uint size)
  {
    Assessment newAssessment = new Assessment(assessee, address(this), master);
    newAssessment.setNumberOfAssessors(size);
    newAssessment.setAssessmentPoolSize(size*20);
    setAssessorPool(address(this), address(newAssessment));
  }

  function finishAssessment(bool pass, uint score, address assessee, address assessment)
  {
    if(pass == true)
    {
      owners.push(assessee);
      scores[assessee] = score;
      Master(master).mapAchievement(assessee,address(this));
    }
    if(pass == false && address(this) == Master(master).getTagAddressFromName("account"))
    {
      User(assessee).suicide();
    }
    assessmentHistory[assessee].push(assessment);
    CompletedAssessment(assessee, pass, score, assessment);
  }
  function getRandom(uint i) returns(uint)
  {
    return 12;
  }
}

//Defines the meta-contract for an assessment
contract Assessment
{
  address assessee; //We need a better word for this
  address[] assessorPool;
  mapping (address => uint) assessors;
  address[] finalAssessors;
  address tag;
  address master;
  uint poolSizeRemaining;
  uint numberOfAssessors;
  struct Results
  {
    bool pass;
    uint score;
  }
  mapping(address => string) assessmentTasks; //Given by the assessors as IPFS hashes
  mapping(address => string) assessmentResponses; //Given by the assessee as IPFS hashes
  mapping(address => Results) assessmentResults; //Pass/Fail and Score given by assessors
  address currentAssessor;
  uint finalScore;
  bool finalResult;
  uint taskCreationTime;
  uint taskCompletionTime;
  uint referenceTime;
  uint numberCancelled;

  function Assessment(address assesseeAddress, address tagAddress, address masterAddress, uint timeForTaskCreation)
  {
    assessee = assesseeAddress;
    tag = tagAddress;
    master = masterAddress;
    startReferenceTime = block.timestamp;
    taskCreationTime = timeForTaskCreation;
  }

  function setNumberOfAssessors(uint number)
  {
    numberOfAssessors = number;
  }

  function getNumberOfAssessors() returns(uint)
  {
    return numberOfAssessors;
  }

  function setAssessmentPoolSize(uint sizeRemaining)
  {
    poolSizeRemaining = sizeRemaining;
  }

  function getAssessmentPoolSize() returns(uint)
  {
    return poolSizeRemaining;
  }

  function addToAssessorPool(address potentialAddress)
  {
    assessorPool.push(potentialAddress);
  }

  function setPotentialAssessor()
  {
    bool potentialAssessorSet = false;
    while(potentialAssessorSet == false)
    {
      address randomAssessor = assessorPool[getRandom(assessorPool.length)];
      if(assessors[randomAssessor] == 0)
      {
        assessors[randomAssessor] = 3;
        currentAssessor = andomAssessor;
        potentialAssessorSet = true;
        User(randomAssessor).notification("Called As A Potential Assessor",tag, 1);
      }
    }
    referenceTime = now;
  }

  function getAssessorPoolLength() returns(uint)
  {
      return assessorPool.length;
  }

  function getRandom(uint i) returns(uint)
  {
    return 12;
  }

  function setTask(string data)
  {
    if(numberCancelled >= numberOfAssessors)
    {
      cancelAssessment();
    }
    if(assessors[currentAssessor] == 5 && now - referenceTime <= taskCreationTime)
    {
      assessmentTasks[currentAssessor] = data;
      assessors[currentAssessor = 6;
      User(currentAssessor).notification("Task Data Inputted", tag, 5);
      User(assessee).notification("New Task Available", tag, 7)
    }
    if(now - referenceTime > taskCreationTime && assessors[currentAssessor]!=5);
    {
      User(currentAssessor).notification("Did Not Submit Task On Time", tag, 6);
      Master(master).mapTokenBalance(currentAssessor, Master(master).getTokenBalance(currentAssessor) - 1);
      User(currentAssessor).setReputation(User(currentAssessor).getReputation() + 1);
      numberCancelled++;
      setPotentialAssessor;
    }
  }

  function cancelAssessment()
  {
    User(assessee).notification("Assessment Cancled", tag, 8);
    for(uint i = 0; i < finalAssessors.length; i++)
    {
      User(finalAssessors[i]).notification("Assessment Cancled", tag, 8);
    }
    selfdestruct(master);
  }

  function getTask(address assessorAddress) returns(string)
  {
    return assessmentTasks[assessorAddress];
  }

  function setResponse(address assesseeAddress, string data)
  {
    assessmentResponses[assesseeAddress] = data;
  }

  function getResponse(address assesseeAddress) returns(string)
  {
    return assessmentResponses[assesseeAddress];
  }

  function setResult(bool pass, uint score)
  {
    Results memory results;
    results.pass = pass;
    results.score = score;
    assessmentResults[msg.sender] = results;
  }

  function assess()
  {

  }

  function calculateResult()
  {

  }

  function confirmAssessor(uint confirm, bool timeKnow)
  {
    if(numberCancelled >= numberOfAssessors)
    {
      cancelAssessment();
    }
    if(assessors[currentAssessor]] != 0 && now - referenceTime <= 180)
    {
      assessors[currentAssessor]] = confirm;
      if(confirm == 1)
      {
        User(currentAssessor).notification("The Time Allocated For Setting The Assessment Task Is:" + taskCreationTime, tag, 2);
        referenceTime = now;
      }
      if(confirm == 2 || confirm == 4)
      {
        User(currentAssessor).notification("Confirmed As Not Assessing", tag, 3);
        numberCancelled ++;
        setPotentialAssessor();
      }
      if(confirm == 5)
      {
        User(currentAssessor).notification("Confirmed As Assessing", tag, 9);
        referenceTime = now;
      }
    }
    if(now - confirmationReferenceTime > 180)
    {
      if(timeKnow == false && assessors[currentAssessor]]==3)
      {
      User(currentAssessor).notification("Did Not Respond In Time To Be Assessor", tag, 4);
      Master(master).mapTokenBalance(currentAssessor, Master(master).getTokenBalance(currentAssessor) - 1);
      setPotentialAssessor();
      }
      if(timeKnow == true && assessors[currentAssessor]==1)
      {
        User(currentAssessor).notification("Did Not Respond In Time To Be Assessor", tag, 4);
        setPotentialAssessor();
      }
    }
  }

  function returnResults()
  {
    Tag(tag).finishAssessment(finalResult, finalScore, assessee, address(this));
  }

  function cashout()
  {

  }
}

contract User
{
  address user;
  address master;
  address[] acheivements;
  string userData;
  uint reputation;

  event Notification
  ( string _description,
    address _sender,
    address _user,
    address _tag,
    uint _code);

  function User(address userAddress, address masterAddress)
  {
    user = userAddress;
    master = masterAddress;
    reputation = 1;
  }

  function getReputation() returns uint
  {
    return reputation;
  }

  function setReputation(uint newReputation)
  {
    reputation = newReputation;
  }

  function notification(string description, address tag, uint code)
  {
    Notification(description, msg.sender, address(this), tag, code);
  }

  function setUserData(string hash)
  {
    userData = hash;
  }

  function getUserData() returns(string)
  {
    return userData;
  }

  function suicide()
  {
    selfdestruct(master);
  }
}

contract Master
{
  //Initialize master data store
  mapping (address => uint) tokenBalance;
  mapping (address => string) tagName;
  mapping (string => address) tagAddressFromName;
  mapping (address => address[]) achievements;
  mapping (address => bool) availability;
  mapping (address => address) users;

  event TagCreation
  ( string _tagName,
    address _tagAddress,
    address[] _parents);

  function Master()
  {
    tokenBalance[address(this)] = 1;
    address[] memory a;
    uint useless = addTag("account", a);
  }

  function mapTokenBalance(address user, uint balance)
  {
    if(tagAddressFromName[tagName[msg.sender]] == 0)
    {
      tokenBalance[user] = balance;
    }
  }
  function mapTagName(address tagAddress, string name)
  {
    tagName[tagAddress] = name;
  }
  function mapTagAddressFromName(string name, address tagAddress)
  {
    tagAddressFromName[name] = tagAddress;
  }
  function mapAchievement(address user, address achievment)
  {
    achievements[user].push(achievment);
  }
  function mapAvailability(address user, bool available)
  {
    availability[user] = available;
  }

  function getTokenBalance(address user) returns(uint)
  {
    return tokenBalance[user];
  }
  function getTagName(address tagAddress) returns(string)
  {
    return tagName[tagAddress];
  }
  function getTagAddressFromName(string name) returns(address)
  {
    return tagAddressFromName[name];
  }
  function getAchievement(address user) returns(address[])
  {
    return achievements[user];
  }
  function getNumberOfachievments(address user) returns(uint)
  {
    return achievements[user].length;
  }
  function getAvailability(address user) returns(bool)
  {
    return availability[user] = true;
  }
  function getTagDescription(string nameOfTag) returns(string tagDescription)
  {
    return Tag(tagAddressFromName[nameOfTag]).getDescription();
  }

  function addUser()
  {
    User newUser = new User(msg.sender, address(this));
    Tag(tagAddressFromName["account"]).startAssessment(address(newUser),5);
  }

  function addTag(string name, address[] parentList, string description) returns(uint) //Creates a new tag contract
  {
    uint response = 0;
    address[] parents;
    if(tokenBalance[msg.sender] < 1)
    {
      response += 1;
    }
    if(tagAddressFromName[name] == 0)
    {
      response += 10;
    }
    if(response==0)
    {
      for(uint i=0; i<= parentList.length; i++) //adds all the given parents
      {
        if(parentList[i]==0)
        {
          response += 100*(10**i);
        }
        else
        {
          parents.push(parentList[i]);
        }
      }
      Tag newTag = new Tag(name, parents, address(this), description);
      address newTagAddress = address(newTag);
      tagName[newTagAddress] = name;
      tagAddressFromName[name] = newTagAddress;
      tokenBalance[msg.sender] -= 1;
      TagCreation(name, newTagAddress, parents);
    }
    return response;
  }
}

//Defines the meta-contract for a Tag
contract Tag
{
  address[] parentTags;
  address master;
  string name;
  string description;
  address[] owners; //Those who have earned the tag
  mapping(address => address[]) assessmentHistory; //All assessments completed
  mapping(address => uint) scores; //All positive assessements scores
  event CompletedAssessment
  ( address _assessee,
    bool _pass,
    uint _score,
    address _assessment);

  function Tag(string tagName, address[] parents, address masterAddress, string tagDescription)
  {
    name = tagName;
    parentTags = parents;
    master = masterAddress;
    description = tagDescription;
  }

  function getDescription() returns(string)
  {
    return description;
  }

  function getOwners() returns(address[])
  {
    return owners;
  }

  function getOwnerLength() returns(uint)
  {
    return owners.length;
  }

  function getOwner(uint index) returns(address)
  {
      return owners[index];
  }

  function getParents() returns(address[])
  {
    return parentTags;
  }

  function getParentsLength() returns(uint)
  {
    return parentTags.length;
  }

  function getParent(uint index) returns(address)
  {
      return parentTags[index];
  }

  function setAssessorPool(address tagAddress, address assessment)
  {
    for(uint i = 0; i < Tag(tagAddress).getOwnerLength() && Assessment(assessment).getAssessmentPoolSize() != 0; i++)
    {
      if(Assessment(assessment).getAssessorPoolLength() < Tag(tagAddress).getOwnerLength()/10)
      {
        address random = Tag(tagAddress).getOwner(getRandom(Tag(tagAddress).getOwnerLength()-1));
        if(Master(master).getAvailability(random) == true)
        {
          Assessment(assessment).addToAssessorPool(random);
          Assessment(assessment).setAssessmentPoolSize(Assessment(assessment).getAssessmentPoolSize() -1);
        }
      }
      else
      {
        for(uint j = 0; j < Tag(tagAddress).getParentsLength(); j++)
        {
          setAssessorPool(Tag(tagAddress).getParent(j), assessment);
        }
      }
      if(Assessment(assessment).getAssessmentPoolSize() <= 0)
      {
        Assessment(assessment).setPotentialAssessors(Assessment(assessment).getNumberOfAssessors());
      }
    }
  }

  function startAssessment(address assessee, uint size)
  {
    Assessment newAssessment = new Assessment(assessee, address(this), master);
    newAssessment.setNumberOfAssessors(size);
    newAssessment.setAssessmentPoolSize(size*20);
    setAssessorPool(address(this), address(newAssessment));
  }

  function finishAssessment(bool pass, uint score, address assessee, address assessment)
  {
    if(pass == true)
    {
      owners.push(assessee);
      scores[assessee] = score;
      Master(master).mapAchievement(assessee,address(this));
    }
    if(pass == false && address(this) == Master(master).getTagAddressFromName("account"))
    {
      User(assessee).suicide();
    }
    assessmentHistory[assessee].push(assessment);
    CompletedAssessment(assessee, pass, score, assessment);
  }
  function getRandom(uint i) returns(uint)
  {
    return 12;
  }
}

//Defines the meta-contract for an assessment
contract Assessment
{
  address assessee; //We need a better word for this
  address[] assessorPool;
  mapping (address => uint) assessors;
  address[] potentialAssessors;
  address[] finalAssessors;
  address tag;
  address master;
  uint poolSizeRemaining;
  uint numberOfAssessors;
  struct Results
  {
    bool pass;
    uint score;
  }
  mapping(address => string) assessmentTasks; //Given by the assessors as IPFS hashes
  mapping(address => string) assessmentResponses; //Given by the assessee as IPFS hashes
  mapping(address => Results) assessmentResults; //Pass/Fail and Score given by assessors
  uint finalScore;
  bool finalResult;
  uint taskCreationTime;
  uint taskCompletionTime;
  uint referenceTime;
  uint numberCancelled;

  function Assessment(address assesseeAddress, address tagAddress, address masterAddress, uint timeForTaskCreation)
  {
    assessee = assesseeAddress;
    tag = tagAddress;
    master = masterAddress;
    startReferenceTime = block.timestamp;
    taskCreationTime = timeForTaskCreation;
  }

  function setNumberOfAssessors(uint number)
  {
    numberOfAssessors = number;
  }

  function getNumberOfAssessors() returns(uint)
  {
    return numberOfAssessors;
  }

  function setAssessmentPoolSize(uint sizeRemaining)
  {
    poolSizeRemaining = sizeRemaining;
  }

  function getAssessmentPoolSize() returns(uint)
  {
    return poolSizeRemaining;
  }

  function addToAssessorPool(address potentialAddress)
  {
    assessorPool.push(potentialAddress);
  }

  function setPotentialAssessor()
  {
    bool potentialAssessorSet = false;
    while(potentialAssessorSet == false)
    {
      address randomAssessor = assessorPool[getRandom(assessorPool.length)];
      if(assessors[randomAssessor] == 0)
      {
        assessors[randomAssessor] = 3;
        potentialAssessors.push(randomAssessor);
        potentialAssessorSet = true;
        User(randomAssessor).notification("Called As A Potential Assessor",tag, 1);
      }
    }
    referenceTime = now;
  }

  function getAssessorPoolLength() returns(uint)
  {
      return assessorPool.length;
  }

  function getRandom(uint i) returns(uint)
  {
    return 12;
  }

  function setTask(string data)
  {
    if(assessors[msg.sender] == 1 && now - taskSettingReferenceTime <= 3600)
    {
      assessmentTasks[msg.sender] = data;
      assessors[msg.sender] = 4;
      User(msg.sender).notification("Task Data Inputted", tag, 5);
      User(assessee).notification("New Task Available", tag, 7)
    }
    if(now - taskSettingReferenceTime > 3600)
    {
      bool invalidAssessment = false;
      for(uint i = 0; i < finalAssessors.length; i++)
      {
        if(assessors[finalAssessors[i]]!=4)
        {
          User(finalAssessors[i]).notification("Did Not Submit Task On Time", tag, 6);
          Master(master).mapTokenBalance(finalAssessors[i], Master(master).getTokenBalance(finalAssessors[i]) - 1);
          User(finalAssessors[i]).setReputation(User(finalAssessors[i]).getReputation() + 1);
          invalidAssessment = true;
        }
      }
      if(invalidAssessment = true)
      {
        cancelAssessment();
      }
    }
    uint totalStatus
    for(uint i = 0; i < finalAssessors.length; i++)
    {
      totalStatus += assessors[finalAssessors[i]];
    }
    if(totalStatus/4 == numberOfAssessors)
    {
      referenceTime = now;
    }
  }

  function cancelAssessment()
  {
    User(assessee).notification("Assessment Cancled", tag, 8);
    for(uint i = 0; i < finalAssessors.length; i++)
    {
      User(finalAssessors[i]).notification("Assessment Cancled", tag, 8);
    }
    selfdestruct(master);
  }

  function getTask(address assessorAddress) returns(string)
  {
    return assessmentTasks[assessorAddress];
  }

  function setResponse(address assesseeAddress, string data)
  {
    assessmentResponses[assesseeAddress] = data;
  }

  function getResponse(address assesseeAddress) returns(string)
  {
    return assessmentResponses[assesseeAddress];
  }

  function setResult(bool pass, uint score)
  {
    Results memory results;
    results.pass = pass;
    results.score = score;
    assessmentResults[msg.sender] = results;
  }

  function assess()
  {

  }

  function calculateResult()
  {

  }

  function confirmAssessor(uint confirm, bool timeKnow)
  {
    if(numberCancelled >= numberOfAssessors)
    {
      cancelAssessment();
    }
    if(assessors[potentialAssessors[potentialAssessors.length - 1]] != 0 && now - referenceTime <= 180)
    {
      assessors[potentialAssessors[potentialAssessors.length - 1]] = confirm;
      if(confirm == 1)
      {
        User(potentialAssessors[potentialAssessors.length -1]).notification("The Time Allocated For Setting The Assessment Task Is:" + taskCreationTime, tag, 2);
        referenceTime = now;
      }
      if(confirm == 2 || confirm == 4)
      {
        User(potentialAssessors[potentialAssessors.length -1]).notification("Confirmed As Not Assessing", tag, 3);
        numberCancelled ++;
        setPotentialAssessor();
      }
      if(confirm == 5)
      {
        finalAssessors.push(potentialAssessors[potentialAssessors.length -1]);
        User(potentialAssessors[potentialAssessors.length -1]).notification("Confirmed As Assessing", tag, 9);
        referenceTime = now;
      }
    }
    if(now - confirmationReferenceTime > 180)
    {
      if(timeKnow == false && assessors[potentialAssessors[potentialAssessors.length -1]]==3)
      {
      User(potentialAssessors[potentialAssessors.length -1]).notification("Did Not Respond In Time To Be Assessor", tag, 4);
      Master(master).mapTokenBalance(potentialAssessors[potentialAssessors.length -1],
        Master(master).getTokenBalance(potentialAssessors[potentialAssessors.length -1]) - 1);
      setPotentialAssessor();
      }
      if(timeKnow == true && assessors[potentialAssessors[potentialAssessors.length -1]]==1)
      {
        User(potentialAssessors[potentialAssessors.length -1]).notification("Did Not Respond In Time To Be Assessor", tag, 4);
        setPotentialAssessor();
      }
    }
  }

  function returnResults()
  {
    Tag(tag).finishAssessment(finalResult, finalScore, assessee, address(this));
  }

  function cashout()
  {

  }
}

contract User
{
  address user;
  address master;
  address[] acheivements;
  string userData;
  uint reputation;

  event Notification
  ( string _description,
    address _sender,
    address _user,
    address _tag,
    uint _code);

  function User(address userAddress, address masterAddress)
  {
    user = userAddress;
    master = masterAddress;
    reputation = 1;
  }

  function getReputation() returns uint
  {
    return reputation;
  }

  function setReputation(uint newReputation)
  {
    reputation = newReputation;
  }

  function notification(string description, address tag, uint code)
  {
    Notification(description, msg.sender, address(this), tag, code);
  }

  function setUserData(string hash)
  {
    userData = hash;
  }

  function getUserData() returns(string)
  {
    return userData;
  }

  function suicide()
  {
    selfdestruct(master);
  }
}


Fixes typo in SafeMath subtraction docs (#806)

pragma solidity ^0.4.18;

/**
 * @title SafeMath
 * @dev Math operations with safety checks that throw on error
 */
library SafeMath {

  /**
  * @dev Multiplies two numbers, throws on overflow.
  */
  function mul(uint256 a, uint256 b) internal pure returns (uint256) {
    if (a == 0) {
      return 0;
    }
    uint256 c = a * b;
    assert(c / a == b);
    return c;
  }

  /**
  * @dev Integer division of two numbers, truncating the quotient.
  */
  function div(uint256 a, uint256 b) internal pure returns (uint256) {
    // assert(b > 0); // Solidity automatically throws when dividing by 0
    uint256 c = a / b;
    // assert(a == b * c + a % b); // There is no case in which this doesn't hold
    return c;
  }

  /**
  * @dev Subtracts two numbers, throws on overflow (i.e. if subtrahend is greater than minuend).
  */
  function sub(uint256 a, uint256 b) internal pure returns (uint256) {
    assert(b <= a);
    return a - b;
  }

  /**
  * @dev Adds two numbers, throws on overflow.
  */
  function add(uint256 a, uint256 b) internal pure returns (uint256) {
    uint256 c = a + b;
    assert(c >= a);
    return c;
  }
}

pragma solidity ^0.4.18;

/**
 * @title SafeMath
 * @dev Math operations with safety checks that throw on error
 */
library SafeMath {

  /**
  * @dev Multiplies two numbers, throws on overflow.
  */
  function mul(uint256 a, uint256 b) internal pure returns (uint256) {
    if (a == 0) {
      return 0;
    }
    uint256 c = a * b;
    assert(c / a == b);
    return c;
  }

  /**
  * @dev Integer division of two numbers, truncating the quotient.
  */
  function div(uint256 a, uint256 b) internal pure returns (uint256) {
    // assert(b > 0); // Solidity automatically throws when dividing by 0
    uint256 c = a / b;
    // assert(a == b * c + a % b); // There is no case in which this doesn't hold
    return c;
  }

  /**
  * @dev Substracts two numbers, throws on overflow (i.e. if subtrahend is greater than minuend).
  */
  function sub(uint256 a, uint256 b) internal pure returns (uint256) {
    assert(b <= a);
    return a - b;
  }

  /**
  * @dev Adds two numbers, throws on overflow.
  */
  function add(uint256 a, uint256 b) internal pure returns (uint256) {
    uint256 c = a + b;
    assert(c >= a);
    return c;
  }
}