fixed an issue that prevented the owner from starting a crowdsale

pragma solidity ^0.4.9;
import "owned.sol";

/*
    Open issues:
    - throw vs. return value?
    - possibly add modifiers for each stage
    - possibly create a shared standard token contract and inherit from it, both for the BancorToken and for the BancorEtherToken
    - add miner abuse protection
    - allow exchanging between 2 reserve tokens directly? can be done through a 3rd party contract
    - startTrading - looping over the reserve - can run out of gas. Possibly split it and do it as a multi-step process
    - approve - to minimize the risk of the approve/transferFrom attack vector
                (see https://docs.google.com/document/d/1YLPtQxZu1UAvO9cZ1O2RPXBbT0mooh4DYKjA_jp-RLM/), approve has to be called twice
                in 2 separate transactions - once to change the allowance to 0 and secondly to change it to the new allowance value.
                Also relevant to the BancorEtherToken
*/

// interfaces

contract ReserveToken { // any ERC20 standard token
    function balanceOf(address _owner) public constant returns (uint256 balance);
    function transfer(address _to, uint256 _value) public returns (bool success);
    function transferFrom(address _from, address _to, uint256 _value) public returns (bool success);
}

contract BancorFormula {
    function calculatePurchaseValue(uint256 _supply, uint256 _reserveBalance, uint16 _reserveRatio, uint256 _depositAmount) public constant returns (uint256 value);
    function calculateSaleValue(uint256 _supply, uint256 _reserveBalance, uint16 _reserveRatio, uint256 _sellAmount) public constant returns (uint256 value);
    function newFormula() public constant returns (address newFormula);
}

contract BancorEvents {
    function newToken() public;
    function tokenUpdate() public;
    function tokenTransfer(address _from, address _to, uint256 _value) public;
    function tokenApproval(address _owner, address _spender, uint256 _value) public;
    function tokenConversion(address _reserveToken, address _trader, bool _isPurchase, uint256 _totalSupply,
                             uint256 _reserveBalance, uint256 _tokenAmount, uint256 _reserveAmount) public;
}

/*
    Bancor Token v0.2
*/
contract BancorToken is owned {
    enum Stage { Managed, Crowdsale, Traded }

    string public standard = 'Token 0.1';
    string public name = "";
    string public symbol = "";                          // 1-6 characters
    uint8 public numDecimalUnits = 0;                   // for display purposes only
    uint256 public totalSupply = 0;
    address public formula = 0x0;                       // bancor calculation formula contract address
    address public events = 0x0;                        // bancor events contract address
    address public crowdsale = 0x0;                     // crowdsale contract address
    uint256 public crowdsaleAllowance = 0;              // current number of tokens the crowdsale contract is allowed to issue
    Stage public stage = Stage.Managed;                 // token stage
    address[] public reserveTokens;                     // ERC20 standard token addresses
    mapping (address => uint8) public reserveRatioOf;   // token addresses -> constant reserve ratio, 1-99
    mapping (address => uint256) public balanceOf;
    mapping (address => mapping (address => uint256)) public allowance;

    // events, can be used to listen to the contract directly, as opposed to through the events contract
    event Update();
    event Transfer(address indexed _from, address indexed _to, uint256 _value);
    event Approval(address indexed _owner, address indexed _spender, uint256 _value);
    event Conversion(address indexed _reserveToken, address indexed _trader, bool _isPurchase,
                     uint256 _totalSupply, uint256 _reserveBalance, uint256 _tokenAmount, uint256 _reserveAmount);

    /*
        _name               token name
        _symbol             token short symbol
        _numDecimalUnits    for display purposes only
        _formula            address of a bancor formula contract
        _events             optional, address of a bancor events contract
    */
    function BancorToken(string _name, string _symbol, uint8 _numDecimalUnits, address _formula, address _events) {
        if (bytes(_name).length == 0 || bytes(_symbol).length < 1 || bytes(_symbol).length > 6 || _formula == 0x0) // validate input
            throw;

        name = _name;
        symbol = _symbol;
        numDecimalUnits = _numDecimalUnits;
        formula = _formula;
        events = _events;

        if (events == 0x0)
            return;

        BancorEvents eventsContract = BancorEvents(events);
        eventsContract.newToken();
    }

    // allows executing a function by the owner in managed stage or by the crowdsale contract in crowdsale stage
    modifier onlyManager {
        if (stage == Stage.Traded ||
            stage == Stage.Managed && msg.sender != owner ||
            stage == Stage.Crowdsale && msg.sender != crowdsale) // validate state & permissions
            throw;
        _;
    }

    /*
        updates the bancor calculation formula contract address
        can only be called by the token owner

        the owner can only update the formula to a new one approved by the current formula's owner

        _formula     new formula contract address
    */
    function setFormula(address _formula) public onlyOwner returns (bool success) {
        BancorFormula formulaContract = BancorFormula(formula);
        if (formulaContract.newFormula() != _formula)
            throw;

        formula = _formula;
        return true;
    }

    /*
        returns the number of reserve tokens defined
    */
    function reserveTokenCount() public returns (uint8 count) {
        return uint8(reserveTokens.length);
    }

    /*
        defines a new reserve for the token (managed stage only)
        can only be called by the token owner

        _token  address of the reserve token
        _ratio  constant reserve ratio, 1-99
    */
    function addReserve(address _token, uint8 _ratio) public onlyOwner returns (bool success) {
        if (reserveRatioOf[_token] != 0 || _ratio < 1 || _ratio > 99) // validate input
            throw;
        if (stage != Stage.Managed) // validate state
            throw;

        reserveRatioOf[_token] = _ratio;
        reserveTokens.push(_token);
        dispatchUpdate();
        return true;
    }

    /*
        increases the token supply and sends the new tokens to an account
        can only be called by the token owner (in managed stage only) or the crowdsale contract (in crowdsale stage only)

        _to         account to receive the new amount
        _amount     amount to increase the supply by
    */
    function issue(address _to, uint256 _amount) public onlyManager returns (bool success) {
        if (totalSupply + _amount < totalSupply) // supply overflow protection
            throw;
        if (balanceOf[_to] + _amount < balanceOf[_to]) // target account balance overflow protection
            throw;
        if (stage == Stage.Crowdsale && _amount > crowdsaleAllowance) // the crowdsale contract is trying to issue more tokens than allowed
            throw;

        totalSupply += _amount;
        balanceOf[_to] += _amount;
        if (stage == Stage.Crowdsale)
            crowdsaleAllowance -= _amount;

        dispatchUpdate();
        dispatchTransfer(this, _to, _amount);
        return true;
    }

    /*
        Removes tokens from an account and decreases the token supply
        can only be called by the token owner (in managed stage only) or the crowdsale contract (in crowdsale stage only)

        _from       account to remove the new amount from
        _amount     amount to decrease the supply by
    */
    function destroy(address _from, uint256 _amount) public onlyManager returns (bool success) {
        if (_amount > totalSupply) // negative supply protection
            throw;
        if (_amount > balanceOf[_from]) // target account negative balance protection
            throw;

        totalSupply -= _amount;
        balanceOf[_from] -= _amount;
        dispatchUpdate();
        dispatchTransfer(_from, this, _amount);
        return true;
    }

    /*
        withdraws tokens from the reserve and sends them to an account
        can only be called by the token owner (in managed stage only) or the crowdsale contract (in crowdsale stage only)

        _reserveToken    reserve token contract address
        _to              account to receive the new amount
        _amount          amount to withdraw (in the reserve token)
    */
    function withdraw(address _reserveToken, address _to, uint256 _amount) public onlyManager returns (bool success) {
        if (reserveRatioOf[_reserveToken] == 0 || _amount == 0) // validate input
            throw;

        ReserveToken reserveToken = ReserveToken(_reserveToken);
        return reserveToken.transfer(_to, _amount);
    }

    /*
        starts the crowdsale stage (managed stage only)
        can only be called by the token owner

        _crowdsale     new crowdsale contract address
    */
    function startCrowdsale(address _crowdsale, uint256 _allowance) public onlyOwner returns (bool success) {
        if (stage != Stage.Managed || reserveTokens.length == 0) // validate state
            throw;

        crowdsale = _crowdsale;
        crowdsaleAllowance = _allowance;
        stage = Stage.Crowdsale;
        dispatchUpdate();
        return true;
    }

    /*
        starts the traded stage
        can only be called by the token owner (in managed stage only) or the crowdsale contract (in crowdsale stage only)
    */
    function startTrading() public onlyManager returns (bool success) {
        if (totalSupply == 0) // validate state
            throw;

        // make sure that there's balance in all the reserves
        for (uint16 i = 0; i < reserveTokens.length; ++i) {
            ReserveToken reserveToken = ReserveToken(reserveTokens[i]);
            if (reserveToken.balanceOf(this) == 0)
                throw;
        }

        stage = Stage.Traded;
        dispatchUpdate();
        return true;
    }

    /*
        buys the token by depositing one of its reserve tokens

        _reserveToken   reserve token contract address
        _depositAmount  amount to deposit (in the reserve token)
        _minimumValue   if the conversion results in a value smaller than this value, it is cancelled
    */
    function buy(address _reserveToken, uint256 _depositAmount, uint256 _minimumValue) public returns (uint256 value) {
        uint8 reserveRatio = reserveRatioOf[_reserveToken];
        if (reserveRatio == 0 || _depositAmount == 0) // validate input
            throw;
        if (stage != Stage.Traded) // validate state
            throw;

        ReserveToken reserveToken = ReserveToken(_reserveToken);
        uint256 reserveBalance = reserveToken.balanceOf(this);

        BancorFormula formulaContract = BancorFormula(formula);
        value = formulaContract.calculatePurchaseValue(totalSupply, reserveBalance, reserveRatio, _depositAmount);
        if (value == 0 || value < _minimumValue) // trade gave nothing in return or didn't return a value that meets the minimum requested value
            throw;
        if (totalSupply + value < totalSupply) // supply overflow protection
            throw;
        if (!reserveToken.transferFrom(msg.sender, this, _depositAmount)) // can't withdraw funds from the reserve token
            throw;

        uint256 startSupply = totalSupply;
        totalSupply += value;
        balanceOf[msg.sender] += value;
        dispatchConversion(_reserveToken, msg.sender, true, startSupply, reserveBalance, value, _depositAmount);
        return value;
    }

    /*
        sells the token for one of its reserve tokens

        _reserveToken   reserve token contract address
        _sellAmount     amount to sell (in the token)
        _minimumValue   if the conversion results in a value smaller than this value, it is cancelled
    */
    function sell(address _reserveToken, uint256 _sellAmount, uint256 _minimumValue) public returns (uint256 value) {
        uint8 reserveRatio = reserveRatioOf[_reserveToken];
        if (reserveRatio == 0 || _sellAmount == 0) // validate input
            throw;
        if (stage != Stage.Traded) // validate state
            throw;
        if (balanceOf[msg.sender] < _sellAmount) // balance check
            throw;

        ReserveToken reserveToken = ReserveToken(_reserveToken);
        uint256 reserveBalance = reserveToken.balanceOf(this);

        BancorFormula formulaContract = BancorFormula(formula);
        value = formulaContract.calculateSaleValue(totalSupply, reserveBalance, reserveRatio, _sellAmount);
        if (value == 0 || value < _minimumValue) // trade gave nothing in return or didn't return a value that meets the minimum requested value
            throw;
        if (reserveBalance <= value) // trade will deplete the reserve
            throw;

        uint256 startSupply = totalSupply;
        totalSupply -= _sellAmount;
        balanceOf[msg.sender] -= _sellAmount;
        if (!reserveToken.transfer(msg.sender, value)) // can't transfer funds to the caller
            throw;

        // if the supply was totally depleted, return to managed stage
        if (totalSupply == 0) {
            crowdsale = 0x0;
            crowdsaleAllowance = 0;
            stage = Stage.Managed;
        }

        dispatchConversion(_reserveToken, msg.sender, false, startSupply, reserveBalance, _sellAmount, value);
        return value;
    }

    // ERC20 standard methods

    // send coins
    function transfer(address _to, uint256 _value) public returns (bool success) {
        if (balanceOf[msg.sender] < _value) // balance check
            throw;
        if (balanceOf[_to] + _value < balanceOf[_to]) // overflow protection
            throw;

        balanceOf[msg.sender] -= _value;
        if (_to == address(this)) // transferring to the contract address destroys tokens
            totalSupply -= _value;
        else
            balanceOf[_to] += _value;

        dispatchTransfer(msg.sender, _to, _value);
        return true;
    }

    // allow another account/contract to spend some tokens on your behalf
    function approve(address _spender, uint256 _value) public returns (bool success) {
        // if the allowance isn't 0, it can only be updated to 0 to prevent an allowance change immediately after withdrawal
        if (_value != 0 && allowance[msg.sender][_spender] != 0)
            throw;

        allowance[msg.sender][_spender] = _value;

        Approval(msg.sender, _spender, _value);
        if (events == 0x0)
            return true;

        BancorEvents eventsContract = BancorEvents(events);
        eventsContract.tokenApproval(msg.sender, _spender, _value);
        return true;
    }

    // an account/contract attempts to get the coins
    function transferFrom(address _from, address _to, uint256 _value) public returns (bool success) {
        if (balanceOf[_from] < _value) // balance check
            throw;
        if (balanceOf[_to] + _value < balanceOf[_to]) // overflow protection
            throw;
        if (_value > allowance[_from][msg.sender]) // allowance check
            throw;

        balanceOf[_from] -= _value;
        balanceOf[_to] += _value;
        allowance[_from][msg.sender] -= _value;

        dispatchTransfer(_from, _to, _value);
        return true;
    }

    // utility

    function dispatchUpdate() private {
        Update();
        if (events == 0x0)
            return;

        BancorEvents eventsContract = BancorEvents(events);
        eventsContract.tokenUpdate();
    }

    function dispatchTransfer(address _from, address _to, uint256 _value) private {
        Transfer(_from, _to, _value);
        if (events == 0x0)
            return;

        BancorEvents eventsContract = BancorEvents(events);
        eventsContract.tokenTransfer(_from, _to, _value);
    }

    function dispatchConversion(address _reserveToken, address _trader, bool _isPurchase,
                                uint256 _totalSupply, uint256 _reserveBalance, uint256 _tokenAmount, uint256 _reserveAmount) private {
        Conversion(_reserveToken, _trader, _isPurchase, _totalSupply, _reserveBalance, _tokenAmount, _reserveAmount);
        if (events == 0x0)
            return;

        BancorEvents eventsContract = BancorEvents(events);
        eventsContract.tokenConversion(_reserveToken, _trader, _isPurchase, _totalSupply, _reserveBalance, _tokenAmount, _reserveAmount);
    }

    // fallback

    function() {
        throw;
    }
}

pragma solidity ^0.4.9;
import "owned.sol";

/*
    Open issues:
    - throw vs. return value?
    - possibly add modifiers for each stage
    - possibly create a shared standard token contract and inherit from it, both for the BancorToken and for the BancorEtherToken
    - add miner abuse protection
    - allow exchanging between 2 reserve tokens directly? can be done through a 3rd party contract
    - startTrading - looping over the reserve - can run out of gas. Possibly split it and do it as a multi-step process
    - approve - to minimize the risk of the approve/transferFrom attack vector
                (see https://docs.google.com/document/d/1YLPtQxZu1UAvO9cZ1O2RPXBbT0mooh4DYKjA_jp-RLM/), approve has to be called twice
                in 2 separate transactions - once to change the allowance to 0 and secondly to change it to the new allowance value.
                Also relevant to the BancorEtherToken
*/

// interfaces

contract ReserveToken { // any ERC20 standard token
    function balanceOf(address _owner) public constant returns (uint256 balance);
    function transfer(address _to, uint256 _value) public returns (bool success);
    function transferFrom(address _from, address _to, uint256 _value) public returns (bool success);
}

contract BancorFormula {
    function calculatePurchaseValue(uint256 _supply, uint256 _reserveBalance, uint16 _reserveRatio, uint256 _depositAmount) public constant returns (uint256 value);
    function calculateSaleValue(uint256 _supply, uint256 _reserveBalance, uint16 _reserveRatio, uint256 _sellAmount) public constant returns (uint256 value);
    function newFormula() public constant returns (address newFormula);
}

contract BancorEvents {
    function newToken() public;
    function tokenUpdate() public;
    function tokenTransfer(address _from, address _to, uint256 _value) public;
    function tokenApproval(address _owner, address _spender, uint256 _value) public;
    function tokenConversion(address _reserveToken, address _trader, bool _isPurchase, uint256 _totalSupply,
                             uint256 _reserveBalance, uint256 _tokenAmount, uint256 _reserveAmount) public;
}

/*
    Bancor Token v0.2
*/
contract BancorToken is owned {
    enum Stage { Managed, Crowdsale, Traded }

    string public standard = 'Token 0.1';
    string public name = "";
    string public symbol = "";                          // 1-6 characters
    uint8 public numDecimalUnits = 0;                   // for display purposes only
    uint256 public totalSupply = 0;
    address public formula = 0x0;                       // bancor calculation formula contract address
    address public events = 0x0;                        // bancor events contract address
    address public crowdsale = 0x0;                     // crowdsale contract address
    uint256 public crowdsaleAllowance = 0;              // current number of tokens the crowdsale contract is allowed to issue
    Stage public stage = Stage.Managed;                 // token stage
    address[] public reserveTokens;                     // ERC20 standard token addresses
    mapping (address => uint8) public reserveRatioOf;   // token addresses -> constant reserve ratio, 1-99
    mapping (address => uint256) public balanceOf;
    mapping (address => mapping (address => uint256)) public allowance;

    // events, can be used to listen to the contract directly, as opposed to through the events contract
    event Update();
    event Transfer(address indexed _from, address indexed _to, uint256 _value);
    event Approval(address indexed _owner, address indexed _spender, uint256 _value);
    event Conversion(address indexed _reserveToken, address indexed _trader, bool _isPurchase,
                     uint256 _totalSupply, uint256 _reserveBalance, uint256 _tokenAmount, uint256 _reserveAmount);

    /*
        _name               token name
        _symbol             token short symbol
        _numDecimalUnits    for display purposes only
        _formula            address of a bancor formula contract
        _events             optional, address of a bancor events contract
    */
    function BancorToken(string _name, string _symbol, uint8 _numDecimalUnits, address _formula, address _events) {
        if (bytes(_name).length == 0 || bytes(_symbol).length < 1 || bytes(_symbol).length > 6 || _formula == 0x0) // validate input
            throw;

        name = _name;
        symbol = _symbol;
        numDecimalUnits = _numDecimalUnits;
        formula = _formula;
        events = _events;

        if (events == 0x0)
            return;

        BancorEvents eventsContract = BancorEvents(events);
        eventsContract.newToken();
    }

    // allows executing a function by the owner in managed stage or by the crowdsale contract in crowdsale stage
    modifier onlyManager {
        if (stage == Stage.Traded ||
            stage == Stage.Managed && msg.sender != owner ||
            stage == Stage.Crowdsale && msg.sender != crowdsale) // validate state & permissions
            throw;
        _;
    }

    /*
        updates the bancor calculation formula contract address
        can only be called by the token owner

        the owner can only update the formula to a new one approved by the current formula's owner

        _formula     new formula contract address
    */
    function setFormula(address _formula) public onlyOwner returns (bool success) {
        BancorFormula formulaContract = BancorFormula(formula);
        if (formulaContract.newFormula() != _formula)
            throw;

        formula = _formula;
        return true;
    }

    /*
        returns the number of reserve tokens defined
    */
    function reserveTokenCount() public returns (uint8 count) {
        return uint8(reserveTokens.length);
    }

    /*
        defines a new reserve for the token (managed stage only)
        can only be called by the token owner

        _token  address of the reserve token
        _ratio  constant reserve ratio, 1-99
    */
    function addReserve(address _token, uint8 _ratio) public onlyOwner returns (bool success) {
        if (reserveRatioOf[_token] != 0 || _ratio < 1 || _ratio > 99) // validate input
            throw;
        if (stage != Stage.Managed) // validate state
            throw;

        reserveRatioOf[_token] = _ratio;
        reserveTokens.push(_token);
        dispatchUpdate();
        return true;
    }

    /*
        increases the token supply and sends the new tokens to an account
        can only be called by the token owner (in managed stage only) or the crowdsale contract (in crowdsale stage only)

        _to         account to receive the new amount
        _amount     amount to increase the supply by
    */
    function issue(address _to, uint256 _amount) public onlyManager returns (bool success) {
        if (totalSupply + _amount < totalSupply) // supply overflow protection
            throw;
        if (balanceOf[_to] + _amount < balanceOf[_to]) // target account balance overflow protection
            throw;
        if (stage == Stage.Crowdsale && _amount > crowdsaleAllowance) // the crowdsale contract is trying to issue more tokens than allowed
            throw;

        totalSupply += _amount;
        balanceOf[_to] += _amount;
        if (stage == Stage.Crowdsale)
            crowdsaleAllowance -= _amount;

        dispatchUpdate();
        dispatchTransfer(this, _to, _amount);
        return true;
    }

    /*
        Removes tokens from an account and decreases the token supply
        can only be called by the token owner (in managed stage only) or the crowdsale contract (in crowdsale stage only)

        _from       account to remove the new amount from
        _amount     amount to decrease the supply by
    */
    function destroy(address _from, uint256 _amount) public onlyManager returns (bool success) {
        if (_amount > totalSupply) // negative supply protection
            throw;
        if (_amount > balanceOf[_from]) // target account negative balance protection
            throw;

        totalSupply -= _amount;
        balanceOf[_from] -= _amount;
        dispatchUpdate();
        dispatchTransfer(_from, this, _amount);
        return true;
    }

    /*
        withdraws tokens from the reserve and sends them to an account
        can only be called by the token owner (in managed stage only) or the crowdsale contract (in crowdsale stage only)

        _reserveToken    reserve token contract address
        _to              account to receive the new amount
        _amount          amount to withdraw (in the reserve token)
    */
    function withdraw(address _reserveToken, address _to, uint256 _amount) public onlyManager returns (bool success) {
        if (reserveRatioOf[_reserveToken] == 0 || _amount == 0) // validate input
            throw;

        ReserveToken reserveToken = ReserveToken(_reserveToken);
        return reserveToken.transfer(_to, _amount);
    }

    /*
        starts the crowdsale stage (managed stage only)
        can only be called by the token owner

        _crowdsale     new crowdsale contract address
    */
    function startCrowdsale(address _crowdsale, uint256 _allowance) public onlyOwner returns (bool success) {
        if (stage != Stage.Managed || crowdsale == 0x0 || reserveTokens.length == 0) // validate state
            throw;

        crowdsale = _crowdsale;
        crowdsaleAllowance = _allowance;
        stage = Stage.Crowdsale;
        dispatchUpdate();
        return true;
    }

    /*
        starts the traded stage
        can only be called by the token owner (in managed stage only) or the crowdsale contract (in crowdsale stage only)
    */
    function startTrading() public onlyManager returns (bool success) {
        if (totalSupply == 0) // validate state
            throw;

        // make sure that there's balance in all the reserves
        for (uint16 i = 0; i < reserveTokens.length; ++i) {
            ReserveToken reserveToken = ReserveToken(reserveTokens[i]);
            if (reserveToken.balanceOf(this) == 0)
                throw;
        }

        stage = Stage.Traded;
        dispatchUpdate();
        return true;
    }

    /*
        buys the token by depositing one of its reserve tokens

        _reserveToken   reserve token contract address
        _depositAmount  amount to deposit (in the reserve token)
        _minimumValue   if the conversion results in a value smaller than this value, it is cancelled
    */
    function buy(address _reserveToken, uint256 _depositAmount, uint256 _minimumValue) public returns (uint256 value) {
        uint8 reserveRatio = reserveRatioOf[_reserveToken];
        if (reserveRatio == 0 || _depositAmount == 0) // validate input
            throw;
        if (stage != Stage.Traded) // validate state
            throw;

        ReserveToken reserveToken = ReserveToken(_reserveToken);
        uint256 reserveBalance = reserveToken.balanceOf(this);

        BancorFormula formulaContract = BancorFormula(formula);
        value = formulaContract.calculatePurchaseValue(totalSupply, reserveBalance, reserveRatio, _depositAmount);
        if (value == 0 || value < _minimumValue) // trade gave nothing in return or didn't return a value that meets the minimum requested value
            throw;
        if (totalSupply + value < totalSupply) // supply overflow protection
            throw;
        if (!reserveToken.transferFrom(msg.sender, this, _depositAmount)) // can't withdraw funds from the reserve token
            throw;

        uint256 startSupply = totalSupply;
        totalSupply += value;
        balanceOf[msg.sender] += value;
        dispatchConversion(_reserveToken, msg.sender, true, startSupply, reserveBalance, value, _depositAmount);
        return value;
    }

    /*
        sells the token for one of its reserve tokens

        _reserveToken   reserve token contract address
        _sellAmount     amount to sell (in the token)
        _minimumValue   if the conversion results in a value smaller than this value, it is cancelled
    */
    function sell(address _reserveToken, uint256 _sellAmount, uint256 _minimumValue) public returns (uint256 value) {
        uint8 reserveRatio = reserveRatioOf[_reserveToken];
        if (reserveRatio == 0 || _sellAmount == 0) // validate input
            throw;
        if (stage != Stage.Traded) // validate state
            throw;
        if (balanceOf[msg.sender] < _sellAmount) // balance check
            throw;

        ReserveToken reserveToken = ReserveToken(_reserveToken);
        uint256 reserveBalance = reserveToken.balanceOf(this);

        BancorFormula formulaContract = BancorFormula(formula);
        value = formulaContract.calculateSaleValue(totalSupply, reserveBalance, reserveRatio, _sellAmount);
        if (value == 0 || value < _minimumValue) // trade gave nothing in return or didn't return a value that meets the minimum requested value
            throw;
        if (reserveBalance <= value) // trade will deplete the reserve
            throw;

        uint256 startSupply = totalSupply;
        totalSupply -= _sellAmount;
        balanceOf[msg.sender] -= _sellAmount;
        if (!reserveToken.transfer(msg.sender, value)) // can't transfer funds to the caller
            throw;

        // if the supply was totally depleted, return to managed stage
        if (totalSupply == 0) {
            crowdsale = 0x0;
            crowdsaleAllowance = 0;
            stage = Stage.Managed;
        }

        dispatchConversion(_reserveToken, msg.sender, false, startSupply, reserveBalance, _sellAmount, value);
        return value;
    }

    // ERC20 standard methods

    // send coins
    function transfer(address _to, uint256 _value) public returns (bool success) {
        if (balanceOf[msg.sender] < _value) // balance check
            throw;
        if (balanceOf[_to] + _value < balanceOf[_to]) // overflow protection
            throw;

        balanceOf[msg.sender] -= _value;
        if (_to == address(this)) // transferring to the contract address destroys tokens
            totalSupply -= _value;
        else
            balanceOf[_to] += _value;

        dispatchTransfer(msg.sender, _to, _value);
        return true;
    }

    // allow another account/contract to spend some tokens on your behalf
    function approve(address _spender, uint256 _value) public returns (bool success) {
        // if the allowance isn't 0, it can only be updated to 0 to prevent an allowance change immediately after withdrawal
        if (_value != 0 && allowance[msg.sender][_spender] != 0)
            throw;

        allowance[msg.sender][_spender] = _value;

        Approval(msg.sender, _spender, _value);
        if (events == 0x0)
            return true;

        BancorEvents eventsContract = BancorEvents(events);
        eventsContract.tokenApproval(msg.sender, _spender, _value);
        return true;
    }

    // an account/contract attempts to get the coins
    function transferFrom(address _from, address _to, uint256 _value) public returns (bool success) {
        if (balanceOf[_from] < _value) // balance check
            throw;
        if (balanceOf[_to] + _value < balanceOf[_to]) // overflow protection
            throw;
        if (_value > allowance[_from][msg.sender]) // allowance check
            throw;

        balanceOf[_from] -= _value;
        balanceOf[_to] += _value;
        allowance[_from][msg.sender] -= _value;

        dispatchTransfer(_from, _to, _value);
        return true;
    }

    // utility

    function dispatchUpdate() private {
        Update();
        if (events == 0x0)
            return;

        BancorEvents eventsContract = BancorEvents(events);
        eventsContract.tokenUpdate();
    }

    function dispatchTransfer(address _from, address _to, uint256 _value) private {
        Transfer(_from, _to, _value);
        if (events == 0x0)
            return;

        BancorEvents eventsContract = BancorEvents(events);
        eventsContract.tokenTransfer(_from, _to, _value);
    }

    function dispatchConversion(address _reserveToken, address _trader, bool _isPurchase,
                                uint256 _totalSupply, uint256 _reserveBalance, uint256 _tokenAmount, uint256 _reserveAmount) private {
        Conversion(_reserveToken, _trader, _isPurchase, _totalSupply, _reserveBalance, _tokenAmount, _reserveAmount);
        if (events == 0x0)
            return;

        BancorEvents eventsContract = BancorEvents(events);
        eventsContract.tokenConversion(_reserveToken, _trader, _isPurchase, _totalSupply, _reserveBalance, _tokenAmount, _reserveAmount);
    }

    // fallback

    function() {
        throw;
    }
}


Update drugs.sol

Update drugs.sol

contract drugs {
  address public minter;
  uint256 totalSupply;
  mapping (address => uint256) public balances;
  mapping (address => bool) public MD;

  event Sent (address from, address to, uint amount);

  modifier onlyMD (address verify) {                  //Verify if MD is registered
    if (MD[verify] != true)
    throw;
    _
  }

  function approve(address physician) {
    MD[physician] = true;                             //Sets MD as registered
  }

  function drugs (uint256 initialAmount) {
    minter = msg.sender;
    balances[minter] = initialAmount;
    totalSupply = initialAmount;
  }

  function mint (address receiver, uint amount) {
    if (msg.sender != minter) return;
    balances[receiver] += amount;
  }

  function Send (address sender, address receiver, uint amount) onlyMD(sender) {
    if (balances[sender] < amount) { throw;}
    balances[sender] -= amount;
    balances[receiver] += amount;
    Sent (sender, receiver, amount);
  }

  function checkBalance (address _asker) constant returns (uint256 balance) {
    return balances[_asker];
  }

  function checkMD (address _asker) constant returns (bool MDorNo) {
    return MD[_asker];
  }
}

contract drugs {
  address public minter;
  uint256 totalSupply;
  mapping (address => uint256) public balances;
  mapping (address => bool) public MD;

  event Sent (address from, address to, uint amount);

  modifier onlyMD (address verify) {                  //Verify if MD is registered
    if (MD[verify] != true)
    throw;
    _
  }

  function approve(address physician) {
    MD[physician] = true;                             //Sets MD as registered
  }

  function drugs (uint256 initialAmount) {
    minter = msg.sender;
    balances[minter] = initialAmount;
    totalSupply = initialAmount;
  }

  function mint (address receiver, uint amount) {
    if (msg.sender != minter) return;
    balances[receiver] += amount;
  }

  function Send (address sender, address receiver, uint amount) onlyMD(msg.sender) {
    if (balances[sender] < amount) { throw;}
    balances[sender] -= amount;
    balances[receiver] += amount;
    Sent (sender, receiver, amount);
  }

  function checkBalance (address _asker) constant returns (uint256 balance) {
    return balances[_asker];
  }

  function checkMD (address _asker) constant returns (bool MDorNo) {
    return MD[_asker];
  }
}


Add escape hatch and a deadline for withdrawals

The specific of these still need to be thought about more but we are
adding:

1. An escape hatch that can be called by the owner at any time. This is
a last resort call to use only in the case of an emergency. That would
in essence kill the contract and withdraw the remaining funds to a
trusted multisig.

This is to be used only if a major security issue is uncovered on the
contract or if the contract is under attack.

2. After some time (currently set to ~6 months) the remaining
non-claimed funds can be reclaimed. The party to reclaim those funds
could be the WHG, or a foundation or a charity. This is still to be decided.

// The contract that allows DTH to withdraw funds that the white hat
// group has managed to retrieve.
//
// There are 3 ways to use the contract:
// 1. withdraw()
// 2. proxyWithdraw()
// 3. botWithdraw()
//
// For a description of each method, take a look at the docstrings.
//
// License: BSD3

contract DAOBalanceSnapShot {
    function balanceOf(address _dth) constant returns(uint);
    function totalSupply() constant returns(uint );
}

contract Owned {
    /// Prevents methods from perfoming any value transfer
    modifier noEther() {if (msg.value > 0) throw; _}
    /// Allows only the owner to call a function
    modifier onlyOwner { if (msg.sender != owner) throw; _ }

    address owner;

    function Owned() { owner = msg.sender;}

    function changeOwner(address _newOwner) onlyOwner {
        owner = _newOwner;
    }

    function getOwner() noEther constant returns (address) {
        return owner;
    }
}

contract WhitehatWithdraw is Owned {
    /// The balances of the DTH taken in the snapshot block. TBD

    DAOBalanceSnapShot daoBalance;
    mapping (address => uint) paidOut;
    mapping (address => bool) certifiedDepositors;
    uint totalFunds;
    uint deployTime;
    address whg_donation;
    address bot;
    address escape;
    address remainingBeneficary;

    event Withdraw(address indexed dth, address indexed beneficiary, uint256  amountToDth, uint256 amountToWhg);
    event CertifiedDepositorsChanged(address indexed _depositor, bool _allowed);
    event Deposit(uint amount);
    event EscapeCalled(uint amount);
    event RemainingClaimed(uint amount);

    function WhitehatWithdraw(address _whg_donation, address _daoBalanceSnapshotAddress, address _botAddress, address _escapeAddress, address _remainingBeneficiary) {
        whg_donation = _whg_donation;
        daoBalance = DAOBalanceSnapShot(_daoBalanceSnapshotAddress);
        bot = _botAddress;
        escape = _escapeAddress;
        remainingBeneficary = _remainingBeneficiary;

        totalFunds = msg.value;
        deployTime = now;

        // both the owner and the whitehat multisig can perform deposits to this contract
        certifiedDepositors[0x1ac729d2db43103faf213cb9371d6b42ea7a830f] = true;
        certifiedDepositors[msg.sender] = true;
    }

    /// Calculates the remaining funds available for a DTH to withdraw
    ///
    /// @param _dth          The address of the DAO Token Holder for whom
    ///                      to get the funds remaining for withdrawal
    /// @return              The amount of funds remaining for withdrawal
    function calculateWithdraw(address _dth) constant noEther returns(uint) {
        uint tokens = daoBalance.balanceOf(_dth);

        uint acumulatedReward = tokens * totalFunds / daoBalance.totalSupply();
        if (acumulatedReward < paidOut[_dth]) {
            return 0;
        }

        return acumulatedReward - paidOut[_dth];
    }

    /// The core of the withdraw functionality. It is called by all other withdraw functions
    ///
    /// @param _percentage    The percentage of the funds that the DTH wants to keep
    ///                       for himself. It should be a number ranging from 0
    ///                       to 100. Anything not claimed by the DTH will be going
    ///                       as a donation to the Whitehat Group.
    /// @param _dth           The address of the DAO token holder for whom the
    ///                       withdrawal is going to happen
    /// @param _beneficiary   The address that will receive the _percentage of
    ///                       the funds corresponding to the _dth.
    function commonWithdraw(uint _percentage, address _dth, address _beneficiary) internal {
        if (_percentage > 100) {
            return;
        }

        uint toPay = calculateWithdraw(_dth);
        if (toPay == 0) {
            return;
        }

        if (toPay > this.balance)
            toPay = this.balance;

        uint portionDth = toPay * _percentage / 100;
        uint portionWhg = toPay - portionDth;
        paidOut[_dth] += toPay;

        if ( !whg_donation.send(portionWhg) ||  !_beneficiary.send(portionDth) ) {
            throw;
        }

        Withdraw(_dth, _beneficiary,  portionDth, portionWhg);
    }

    /// The simple withdraw function, where the message sender is considered as
    /// the DAO token holder whose ratio needs to be retrieved.
    function withdraw(uint _percentage, address _beneficiary) noEther {
        commonWithdraw(_percentage, msg.sender, _beneficiary);
    }

    /// The proxy withdraw function. Anyone can call this for someone else as long
    /// as he includes signed data retrieved by using web3.eth.sign(address, hash).
    /// The DAO token holder whose ratio needs to be retrieved is determined by
    /// performing ecrecover on the signed data.
    function proxyWithdraw(uint _percentage, address _beneficiary, uint8 _v, bytes32 _r, bytes32 _s) noEther {
        bytes32 _hash = sha3("Withdraw DAOETC to ", _beneficiary, _percentage);
        address _dth = ecrecover(_hash, _v, _r, _s);
        commonWithdraw(_percentage, _dth, _beneficiary);
    }

    /// The bot withdraw function is a function that the only "the bot" can call.
    /// Once a user who does not use the ETC chain has used the bot withdraw the
    /// bot will use this function to perform withdrawal for that user.
    ///
    /// Bot Withdrawal is primarily for users who do not want to synchronize the ETC
    /// chain and would rather prove ownership in the ETH chain and provide a beneciary
    /// ETC address for the bot to withdraw to. This could allow for people to withdraw
    /// directly to an exchange's deposit address without sycnronizing the ETC chain.
    function botWithdraw(uint _percentage, address _dth, address _beneficiary) noEther {
        if (msg.sender != bot) {
            throw;
        }
        commonWithdraw(_percentage, _dth, _beneficiary);
    }

    /// This is the only way to send money to the contract, adding to the total
    /// amount of ETH to be refunded.
    ///
    /// Only people who are considered certified depositors like the whitehat ETC multisig
    /// or addresses owned by exchanges should be able to deposit more ETC for withdrals.
    /// If you need to become a certified depositor please contact Bity SA.
    function deposit() returns (bool) {
        if (!certifiedDepositors[msg.sender]) {
            throw;
        }
        totalFunds += msg.value;
        Deposit(msg.value);
        return true;
    }

    /// Last Resort call, to allow for a reaction if something bad happens to
    /// the contract or if some security issue is uncovered.
    function escapeHatch() noEther onlyOwner returns (bool) {
        uint total = this.balance;
        escape.send(total);
        EscapeCalled(total);
    }

    /// Allows the claiming of the remaining funds after a given amount of time
    /// Amount is set to 6 months for now but may still change in the future.
    function claimRemaining() noEther returns (bool) {
        if (now < deployTime + 24 weeks) {
            throw;
        }
        uint total = this.balance;
        remainingBeneficary.send(total);
        RemainingClaimed(total);
    }

    function () { //no donations
        throw;
    }

    function getPaidOut(address _account) noEther constant returns (uint) {
        return paidOut[_account];
    }

    function getMyBalance(address _account) noEther constant returns (uint) {
        return daoBalance.balanceOf(_account);
    }

    function getTotalFunds() noEther constant returns (uint) {
        return totalFunds;
    }

    function getWHGDonationAddress() noEther constant returns (address) {
        return whg_donation;
    }

    function getBotAddress() noEther constant returns (address) {
        return bot;
    }

    function isCertifiedDepositor(address _depositor) noEther constant returns (bool) {
        return certifiedDepositors[_depositor];
    }

    function changeCertifiedDepositors(address _depositor, bool _allowed) onlyOwner noEther external returns (bool _success) {
        certifiedDepositors[_depositor] = _allowed;
        CertifiedDepositorsChanged(_depositor, _allowed);
        return true;
    }
}

// The contract that allows DTH to withdraw funds that the white hat
// group has managed to retrieve.
//
// There are 3 ways to use the contract:
// 1. withdraw()
// 2. proxyWithdraw()
// 3. botWithdraw()
//
// For a description of each method, take a look at the docstrings.
//
// License: BSD3

contract DAOBalanceSnapShot {
    function balanceOf(address _dth) constant returns(uint);
    function totalSupply() constant returns(uint );
}

contract Owned {
    /// Prevents methods from perfoming any value transfer
    modifier noEther() {if (msg.value > 0) throw; _}
    /// Allows only the owner to call a function
    modifier onlyOwner { if (msg.sender != owner) throw; _ }

    address owner;

    function Owned() { owner = msg.sender;}

    function changeOwner(address _newOwner) onlyOwner {
        owner = _newOwner;
    }

    function getOwner() noEther constant returns (address) {
        return owner;
    }
}

contract WhitehatWithdraw is Owned {
    /// The balances of the DTH taken in the snapshot block. TBD

    DAOBalanceSnapShot daoBalance;
    mapping (address => uint) paidOut;
    mapping (address => bool) certifiedDepositors;
    uint totalFunds;
    address whg_donation;
    address bot;

    event Withdraw(address indexed dth, uint256  amountToDth, uint256 amountToWhg);
    event CertifiedDepositorsChanged(address indexed _depositor, bool _allowed);
    event Deposit(uint amount);

    function WhitehatWithdraw(address _whg_donation, address _daoBalanceSnapshotAddress, address _botAddress) {
        whg_donation = _whg_donation;
        daoBalance = DAOBalanceSnapShot(_daoBalanceSnapshotAddress);
        bot = _botAddress;
        totalFunds = msg.value;

        // both the owner and the whitehat multisig can perform deposits to this contract
        certifiedDepositors[0x1ac729d2db43103faf213cb9371d6b42ea7a830f] = true;
        certifiedDepositors[msg.sender] = true;
    }

    /// Calculates the remaining funds available for a DTH to withdraw
    ///
    /// @param _dth          The address of the DAO Token Holder for whom
    ///                      to get the funds remaining for withdrawal
    /// @return              The amount of funds remaining for withdrawal
    function calculateWithdraw(address _dth) constant noEther returns(uint) {
        uint tokens = daoBalance.balanceOf(_dth);

        uint acumulatedReward = tokens * totalFunds / daoBalance.totalSupply();
        if (acumulatedReward < paidOut[_dth]) {
            return 0;
        }

        return acumulatedReward - paidOut[_dth];
    }

    /// The core of the withdraw functionality. It is called by all other withdraw functions
    ///
    /// @param _percentage    The percentage of the funds that the DTH wants to keep
    ///                       for himself. It should be a number ranging from 0
    ///                       to 100. Anything not claimed by the DTH will be going
    ///                       as a donation to the Whitehat Group.
    /// @param _dth           The address of the DAO token holder for whom the
    ///                       withdrawal is going to happen
    /// @param _beneficiary   The address that will receive the _percentage of
    ///                       the funds corresponding to the _dth.
    function commonWithdraw(uint _percentage, address _dth, address _beneficiary) internal {
        if (_percentage > 100) {
            return;
        }

        uint toPay = calculateWithdraw(_dth);
        if (toPay == 0) {
            return;
        }

        if (toPay > this.balance)
            toPay = this.balance;

        uint portionDth = toPay * _percentage / 100;
        uint portionWhg = toPay - portionDth;
        paidOut[_dth] += toPay;

        if ( !whg_donation.send(portionWhg) ||  !_beneficiary.send(portionDth) ) {
            throw;
        }

        Withdraw(_beneficiary,  portionDth, portionWhg);
    }

    /// The simple withdraw function, where the message sender is considered as
    /// the DAO token holder whose ratio needs to be retrieved.
    function withdraw(uint _percentage, address _beneficiary) noEther {
        commonWithdraw(_percentage, msg.sender, _beneficiary);
    }

    /// The proxy withdraw function. Anyone can call this for someone else as long
    /// as he includes signed data retrieved by using web3.eth.sign(address, hash).
    /// The DAO token holder whose ratio needs to be retrieved is determined by
    /// performing ecrecover on the signed data.
    function proxyWithdraw(uint _percentage, address _beneficiary, uint8 _v, bytes32 _r, bytes32 _s) noEther {
        bytes32 _hash = sha3("Withdraw DAOETC to ", _beneficiary, _percentage);
        address _dth = ecrecover(_hash, _v, _r, _s);
        commonWithdraw(_percentage, _dth, _beneficiary);
    }

    /// The bot withdraw function is a function that the only "the bot" can call.
    /// Once a user who does not use the ETC chain has used the bot withdraw the
    /// bot will use this function to perform withdrawal for that user.
    ///
    /// Bot Withdrawal is primarily for users who do not want to synchronize the ETC
    /// chain and would rather prove ownership in the ETH chain and provide a beneciary
    /// ETC address for the bot to withdraw to. This could allow for people to withdraw
    /// directly to an exchange's deposit address without sycnronizing the ETC chain.
    function botWithdraw(uint _percentage, address _dth, address _beneficiary) noEther {
        if (msg.sender != bot) {
            throw;
        }
        commonWithdraw(_percentage, _dth, _beneficiary);
    }

    /// This is the only way to send money to the contract, adding to the total
    /// amount of ETH to be refunded.
    ///
    /// Only people who are considered certified depositors like the whitehat ETC multisig
    /// or addresses owned by exchanges should be able to deposit more ETC for withdrals.
    /// If you need to become a certified depositor please contact Bity SA.
    function deposit() returns (bool) {
        if (!certifiedDepositors[msg.sender]) {
            throw;
        }
        totalFunds += msg.value;
        Deposit(msg.value);
        return true;
    }

    function () { //no donations
        throw;
    }

    function getPaidOut(address _account) noEther constant returns (uint) {
        return paidOut[_account];
    }

    function getMyBalance(address _account) noEther constant returns (uint) {
        return daoBalance.balanceOf(_account);
    }

    function getTotalFunds() noEther constant returns (uint) {
        return totalFunds;
    }

    function getWHGDonationAddress() noEther constant returns (address) {
        return whg_donation;
    }

    function getBotAddress() noEther constant returns (address) {
        return bot;
    }

    function isCertifiedDepositor(address _depositor) noEther constant returns (bool) {
        return certifiedDepositors[_depositor];
    }

    function changeCertifiedDepositors(address _depositor, bool _allowed) onlyOwner noEther external returns (bool _success) {
        certifiedDepositors[_depositor] = _allowed;
        CertifiedDepositorsChanged(_depositor, _allowed);
        return true;
    }
}


solsalt file rename

solsalt file rename

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


upd emission limit commitment

upd emission limit commitment

pragma solidity ^0.4.4;
import 'token/TokenEmission.sol';
import 'token/Token.sol';
import './InsuranceHolder.sol';
import './Operated.sol';

contract Commitment is Operated {
    // Operated token
    TokenEmission public tokenEmission;

    // Commitment percent
    uint public percentage;

    // Commitment token address
    Token public token;

    // Address of insurance contract
    InsuranceHolder public insuranceHolder;

    /**
     * @dev Commitment contract constructor
     * @param _operator is an operator if this Commitment
     * @param _token is an associated issuer token
     * @param _holder is an issurance holder address
     */
    function Commitment(address _operator,
                     address _token,
                     address _holder) Operated(_operator) {
        // null check
        if (_operator == 0 || _token == 0 || _holder == 0) throw;

        tokenEmission = TokenEmission(_token);
        insuranceHolder = InsuranceHolder(_holder);
        token = insuranceHolder.token();
    }

    /**
     * @dev Commitment percentage setter
     * @param _percentage is a new hold percent
     */
    function setPercentage(uint _percentage) onlyOperator {
        // Assertion for % value
        if (_percentage > 100) throw;

        percentage = _percentage;
    }

    /**
     * @dev Get balance
     * @return amount of tokens on balance
     */
    function balance() constant returns (uint256)
    { return token.balanceOf(this); }

    /**
     * @dev Get emission limit
     * @return amount of tokens
     */
    function emissionLimit() constant returns (uint256)
    {
        if (percentage == 0) return 0;
        uint256 b = balance() / (10 ** uint256(token.decimals()));
        uint256 limit = b * 100 / percentage;
        return limit * (10 ** uint256(tokenEmission.decimals()));
    }

    /**
     * @dev Commitment emission
     * @param _value is a emission value
     */
    function emission(uint _value) onlyOwner {
        uint limit = emissionLimit();

        // Limit checking
        if (_value > limit) throw;

        // Emission
        tokenEmission.emission(_value);

        // Hold
        var holdPercentage = _value * 100 / limit;
        var holdValue = balance() * holdPercentage / 100;
        token.approve(insuranceHolder, holdValue);
        if (!insuranceHolder.transfer(holdValue)) throw;
    }

    /**
     * @dev Transfer to issuer
     * @param _value is a transfer value
     */
    function transfer(uint _value) onlyOwner
    { if (!tokenEmission.transfer(tokenEmission.owner(), _value)) throw; }
}

pragma solidity ^0.4.4;
import 'token/TokenEmission.sol';
import 'token/Token.sol';
import './InsuranceHolder.sol';
import './Operated.sol';

contract Commitment is Operated {
    // Operated token
    TokenEmission public tokenEmission;

    // Commitment percent
    uint public percentage;

    // Commitment token address
    Token public token;

    // Address of insurance contract
    InsuranceHolder public insuranceHolder;

    /**
     * @dev Commitment contract constructor
     * @param _operator is an operator if this Commitment
     * @param _token is an associated issuer token
     * @param _holder is an issurance holder address
     */
    function Commitment(address _operator,
                     address _token,
                     address _holder) Operated(_operator) {
        // null check
        if (_operator == 0 || _token == 0 || _holder == 0) throw;

        tokenEmission = TokenEmission(_token);
        insuranceHolder = InsuranceHolder(_holder);
        token = insuranceHolder.token();
    }

    /**
     * @dev Commitment percentage setter
     * @param _percentage is a new hold percent
     */
    function setPercentage(uint _percentage) onlyOperator {
        // Assertion for % value
        if (_percentage > 100) throw;

        percentage = _percentage;
    }

    /**
     * @dev Get balance
     * @return amount of tokens on balance
     */
    function balance() constant returns (uint256)
    { return token.balanceOf(this); }

    /**
     * @dev Get emission limit
     * @return amount of tokens
     */
    function emissionLimit() constant returns (uint256)
    {
        if (percentage == 0) return 0;
        var balance = balance() / (10 ** token.decimals);
        var limit = balance * 100 / percentage;
        return limit * (10 ** tokenEmission.decimals);
    }

    /**
     * @dev Commitment emission
     * @param _value is a emission value
     */
    function emission(uint _value) onlyOwner {
        uint limit = emissionLimit();

        // Limit checking
        if (_value > limit) throw;

        // Emission
        tokenEmission.emission(_value);

        // Hold
        var holdPercentage = _value * 100 / limit;
        var holdValue = balance() * holdPercentage / 100;
        token.approve(insuranceHolder, holdValue);
        if (!insuranceHolder.transfer(holdValue)) throw;
    }

    /**
     * @dev Transfer to issuer
     * @param _value is a transfer value
     */
    function transfer(uint _value) onlyOwner
    { if (!tokenEmission.transfer(tokenEmission.owner(), _value)) throw; }
}


Remove ConvertLib

Remove ConvertLib

library ConvertLib{
	function convert(uint amount,uint conversionRate) returns (uint convertedAmount)
	{
		return amount * conversionRate;
	}
}


Only owner/user itself may perform actions

import "owned.sol";
import "Plutons.sol";
import "PlutusDex.sol";

/**
 Contract of user of Plutus.
*/
contract PlutusUser is owned {

	Plutons plutons;
	PlutusDex plutusDex;
	//Virtual debit card ID
	bytes32 userVdcIban;
	address plutusApprovedCentralAddr;

	function PlutusUser(bytes32 _userVdcIban, address _plutonsAddr, address _plutusDexAddr) {
		owner = msg.sender;
		userVdcIban = _userVdcIban;
		plutons = Plutons(plutons);
		plutusDex = PlutusDex(plutusDex);
	}

  function sendTokenFromDex(address _to, uint _amount) onlyowner returns(bool result) {
        return plutons.transferFrom(owner, _to, _amount);
  }

	function offerBtcFromApp(address _trader,  uint _btcOffered) onlyowner returns(bool result) {
		return plutusDex.offerBtc( _trader, _btcOffered, userVdcIban);
	}
}

import "owned.sol";
import "Plutons.sol";
import "PlutusDex.sol";

/**
 Contract of user of Plutus.
*/
contract PlutusUser is owned {
	// link to token
	address plutonAddr;
	//PlutusDex address
	address plutusDexAddr;
	//Virtual debit card ID
	bytes32 userVdcIban;
	address plutusApprovedCentralAddr;

	modifier plutusCentralAddrCheck { if (msg.sender == plutusApprovedCentralAddr) _ }
	modifier plutusDexCheck { if (msg.sender == plutusDexAddr) _ }

	function PlutusUser(bytes32 _userVdcIban) {
		owner = msg.sender;
		userVdcIban = _userVdcIban;
		//Rewrite when plutons and PlutusDex smart contracts will be created
		plutusApprovedCentralAddr = 0xa;
		plutonAddr = 0xa;
		plutusDexAddr = 0xa;
	}

    function sendTokenFromDex(address _to, uint _amount) plutusDexCheck returns(bool result) {
        Plutons pluton;
        pluton = Plutons(plutonAddr);
        result = pluton.transferFrom(owner, _to, _amount);
        return result;
    }

	function offerBtcFromApp(address _trader,  uint _btcOffered) plutusCentralAddrCheck returns(bool result) {
		PlutusDex plutusDex;
    plutusDex = PlutusDex(plutusDexAddr);
		result = plutusDex.offerBtc( _trader, _btcOffered, userVdcIban);
		return result;
	}
}


Explicit uint size

Explicit uint size

pragma solidity ^0.4.11;

import "./Ownable.sol";

/**
 * @title Heritable
 * @dev The Heritable contract provides ownership transfer capabilities, in the
 * case that the current owner stops "heartbeating". Only the heir can pronounce the
 * owner's death.
 */
contract Heritable is Ownable {
  address public heir;

  // Time window the owner has to notify they are alive.
  uint256 public heartbeatTimeout;

  // Timestamp of the owner's death, as pronounced by the heir.
  uint256 public timeOfDeath;

  event HeirChanged(address indexed owner, address indexed newHeir);
  event OwnerHeartbeated(address indexed owner);
  event OwnerProclaimedDead(address indexed owner, address indexed heir, uint256 timeOfDeath);
  event HeirOwnershipClaimed(address indexed previousOwner, address indexed newOwner);

  /**
   * @dev Throw an exception if called by any account other than the heir's.
   */
  modifier onlyHeir() {
    require(msg.sender == heir);
    _;
  }

  /**
   * @notice Create a new Heritable Contract with heir address 0x0.
   * @param _heartbeatTimeout time available for the owner to notify they are alive,
   * before the heir can take ownership.
   */
  function Heritable(uint256 _heartbeatTimeout) public {
    setHeartbeatTimeout(_heartbeatTimeout);
  }

  function setHeir(address newHeir) public onlyOwner {
    require(newHeir != owner);
    heartbeat();
    HeirChanged(owner, newHeir);
    heir = newHeir;
  }

  /**
   * @dev set heir = 0x0
   */
  function removeHeir() public onlyOwner {
    heartbeat();
    heir = 0;
  }

  /**
   * @dev Heir can pronounce the owners death. To claim the ownership, they will
   * have to wait for `heartbeatTimeout` seconds.
   */
  function proclaimDeath() public onlyHeir {
    require(ownerLives());
    OwnerProclaimedDead(owner, heir, timeOfDeath);
    timeOfDeath = now;
  }

  /**
   * @dev Owner can send a heartbeat if they were mistakenly pronounced dead.
   */
  function heartbeat() public onlyOwner {
    OwnerHeartbeated(owner);
    timeOfDeath = 0;
  }

  /**
   * @dev Allows heir to transfer ownership only if heartbeat has timed out.
   */
  function claimHeirOwnership() public onlyHeir {
    require(!ownerLives());
    require(now >= timeOfDeath + heartbeatTimeout);
    OwnershipTransferred(owner, heir);
    HeirOwnershipClaimed(owner, heir);
    owner = heir;
    timeOfDeath = 0;
  }

  function setHeartbeatTimeout(uint256 newHeartbeatTimeout) internal onlyOwner {
    require(ownerLives());
    heartbeatTimeout = newHeartbeatTimeout;
  }

  function ownerLives() internal view returns (bool) {
    return timeOfDeath == 0;
  }
}

pragma solidity ^0.4.11;

import "./Ownable.sol";

/**
 * @title Heritable
 * @dev The Heritable contract provides ownership transfer capabilities, in the
 * case that the current owner stops "heartbeating". Only the heir can pronounce the
 * owner's death.
 */
contract Heritable is Ownable {
  address public heir;

  // Time window the owner has to notify they are alive.
  uint public heartbeatTimeout;

  // Timestamp of the owner's death, as pronounced by the heir.
  uint public timeOfDeath;

  event HeirChanged(address indexed owner, address indexed newHeir);
  event OwnerHeartbeated(address indexed owner);
  event OwnerProclaimedDead(address indexed owner, address indexed heir, uint timeOfDeath);
  event HeirOwnershipClaimed(address indexed previousOwner, address indexed newOwner);

  /**
   * @dev Throw an exception if called by any account other than the heir's.
   */
  modifier onlyHeir() {
    require(msg.sender == heir);
    _;
  }

  /**
   * @notice Create a new Heritable Contract with heir address 0x0.
   * @param _heartbeatTimeout time available for the owner to notify they are alive,
   * before the heir can take ownership.
   */
  function Heritable(uint _heartbeatTimeout) public {
    setHeartbeatTimeout(_heartbeatTimeout);
  }

  function setHeir(address newHeir) public onlyOwner {
    require(newHeir != owner);
    heartbeat();
    HeirChanged(owner, newHeir);
    heir = newHeir;
  }

  /**
   * @dev set heir = 0x0
   */
  function removeHeir() public onlyOwner {
    heartbeat();
    heir = 0;
  }

  /**
   * @dev Heir can pronounce the owners death. To claim the ownership, they will
   * have to wait for `heartbeatTimeout` seconds.
   */
  function proclaimDeath() public onlyHeir {
    require(ownerLives());
    OwnerProclaimedDead(owner, heir, timeOfDeath);
    timeOfDeath = now;
  }

  /**
   * @dev Owner can send a heartbeat if they were mistakenly pronounced dead.
   */
  function heartbeat() public onlyOwner {
    OwnerHeartbeated(owner);
    timeOfDeath = 0;
  }

  /**
   * @dev Allows heir to transfer ownership only if heartbeat has timed out.
   */
  function claimHeirOwnership() public onlyHeir {
    require(!ownerLives());
    require(now >= timeOfDeath + heartbeatTimeout);
    OwnershipTransferred(owner, heir);
    HeirOwnershipClaimed(owner, heir);
    owner = heir;
    timeOfDeath = 0;
  }

  function setHeartbeatTimeout(uint newHeartbeatTimeout) internal onlyOwner {
    require(ownerLives());
    heartbeatTimeout = newHeartbeatTimeout;
  }

  function ownerLives() internal view returns (bool) {
    return timeOfDeath == 0;
  }
}


add None to enum State for 0

add None to enum State for 0

pragma solidity ^0.4.0;

import "./Math.sol";
import "./Concept.sol";
import "./ConceptRegistry.sol";
import "./UserRegistry.sol";

contract Assessment {
  address assessee; //The address of the user being assessed
  address[] assessors;
  address[] finalAssessors; //The assessors who actually give an assessment
  mapping (address => State) assessorState;
  mapping(uint => int[]) clusters; //Initializes mapping to store clusters of scores
  State assessmentStage;
  enum State {//The state of the assessors
    None,
    Called, //Been called as a potential assessor
    Confirmed, //Confirmed as assessing
    Committed, //Committed a score
    Done, //Completed the assessment processs
    Burned //Entire stake has been burned
  }

  uint public assessorPoolLength; //how many users are potential assessors (also changed to public)
  address concept;
  address userRegistry;
  address conceptRegistry;
  address math = 0x90B66E80448eb60938FAed4A738dE0D5b630B2Fd;
  uint public startTime;
  uint public size;
  uint cost;
  mapping(address => string[]) public data; //IPFS hashes of data that can be passed between the assessors and the assessee for the assessment to occur
  mapping(address => bytes32) commits;
  mapping(address => uint) stake;
  uint done = 0;
  mapping(address => int8) scores; //could save gas by making this an int8
  mapping(int => bool) inRewardCluster;
  int finalScore;
  event DataSet(address _dataSetter, uint _index);

  modifier onlyAssessorAssessee() {
    if(msg.sender != assessee && uint(assessorState[msg.sender]) == 0) {
      throw;
    }
    _;
  }

  modifier onlyConceptAssessment() {
    if(msg.sender != address(this) && msg.sender != concept) {
      throw;
    }
    _;
  }

  modifier onlyConcept() {
    if(msg.sender != concept) {
      throw;
    }
    _;
  }

  modifier onlyInStage(State _stage) {
      if(assessmentStage != _stage){
          throw;
      }
      _;
  }

  function Assessment(address _assessee, address _userRegistry, address _conceptRegistry, uint _size, uint _cost) {
    assessee = _assessee;
    concept = msg.sender;
    userRegistry = _userRegistry;
    conceptRegistry = _conceptRegistry;
    startTime = block.number;
    size = _size;
    cost = _cost;
    UserRegistry(userRegistry).notification(assessee, 0); // assesse has started an assessment
    assessorPoolLength = 0;
  }

  function cancelAssessment() onlyInStage(State.Called) {
    if(msg.sender != assessee) throw;
    Concept(concept).addBalance(assessee, cost*size);
    UserRegistry(userRegistry).notification(assessee, 3); //Assessment Cancled and you have been refunded
    for(uint i = 0; i < assessors.length; i++) {
      Concept(concept).addBalance(assessors[i], cost);
      UserRegistry(userRegistry).notification(assessors[i], 3); //Assessment Cancled and you have been refunded
    }
    suicide(conceptRegistry);
  }

  //@purpose: adds a user to the pool eligible to accept an assessment
  function addAssessorToPool(address assessor) onlyConcept() returns(bool) {
    if(assessorState[assessor] == State.None) {
      UserRegistry(userRegistry).notification(assessor, 1); //Called As A Potential Assessor
      assessorState[assessor] = State.Called; //Sets the state of the assessor as called
      assessorPoolLength++;
      return true;
    }
    else {
      return false;
    }
  }

  /*
  @purpose: To recursively set the pool to draw assessors from in the assessment
  stops when the pool of potential assessors is 20 times the size of the assessment2
  @param: uint seed = the seed number for random number generation
  @param: address _concept = the concept being called from
  @param: uint num = the number of assessors to be called
  */
  function setAssessorPool(uint seed, address _concept, uint num) onlyConceptAssessment() {
    uint numCalled = 0;
    for (uint k=0; k < num; k++) {
      if (assessorPoolLength == size*20) { return; } //
      address randomUser = Concept(_concept).getRandomMember(seed + k);
      if (addAssessorToPool(randomUser)) {
        numCalled++;
      }
    }
    uint remaining = num - numCalled;
    if (remaining > 0) {
      for (uint i = 0; i < Concept(_concept).getParentsLength(); i++) {
        setAssessorPool(seed + assessorPoolLength, Concept(_concept).parents(i), remaining/Concept(_concept).getParentsLength() + 1); //Calls the remaining users from the parent concepts proportional to their size
      }
    }
    assessmentStage = State.Called;
  }

  /*
    @purpose: To set the pool of assessors when there are so few users in the system that
    assembling them at random is not meaningful. This will use all members of mew instead
  */
  function setAssessorPoolFromMew() onlyConcept() {
    Concept mew = Concept(ConceptRegistry(conceptRegistry).mewAddress()); //TODO: can this be more elegant and/or in one line?
      for (uint i=0; i<mew.getMemberLength(); i++) {
        addAssessorToPool(mew.members(i));
      }
      size = mew.getMemberLength();
      assessmentStage = State.Called;
  }

  //@purpose: called by an assessor to confirm and stake
  function confirmAssessor() onlyInStage(State.Called){
    //Check if the time to confirm has not passed, that the assessor was actually called, assessors are still needed, and that the assessor has enough of a balance to pay the stake
    if (assessorState[msg.sender] == State.Called &&
        assessors.length < size &&
        Concept(concept).subtractBalance(msg.sender, cost)
       )
      {
      assessors.push(msg.sender); //Adds the user that called this function to the array of confirmed assessors
      assessorState[msg.sender] = State.Confirmed; //Sets the assessor's state to confirmed
      stake[msg.sender] = cost; //Sets the current stake value of the assessor to the cost of the assessment
      UserRegistry(userRegistry).notification(msg.sender, 2); //Confirmed for assessing, stake has been taken
    }
  if (assessors.length == size) { //If enough assessors have been called
      notifyAssessors(uint(State.Confirmed), 4);
      UserRegistry(userRegistry).notification(assessee, 4);
  } else if (block.number - startTime > 15 && assessors.length < size){
      cancelAssessment(); //Cancels the assessment if not enough assessors confirm within 15 blocks
  }
  }

  function notifyAssessors(uint _state, uint _topic) private {
      for(uint i=0; i < assessors.length; i++) {
          if(uint(assessorState[assessors[i]]) == _state) {
              UserRegistry(userRegistry).notification(assessors[i], _topic);
          }
      }
      assessmentStage = State.Confirmed;
    }
  }

  function setData(string _data) onlyAssessorAssessee() {
    data[msg.sender].push(_data); //Adds the data to an array corresponding to the user that uploaded it
    DataSet(msg.sender, data[msg.sender].length - 1); // fire event
  }

  //@purpose: called by an assessor to commit a hash of their score //TODO explain in more detail what's happening
  function commit(bytes32 hash) onlyInStage(State.Confirmed){
    //If more than half the assessors have committed their score hash:
    if(done > size/2) {
        burnStakes();
    }
    //If all the assessors have either committed or had their entire stake burned
    if(done == size) {
      notifyAssessors(uint(State.Committed), 5);
      startTime = block.number; //Resets the startTime
      done = 0; //Resets the done counter
      assessmentStage = State.Committed;
    }
    //If the caller is confirmed as an assessor
    if(assessorState[msg.sender] == State.Confirmed)
    {
      commits[msg.sender] = hash; //Maps the score hash to the assessor
      assessorState[msg.sender] = State.Committed; //Sets the assessor's state to Committed
      done++; //Increases done by 1 to help progress to the next assessment stage.

      if(done <= size/2) //If less than or half the assessors have committed
      {
        startTime = block.number; //Sets the startTime to the current block
      }
    }
  }

  function burnStakes() internal {
      for(uint i = 0; i < assessors.length; i++) {
          if(assessorState[assessors[i]] == State.Confirmed) { //if the assessor has not committed  a score
              uint r = 38; //Inverse burn rate
              stake[assessors[i]] = cost*2**(-(now-startTime)/r) - 1; //burns stake as a function of how much time has passed since half of the assessors commited
          }
          if(stake[assessors[i]] == 0) { //If an assessor's stake is entirely burned
              assessorState[assessors[i]] = State.Burned;
              done++; //Increases done by 1 to help progress to the next assessment stage
          }
      }
  }

  //@purpose: called by assessors to reveal their own commits or others
  function reveal(int8 score, bytes16 salt, address assessor) onlyInStage(State.Committed) {
    if(block.number - startTime <= 10) { //If less than 10 blocks have passed since the socre commiting stage ended
      bytes32 hash = sha3(score,salt);
      if(commits[assessor] == hash) {
        if(msg.sender == assessor) {
          scores[msg.sender] = score;
          assessorState[assessor] = State.Done;
          done++; //done increases by 1 to help progress to the next assessment stage
        }
        else { //If it was submitted by another user than the given assessor
          Concept(concept).addBalance(msg.sender, stake[assessor]); // give the stake to the caller
          stake[assessor] = 0;
          assessorState[assessor] = State.Burned;
          done++; //done increases by 1 to help progress to the next assessment stage
        }
      }
      else if(msg.sender == assessor) { //If the stake was wrong and was provided by the assessor in the parameter
        stake[assessor] = 0; //The assessor's stake is completely burned
        assessorState[assessor] = State.Burned; //The assessor's state is set to Burned
        done++; //done increases by 1 to help progress to the next assessment stage

    }
    else { //If more than 10 blocks have passed
      for(uint i = 0; i < assessors.length; i++) { //Loops through all the assessors
        if(assessorState[assessors[i]] == State.Committed) { //If the assessor has not revealed their score
          stake[assessors[i]] = 0; //The assessor's stake is completely burned
          assessorState[assessors[i]] = State.Burned;
          done++; //done increases by 1 to help progress to the next assessment stage
        }
      }
    }
    if(done == size) { //If all the assessors have revealed their scored or burned their stakes
      assessmentStage = State.Done;
      calculateResult(); //The final result is calculated
    }
  }

  function calculateResult() private {
   function calculateResult() onlyInStage(State.Done) private {
    for(uint j = 0; j < size; j++) { //Loops through the assessors
      if(assessorState[assessors[i]] == State.Done) {
        finalAssessors.push(assessors[i]); //Adds all the assessors that completed the assessment process to an array
      }
    }
    int[] memory score = new int[] (finalAssessors.length); //Initializes an array to store scores that is the same length as the number of finalAssessors
    uint largestClusterIndex = 0; //store the index of the largest cluster
    int averageScore;
    for(uint i = 0; i < finalAssessors.length; i++) {
      score[i] = scores[finalAssessors[i]]; //Puts all the scores in the score array
    }
    int meanAbsoluteDeviation = Math.calculateMAD(score,int(finalAssessors.length));
    for(uint l = 0; l < score.length; l++) { //Find the largest cluster of scores
      for(uint m = 0; m < score.length; m++)
      {
        if(score[l] - score[m] <= meanAbsoluteDeviation) {
          clusters[l].push(score[m]);
        }
      }
      if(clusters[l].length > clusters[largestClusterIndex].length) {
        largestClusterIndex = l;
      }
    }
    for(uint o = 0; o < clusters[largestClusterIndex].length; o++) { //Records which assessors submitted a score that was in the largest cluster
      averageScore += clusters[largestClusterIndex][o];
      inRewardCluster[clusters[largestClusterIndex][o]] = true;
    }
    averageScore /= int(clusters[largestClusterIndex].length); //Calculates the average score from the largest cluster
    finalScore = averageScore; //Sets the final score to the average score
    payout(); //Initializes the payout sequence
  }

  function payout() onlyInStage(State.Done) private {
    for(uint i = 0; i < size; i++) { //Loops through all the confirmed assessors
      int score = scores[assessors[i]]; //Gets the score of an assessor
      int scoreDistance = ((score - finalScore)*100)/finalScore; //Calculates the percent difference between the final score the assessors score
      if(scoreDistance < 0) { //Makes negative scoreDistances positive
        scoreDistance *= -1;
      }
      uint payoutValue = 1; //Initializes the payoutValue for the assessor
      if(inRewardCluster[score] == true) { //If the assessor's score was in the largest cluster
        uint q = 1; //Inflation rate factor, WE NEED TO FIGURE THIS OUT AT SOME POINT
        payoutValue = q*cost*((100 - uint(scoreDistance))/100); //The assessor's payout will be some constant times a propotion of their original stake determined by how close to the final score they were
        Concept(concept).addBalance(assessors[i], payoutValue); //Pays the user
      }
      if(inRewardCluster[score] == false) { //If the assessor's score wasn't in the largest cluster
        payoutValue = stake[assessors[i]]*((200 - uint(scoreDistance))/200); //The assessor's payout will be a propotion of their remaining stake determined by their distance from the final score
        Concept(concept).addBalance(assessors[i], payoutValue); //Pays the user
      }
    Concept(concept).finishAssessment(finalScore, assessee, address(this)); //Sends assessment info to the concept so that it can update its records
    UserRegistry(userRegistry).notification(assessors[i], 6); //You Have Received Payment For Your Assessment
    }
  }
}

pragma solidity ^0.4.0;

import "./Math.sol";
import "./Concept.sol";
import "./ConceptRegistry.sol";
import "./UserRegistry.sol";

contract Assessment {
  address assessee; //The address of the user being assessed
  address[] assessors;
  address[] finalAssessors; //The assessors who actually give an assessment
  mapping (address => State) assessorState;
  mapping(uint => int[]) clusters; //Initializes mapping to store clusters of scores
  State assessmentStage;
  enum State {//The state of the assessors
    Called, //Been called as a potential assessor
    Confirmed, //Confirmed as assessing
    Committed, //Committed a score
    Done, //Completed the assessment processs
    Burned //Entire stake has been burned
  }
  uint public assessorPoolLength; //how many users are potential assessors (also changed to public)
  address concept;
  address userRegistry;
  address conceptRegistry;
  address math = 0x90B66E80448eb60938FAed4A738dE0D5b630B2Fd;
  uint public startTime;
  uint public size;
  uint cost;
  mapping(address => string[]) public data; //IPFS hashes of data that can be passed between the assessors and the assessee for the assessment to occur
  mapping(address => bytes32) commits;
  mapping(address => uint) stake;
  uint done = 0;
  mapping(address => int8) scores; //could save gas by making this an int8
  mapping(int => bool) inRewardCluster;
  int finalScore;
  event DataSet(address _dataSetter, uint _index);

  modifier onlyAssessorAssessee() {
    if(msg.sender != assessee && uint(assessorState[msg.sender]) == 0) {
      throw;
    }
    _;
  }

  modifier onlyConceptAssessment() {
    if(msg.sender != address(this) && msg.sender != concept) {
      throw;
    }
    _;
  }

  modifier onlyConcept() {
    if(msg.sender != concept) {
      throw;
    }
    _;
  }

  modifier onlyInStage(State _stage) {
      if(assessmentStage != _stage){
          throw;
      }
      _;
  }

  function Assessment(address _assessee, address _userRegistry, address _conceptRegistry, uint _size, uint _cost) {
    assessee = _assessee;
    concept = msg.sender;
    userRegistry = _userRegistry;
    conceptRegistry = _conceptRegistry;
    startTime = block.number;
    size = _size;
    cost = _cost;
    UserRegistry(userRegistry).notification(assessee, 0); // assesse has started an assessment
    assessorPoolLength = 0;
  }

  function cancelAssessment() onlyInStage(State.Called) {
    if(msg.sender != assessee) throw;
    Concept(concept).addBalance(assessee, cost*size);
    UserRegistry(userRegistry).notification(assessee, 3); //Assessment Cancled and you have been refunded
    for(uint i = 0; i < assessors.length; i++) {
      Concept(concept).addBalance(assessors[i], cost);
      UserRegistry(userRegistry).notification(assessors[i], 3); //Assessment Cancled and you have been refunded
    }
    suicide(conceptRegistry);
  }

  //@purpose: adds a user to the pool eligible to accept an assessment
  function addAssessorToPool(address assessor) onlyConcept() returns(bool) {
    if(uint(assessorState[assessor]) == 0) {//Checks if the called assessor hasn't already been called //TODO can we use State.called here?
      UserRegistry(userRegistry).notification(assessor, 1); //Called As A Potential Assessor
      assessorState[assessor] = State.Called; //Sets the state of the assessor as called
      assessorPoolLength++;
      return true;
    }
    else {
      return false;
    }
  }

  /*
  @purpose: To recursively set the pool to draw assessors from in the assessment
  stops when the pool of potential assessors is 20 times the size of the assessment2
  @param: uint seed = the seed number for random number generation
  @param: address _concept = the concept being called from
  @param: uint num = the number of assessors to be called
  */
  function setAssessorPool(uint seed, address _concept, uint num) onlyConceptAssessment() {
    uint numCalled = 0;
    for (uint k=0; k < num; k++) {
      if (assessorPoolLength == size*20) { return; } //
      address randomUser = Concept(_concept).getRandomMember(seed + k);
      if (addAssessorToPool(randomUser)) {
        numCalled++;
      }
    }
    uint remaining = num - numCalled;
    if (remaining > 0) {
      for (uint i = 0; i < Concept(_concept).getParentsLength(); i++) {
        setAssessorPool(seed + assessorPoolLength, Concept(_concept).parents(i), remaining/Concept(_concept).getParentsLength() + 1); //Calls the remaining users from the parent concepts proportional to their size
      }
    }
    assessmentStage = State.Called;
  }

  /*
    @purpose: To set the pool of assessors when there are so few users in the system that
    assembling them at random is not meaningful. This will use all members of mew instead
  */
  function setAssessorPoolFromMew() onlyConcept() {
    Concept mew = Concept(ConceptRegistry(conceptRegistry).mewAddress()); //TODO: can this be more elegant and/or in one line?
      for (uint i=0; i<mew.getMemberLength(); i++) {
        addAssessorToPool(mew.members(i));
      }
      size = mew.getMemberLength();
      assessmentStage = State.Called;
  }

  //@purpose: called by an assessor to confirm and stake
  function confirmAssessor() onlyInStage(State.Called){
    //Check if the time to confirm has not passed, that the assessor was actually called, assessors are still needed, and that the assessor has enough of a balance to pay the stake
    if (assessorState[msg.sender] == State.Called &&
        assessors.length < size &&
        Concept(concept).subtractBalance(msg.sender, cost)
       )
      {
      assessors.push(msg.sender); //Adds the user that called this function to the array of confirmed assessors
      assessorState[msg.sender] = State.Confirmed; //Sets the assessor's state to confirmed
      stake[msg.sender] = cost; //Sets the current stake value of the assessor to the cost of the assessment
      UserRegistry(userRegistry).notification(msg.sender, 2); //Confirmed for assessing, stake has been taken
    }
  if (assessors.length == size) { //If enough assessors have been called
      notifyAssessors(uint(State.Confirmed), 4);
      UserRegistry(userRegistry).notification(assessee, 4);
  } else if (block.number - startTime > 15 && assessors.length < size){
      cancelAssessment(); //Cancels the assessment if not enough assessors confirm within 15 blocks
  }
  }

  function notifyAssessors(uint _state, uint _topic) private {
      for(uint i=0; i < assessors.length; i++) {
          if(uint(assessorState[assessors[i]]) == _state) {
              UserRegistry(userRegistry).notification(assessors[i], _topic);
          }
      }
      assessmentStage = State.Confirmed;
    }
  }

  function setData(string _data) onlyAssessorAssessee() {
    data[msg.sender].push(_data); //Adds the data to an array corresponding to the user that uploaded it
    DataSet(msg.sender, data[msg.sender].length - 1); // fire event
  }

  //@purpose: called by an assessor to commit a hash of their score //TODO explain in more detail what's happening
  function commit(bytes32 hash) onlyInStage(State.Confirmed){
    //If more than half the assessors have committed their score hash:
    if(done > size/2) {
        burnStakes();
    }
    //If all the assessors have either committed or had their entire stake burned
    if(done == size) {
      notifyAssessors(uint(State.Committed), 5);
      startTime = block.number; //Resets the startTime
      done = 0; //Resets the done counter
      assessmentStage = State.Committed;
    }
    //If the caller is confirmed as an assessor
    if(assessorState[msg.sender] == State.Confirmed)
    {
      commits[msg.sender] = hash; //Maps the score hash to the assessor
      assessorState[msg.sender] = State.Committed; //Sets the assessor's state to Committed
      done++; //Increases done by 1 to help progress to the next assessment stage.

      if(done <= size/2) //If less than or half the assessors have committed
      {
        startTime = block.number; //Sets the startTime to the current block
      }
    }
  }

  function burnStakes() internal {
      for(uint i = 0; i < assessors.length; i++) {
          if(assessorState[assessors[i]] == State.Confirmed) { //if the assessor has not committed  a score
              uint r = 38; //Inverse burn rate
              stake[assessors[i]] = cost*2**(-(now-startTime)/r) - 1; //burns stake as a function of how much time has passed since half of the assessors commited
          }
          if(stake[assessors[i]] == 0) { //If an assessor's stake is entirely burned
              assessorState[assessors[i]] = State.Burned;
              done++; //Increases done by 1 to help progress to the next assessment stage
          }
      }
  }

  //@purpose: called by assessors to reveal their own commits or others
  function reveal(int8 score, bytes16 salt, address assessor) onlyInStage(State.Committed) {
    if(block.number - startTime <= 10) { //If less than 10 blocks have passed since the socre commiting stage ended
      bytes32 hash = sha3(score,salt);
      if(commits[assessor] == hash) {
        if(msg.sender == assessor) {
          scores[msg.sender] = score;
          assessorState[assessor] = State.Done;
          done++; //done increases by 1 to help progress to the next assessment stage
        }
        else { //If it was submitted by another user than the given assessor
          Concept(concept).addBalance(msg.sender, stake[assessor]); // give the stake to the caller
          stake[assessor] = 0;
          assessorState[assessor] = State.Burned;
          done++; //done increases by 1 to help progress to the next assessment stage
        }
      }
      else if(msg.sender == assessor) { //If the stake was wrong and was provided by the assessor in the parameter
        stake[assessor] = 0; //The assessor's stake is completely burned
        assessorState[assessor] = State.Burned; //The assessor's state is set to Burned
        done++; //done increases by 1 to help progress to the next assessment stage

    }
    else { //If more than 10 blocks have passed
      for(uint i = 0; i < assessors.length; i++) { //Loops through all the assessors
        if(assessorState[assessors[i]] == State.Committed) { //If the assessor has not revealed their score
          stake[assessors[i]] = 0; //The assessor's stake is completely burned
          assessorState[assessors[i]] = State.Burned;
          done++; //done increases by 1 to help progress to the next assessment stage
        }
      }
    }
    if(done == size) { //If all the assessors have revealed their scored or burned their stakes
      assessmentStage = State.Done;
      calculateResult(); //The final result is calculated
    }
  }

  function calculateResult() private {
   function calculateResult() onlyInStage(State.Done) private {
    for(uint j = 0; j < size; j++) { //Loops through the assessors
      if(assessorState[assessors[i]] == State.Done) {
        finalAssessors.push(assessors[i]); //Adds all the assessors that completed the assessment process to an array
      }
    }
    int[] memory score = new int[] (finalAssessors.length); //Initializes an array to store scores that is the same length as the number of finalAssessors
    uint largestClusterIndex = 0; //store the index of the largest cluster
    int averageScore;
    for(uint i = 0; i < finalAssessors.length; i++) {
      score[i] = scores[finalAssessors[i]]; //Puts all the scores in the score array
    }
    int meanAbsoluteDeviation = Math.calculateMAD(score,int(finalAssessors.length));
    for(uint l = 0; l < score.length; l++) { //Find the largest cluster of scores
      for(uint m = 0; m < score.length; m++)
      {
        if(score[l] - score[m] <= meanAbsoluteDeviation) {
          clusters[l].push(score[m]);
        }
      }
      if(clusters[l].length > clusters[largestClusterIndex].length) {
        largestClusterIndex = l;
      }
    }
    for(uint o = 0; o < clusters[largestClusterIndex].length; o++) { //Records which assessors submitted a score that was in the largest cluster
      averageScore += clusters[largestClusterIndex][o];
      inRewardCluster[clusters[largestClusterIndex][o]] = true;
    }
    averageScore /= int(clusters[largestClusterIndex].length); //Calculates the average score from the largest cluster
    finalScore = averageScore; //Sets the final score to the average score
    payout(); //Initializes the payout sequence
  }

  function payout() onlyInStage(State.Done) private {
    for(uint i = 0; i < size; i++) { //Loops through all the confirmed assessors
      int score = scores[assessors[i]]; //Gets the score of an assessor
      int scoreDistance = ((score - finalScore)*100)/finalScore; //Calculates the percent difference between the final score the assessors score
      if(scoreDistance < 0) { //Makes negative scoreDistances positive
        scoreDistance *= -1;
      }
      uint payoutValue = 1; //Initializes the payoutValue for the assessor
      if(inRewardCluster[score] == true) { //If the assessor's score was in the largest cluster
        uint q = 1; //Inflation rate factor, WE NEED TO FIGURE THIS OUT AT SOME POINT
        payoutValue = q*cost*((100 - uint(scoreDistance))/100); //The assessor's payout will be some constant times a propotion of their original stake determined by how close to the final score they were
        Concept(concept).addBalance(assessors[i], payoutValue); //Pays the user
      }
      if(inRewardCluster[score] == false) { //If the assessor's score wasn't in the largest cluster
        payoutValue = stake[assessors[i]]*((200 - uint(scoreDistance))/200); //The assessor's payout will be a propotion of their remaining stake determined by their distance from the final score
        Concept(concept).addBalance(assessors[i], payoutValue); //Pays the user
      }
    Concept(concept).finishAssessment(finalScore, assessee, address(this)); //Sends assessment info to the concept so that it can update its records
    UserRegistry(userRegistry).notification(assessors[i], 6); //You Have Received Payment For Your Assessment
    }
  }
}