wip delegation

wip delegation

//SPDX-License-Identifier: MIT
pragma solidity >=0.8.4;

import "@openzeppelin/contracts/access/Ownable.sol";

import "@chainlink/contracts/src/v0.8/VRFConsumerBase.sol";

interface IKetherHomepage {
  function ads(uint _idx) external view returns (address,uint,uint,uint,uint,string memory,string memory,string memory,bool,bool);
  function getAdsLength() view external returns (uint);
}

interface IERC721 {
  function ownerOf(uint256) external view returns (address);
  function balanceOf(address) external view returns (uint256);
  function tokenOfOwnerByIndex(address, uint256) external view returns (uint256);
}

interface IERC20 {
  function balanceOf(address account) external view returns (uint256);
  function transfer(address recipient, uint256 amount) external returns (bool);
}

library Errors {
  string constant MustHaveBalance = "must have tokens to nominate";
  string constant OnlyMagistrate = "only active magistrate can do this";
  string constant MustHaveEntropy = "waiting for entropy";
  string constant MustHaveNominations = "must have nominations";
  string constant AlreadyStarted = "election already started";
  string constant NotExecuted = "election not executed";
  string constant TermNotExpired = "term not expired";
  string constant NotEnoughLink = "not enough LINK";
}

contract KetherSortition is Ownable, VRFConsumerBase {
  event Nominated(
      uint256 indexed termNumber,
      address nominator,
      uint256 pixels
  );

  event ElectionExecuting(
    uint256 indexed termNumber
  );

  event ElectionCompleted(
    uint256 indexed termNumber,
    uint256 magistrateToken,
    address currentTokenOwner
  );

  event StepDown(
    uint256 indexed termNumber,
    uint256 magistrateToken,
    address currentTokenOwner
  );

  struct Nomination{
    uint256 termNumber;
    uint256 nominatedToken;
  }

  // MagistrateToken is tokenId of an NFT whose owner controls the royalties purse for this term.
  uint256 public magistrateToken;

  uint256 constant MIN_ELECTION_DURATION = 2 days;
  uint256 constant TERM_DURATION = 6 weeks;
  uint256 constant PIXELS_PER_CELL = 100;

  uint256 public termStarted;
  uint256 public termExpires;
  uint256 public termNumber = 0;

  IERC721 ketherNFTContract;
  IKetherHomepage ketherContract;

  uint256[] public nominatedTokens;
  uint256 public nominatedPixels = 0;
  mapping(uint256 => Nomination) nominations; // mapping of tokenId => termNumber
  // TODO: mapping(uint256 => uint256) electedCount;

  uint256 public electionEntropy; // Provided by Chainlink

  // nominating -[term expired & startElection() calls]> waitingForEntropy -[Chainlink calls into fulfillrandomness()]> gotEntropy -[completeElection()] -> nominating
  enum StateMachine { NOMINATING, WAITING_FOR_ENTROPY, GOT_ENTROPY }
  StateMachine state = StateMachine.NOMINATING;

  // Chainlink values
  bytes32 private s_keyHash;
  uint256 private s_fee;

  constructor(address _ketherNFTContract, address _ketherContract, address vrfCoordinator, address link, bytes32 keyHash, uint256 fee)
  public
  VRFConsumerBase(vrfCoordinator, link) {
    s_keyHash = keyHash;
    s_fee = fee;

    ketherNFTContract = IERC721(_ketherNFTContract);
    ketherContract = IKetherHomepage(_ketherContract);

    termExpires = block.timestamp + MIN_ELECTION_DURATION;
  }

  // Internal helpers:

  /**
   * @dev Only callable by Chainlink VRF, async triggered via startElection().
   */
  function fulfillRandomness(bytes32 requestId, uint256 randomness) internal override {
    require(state == StateMachine.WAITING_FOR_ENTROPY, Errors.NotExecuted);
    electionEntropy = randomness;
    state = StateMachine.GOT_ENTROPY;
  }

  // Views:

  function getMagistrate() public view returns (address) {
    return getAdOwner(magistrateToken);
  }

  function getAdOwner(uint256 _idx) public view returns (address) {
    return ketherNFTContract.ownerOf(_idx);
  }

  function getAdPixels(uint256 _idx) public view returns (uint256) {
    (,,,uint width,uint height,,,,,) = ketherContract.ads(_idx);
    return width * height * PIXELS_PER_CELL;
  }

  function isNominated(uint256 _idx) public view returns (bool) {
    return nominations[_idx].termNumber > termNumber;
  }

  function getNominatedToken(uint256 _idx) public view returns (uint256) {
    require(isNominated(_idx), "erorr todo");

    return nominations[_idx].nominatedToken;
  }

  function getNextMagistrateToken() public view returns (uint256) {
    require(state == StateMachine.GOT_ENTROPY, Errors.MustHaveEntropy);
    require(nominatedTokens.length > 0, Errors.MustHaveNominations);

    uint256 pixelChosen = electionEntropy % nominatedPixels;
    uint256 curPixel = 0;

    for(uint256 i = 0; i < nominatedTokens.length; i++) {
      uint256 idx = nominatedTokens[i];
      curPixel += getAdPixels(idx);
      if (curPixel > pixelChosen) {
        return getNominatedToken(idx);
      }
    }
    return 0;
  }

  // External interface:

  // TODO: function nominateAll() external
  // TODO: function nominate(ownedTokenId) external

  /**
   * @dev Nominate tokens held by the sender as candidates for magistrate in the next term.
   *      Nominations of tokens are independent of their owner.
   * @return Number of nominated pixels
   *
   * TODO
   */
  function nominate(uint256 _ownedTokenId, uint256 _nominateTokenId) external returns (uint256) {
    require(state == StateMachine.NOMINATING, Errors.AlreadyStarted);
    address sender = _msgSender();
    require(ketherNFTContract.ownerOf(_ownedTokenId) == sender, Errors.MustHaveBalance);

    uint256 pixels = _nominate(_ownedTokenId, _nominateTokenId);
    emit Nominated(termNumber+1, sender, pixels);

    return pixels;
  }

  /**
   * @dev Nominate tokens held by the sender as candidates for magistrate in the next term
   *      Nominations of tokens are independent of their owner.
   * @return Number of nominated pixels
   * TODO
   */
  function nominateAll(uint256 _nominateTokenId) external returns (uint256) {
    require(state == StateMachine.NOMINATING, Errors.AlreadyStarted);
    address sender = _msgSender();
    require(ketherNFTContract.balanceOf(sender) > 0, Errors.MustHaveBalance);

    uint256 pixels = 0;
    for (uint256 i = 0; i < ketherNFTContract.balanceOf(sender); i++) {
      uint256 idx = ketherNFTContract.tokenOfOwnerByIndex(sender, i);
      pixels += _nominate(idx, _nominateTokenId);
    }

    nominatedPixels += pixels;

    emit Nominated(termNumber+1, sender, pixels);
    return pixels;
  }

  function nominateSelf() external returns (uint256) {
    require(state == StateMachine.NOMINATING, Errors.AlreadyStarted);
    address sender = _msgSender();
    require(ketherNFTContract.balanceOf(sender) > 0, Errors.MustHaveBalance);

    uint256 pixels = 0;
    for (uint256 i = 0; i < ketherNFTContract.balanceOf(sender); i++) {
      uint256 idx = ketherNFTContract.tokenOfOwnerByIndex(sender, i);
      pixels += _nominate(idx, idx);
    }

    nominatedPixels += pixels;

    emit Nominated(termNumber+1, sender, pixels);
    return pixels;
  }

  function _nominate(uint256 _ownedTokenId, uint256 _nominateTokenId) internal returns (uint256 pixels) {
      // Only push the ad and update pixel count if it's not been nominated before
      if (!isNominated(_ownedTokenId)) {
        pixels += getAdPixels(_ownedTokenId);
        nominatedTokens.push(_ownedTokenId);
      }

      nominations[_ownedTokenId] = Nomination(termNumber + 1, _nominateTokenId);

      return pixels;
  }

  // TODO: Do we want nominateOther, so people can easily delegate their nominations?

  // TODO: Do we want to have a unNominateSelf()

  /**
   * @dev Stop accepting nominations, start election.
   */
  function startElection() external {
    // FIXME: check that term expired
    require(state == StateMachine.NOMINATING, Errors.AlreadyStarted);
    require(nominatedTokens.length > 0, Errors.MustHaveNominations);
    require(termExpires <= block.timestamp, Errors.TermNotExpired);
    require(LINK.balanceOf(address(this)) >= s_fee, Errors.NotEnoughLink);

    // TODO: check if this is a re-entry vector
    state = StateMachine.WAITING_FOR_ENTROPY;
    requestRandomness(s_keyHash, s_fee);

    emit ElectionExecuting(termNumber);
  }

  /**
   * @dev Assign new magistrate and open up for nominations for next election.
   */
  function completeElection() external {
    require(state == StateMachine.GOT_ENTROPY, Errors.MustHaveEntropy);
    magistrateToken = getNextMagistrateToken();

    // FIXME: This is going to stagger terms, do we want to align them to
    // royalty payouts? Or maybe we could assign payouts to terms on a payment
    // receiver.
    termNumber += 1;
    termStarted = block.timestamp;
    termExpires = termStarted + TERM_DURATION;

    delete nominatedTokens;
    nominatedPixels = 0;
    state = StateMachine.NOMINATING;

    emit ElectionCompleted(termNumber, magistrateToken, getMagistrate());
  }

  // Only magistrate:

  /// @dev Transfer balance controlled by magistrate.
  function withdraw(address payable to) public {
    require(_msgSender() == getMagistrate(), Errors.OnlyMagistrate);
    // NOTE: you have exclusive rights to withdraw until the end of your term.
    // afterwards it becomes a race as someone call call an election.

    // FIXME: Would it be fun if this required having a >2 LINK balance to
    // withdraw? If we wanna be super cute, could automagically buy LINK from
    // the proceeds before transferring the remaining balance.

    to.transfer(address(this).balance);
  }

  /// @dev Cut the term short, leaving enough time for new nominations.
  function stepDown() public {
    require(_msgSender() == getMagistrate(), Errors.OnlyMagistrate);

    uint256 timeRemaining = termExpires - block.timestamp;
    if (timeRemaining > MIN_ELECTION_DURATION) {
      termExpires = block.timestamp + MIN_ELECTION_DURATION;
    }

    emit StepDown(termNumber, magistrateToken, _msgSender());
  }

  // Only owner (admin helpers):

  // TODO: adminUpdateChainlinkValues(bytes32 keyHash, uint256 fee) external onlyOwner

  function adminDelayNextEpoch(uint256 nextEpoch) external onlyOwner {
    // XXX: Implement this.
    // TODO: Should this also allow adjusting the interval?
  }

  /**
   * @dev Withdraw ERC20 tokens, primarily for rescuing remaining LINK once the
   *      experiment is over.
   */
  function adminWithdrawToken(IERC20 token, address to) external onlyOwner {
    // XXX: Add require to confirm that the contract is suspended?
    token.transfer(to, token.balanceOf(address(this)));
  }
}

//SPDX-License-Identifier: MIT
pragma solidity >=0.8.4;

import "@openzeppelin/contracts/access/Ownable.sol";

import "@chainlink/contracts/src/v0.8/VRFConsumerBase.sol";

interface IKetherHomepage {
  function ads(uint _idx) external view returns (address,uint,uint,uint,uint,string memory,string memory,string memory,bool,bool);
  function getAdsLength() view external returns (uint);
}

interface IERC721 {
  function ownerOf(uint256) external view returns (address);
  function balanceOf(address) external view returns (uint256);
  function tokenOfOwnerByIndex(address, uint256) external view returns (uint256);
}

interface IERC20 {
  function balanceOf(address account) external view returns (uint256);
  function transfer(address recipient, uint256 amount) external returns (bool);
}

library Errors {
  string constant MustHaveBalance = "must have tokens to nominate";
  string constant OnlyMagistrate = "only active magistrate can do this";
  string constant MustHaveEntropy = "waiting for entropy";
  string constant MustHaveNominations = "must have nominations";
  string constant AlreadyStarted = "election already started";
  string constant NotExecuted = "election not executed";
  string constant TermNotExpired = "term not expired";
  string constant NotEnoughLink = "not enough LINK";
}

contract KetherSortition is Ownable, VRFConsumerBase {
  event Nomination(
      uint256 indexed termNumber,
      address nominator,
      uint256 pixels
  );

  event ElectionExecuting(
    uint256 indexed termNumber
  );

  event ElectionCompleted(
    uint256 indexed termNumber,
    uint256 magistrateToken,
    address currentTokenOwner
  );

  event StepDown(
    uint256 indexed termNumber,
    uint256 magistrateToken,
    address currentTokenOwner
  );

  // MagistrateToken is tokenId of an NFT whose owner controls the royalties purse for this term.
  uint256 public magistrateToken;

  uint256 constant MIN_ELECTION_DURATION = 2 days;
  uint256 constant TERM_DURATION = 6 weeks;
  uint256 constant PIXELS_PER_CELL = 100;

  uint256 public termStarted;
  uint256 public termExpires;
  uint256 public termNumber = 0;

  IERC721 ketherNFTContract;
  IKetherHomepage ketherContract;

  uint256[] public nominatedTokens;
  uint256 public nominatedPixels = 0;
  mapping(uint256 => uint256) nominations; // mapping of tokenId => termNumber
  // TODO: mapping(uint256 => uint256) electedCount;

  uint256 public electionEntropy; // Provided by Chainlink

  // nominating -[term expired & startElection() calls]> waitingForEntropy -[Chainlink calls into fulfillrandomness()]> gotEntropy -[completeElection()] -> nominating
  enum StateMachine { NOMINATING, WAITING_FOR_ENTROPY, GOT_ENTROPY }
  StateMachine state = StateMachine.NOMINATING;

  // Chainlink values
  bytes32 private s_keyHash;
  uint256 private s_fee;

  constructor(address _ketherNFTContract, address _ketherContract, address vrfCoordinator, address link, bytes32 keyHash, uint256 fee)
  public
  VRFConsumerBase(vrfCoordinator, link) {
    s_keyHash = keyHash;
    s_fee = fee;

    ketherNFTContract = IERC721(_ketherNFTContract);
    ketherContract = IKetherHomepage(_ketherContract);

    termExpires = block.timestamp + MIN_ELECTION_DURATION;
  }

  // Internal helpers:

  /**
   * @dev Only callable by Chainlink VRF, async triggered via startElection().
   */
  function fulfillRandomness(bytes32 requestId, uint256 randomness) internal override {
    require(state == StateMachine.WAITING_FOR_ENTROPY, Errors.NotExecuted);
    electionEntropy = randomness;
    state = StateMachine.GOT_ENTROPY;
  }

  // Views:

  function getMagistrate() public view returns (address) {
    return getAdOwner(magistrateToken);
  }

  function getAdOwner(uint256 _idx) public view returns (address) {
    return ketherNFTContract.ownerOf(_idx);
  }

  function getAdPixels(uint256 _idx) public view returns (uint256) {
    (,,,uint width,uint height,,,,,) = ketherContract.ads(_idx);
    return width * height * PIXELS_PER_CELL;
  }

  function isNominated(uint256 _idx) public view returns (bool) {
    return nominations[_idx] > termNumber;
  }

  function getNextMagistrateToken() public view returns (uint256) {
    require(state == StateMachine.GOT_ENTROPY, Errors.MustHaveEntropy);
    require(nominatedTokens.length > 0, Errors.MustHaveNominations);

    uint256 pixelChosen = electionEntropy % nominatedPixels;
    uint256 curPixel = 0;

    for(uint256 i = 0; i < nominatedTokens.length; i++) {
      uint256 idx = nominatedTokens[i];
      curPixel += getAdPixels(idx);
      if (curPixel > pixelChosen) {
        return idx;
      }
    }
    return 0;
  }

  // External interface:

  /**
   * @dev Nominate tokens held by the sender as candidates for magistrate in the next term.
   *      Nominations of tokens are independent of their owner.
   * @return Number of nominated pixels
   */
  function nominateSelf() external returns (uint256) {
    require(state == StateMachine.NOMINATING, Errors.AlreadyStarted);
    address sender = _msgSender();
    require(ketherNFTContract.balanceOf(sender) > 0, Errors.MustHaveBalance);

    uint256 pixels = 0;
    for (uint256 i = 0; i < ketherNFTContract.balanceOf(sender); i++) {
      uint256 idx = ketherNFTContract.tokenOfOwnerByIndex(sender, i);
      if (!isNominated(idx)) {
        pixels += getAdPixels(idx);
        nominations[idx] = termNumber + 1;
        nominatedTokens.push(idx);
      }
    }

    nominatedPixels += pixels;

    emit Nomination(termNumber, sender, pixels);
    return pixels;
  }

  /*
  // TODO: function nominate(ownedTokenId) external
  function nominate(ownedTokenId, nominateTokenId) external {
  }

  // TODO: function nominateAll() external
  function nominateAll(nominateTokenId) external {
  }
  */

  // TODO: Do we want nominateOther, so people can easily delegate their nominations?

  // TODO: Do we want to have a unNominateSelf()

  /**
   * @dev Stop accepting nominations, start election.
   */
  function startElection() external {
    // FIXME: check that term expired
    require(state == StateMachine.NOMINATING, Errors.AlreadyStarted);
    require(nominatedTokens.length > 0, Errors.MustHaveNominations);
    require(termExpires <= block.timestamp, Errors.TermNotExpired);
    require(LINK.balanceOf(address(this)) >= s_fee, Errors.NotEnoughLink);

    // TODO: check if this is a re-entry vector
    state = StateMachine.WAITING_FOR_ENTROPY;
    requestRandomness(s_keyHash, s_fee);

    emit ElectionExecuting(termNumber);
  }

  /**
   * @dev Assign new magistrate and open up for nominations for next election.
   */
  function completeElection() external {
    require(state == StateMachine.GOT_ENTROPY, Errors.MustHaveEntropy);
    magistrateToken = getNextMagistrateToken();

    // FIXME: This is going to stagger terms, do we want to align them to
    // royalty payouts? Or maybe we could assign payouts to terms on a payment
    // receiver.
    termNumber += 1;
    termStarted = block.timestamp;
    termExpires = termStarted + TERM_DURATION;

    delete nominatedTokens;
    nominatedPixels = 0;
    state = StateMachine.NOMINATING;

    emit ElectionCompleted(termNumber, magistrateToken, getMagistrate());
  }

  // Only magistrate:

  /// @dev Transfer balance controlled by magistrate.
  function withdraw(address payable to) public {
    require(_msgSender() == getMagistrate(), Errors.OnlyMagistrate);
    // NOTE: you have exclusive rights to withdraw until the end of your term.
    // afterwards it becomes a race as someone call call an election.

    // FIXME: Would it be fun if this required having a >2 LINK balance to
    // withdraw? If we wanna be super cute, could automagically buy LINK from
    // the proceeds before transferring the remaining balance.

    to.transfer(address(this).balance);
  }

  /// @dev Cut the term short, leaving enough time for new nominations.
  function stepDown() public {
    require(_msgSender() == getMagistrate(), Errors.OnlyMagistrate);

    uint256 timeRemaining = termExpires - block.timestamp;
    if (timeRemaining > MIN_ELECTION_DURATION) {
      termExpires = block.timestamp + MIN_ELECTION_DURATION;
    }

    emit StepDown(termNumber, magistrateToken, _msgSender());
  }

  // Only owner (admin helpers):

  // TODO: adminUpdateChainlinkValues(bytes32 keyHash, uint256 fee) external onlyOwner

  function adminDelayNextEpoch(uint256 nextEpoch) external onlyOwner {
    // XXX: Implement this.
    // TODO: Should this also allow adjusting the interval?
  }

  /**
   * @dev Withdraw ERC20 tokens, primarily for rescuing remaining LINK once the
   *      experiment is over.
   */
  function adminWithdrawToken(IERC20 token, address to) external onlyOwner {
    // XXX: Add require to confirm that the contract is suspended?
    token.transfer(to, token.balanceOf(address(this)));
  }
}


reduced verbose calls for safemath

reduced verbose calls for safemath

pragma solidity ^0.4.11;
import "./base/Owned.sol";
import "./base/StandardToken.sol";
import "./interface/SalesAgentInterface.sol";
import "./lib/Arithmetic.sol";
import "./lib/SafeMath.sol";

/// @title The main Rocket Pool Token (RPL) contract
/// @author David Rugendyke - http://www.rocketpool.net

/*****************************************************************
*   This is the main Rocket Pool Token (RPL) contract. It features
*   Smart Agent compatibility. The Sale Agent is a new type of
*   contract that can authorise the minting of tokens on behalf of
*   the traditional ERC20 token contract. This allows you to
*   distribute your ICO tokens through multiple Sale Agents,
*   at various times, of various token quantities and of varying
*   fund targets. Once you’ve written a new Sale Agent contract,
*   you can register him with the main ERC20 token contract,
*   he’s then permitted to sell it’s tokens on your behalf using
*   guidelines such as the amount of tokens he’s allowed to sell,
*   the maximum ether he’s allowed to raise, the start block and
*   end blocks he’s allowed to sell between and more.
/****************************************************************/

contract RocketPoolToken is StandardToken, Owned {

     /**** Properties ***********/

    string public name = 'Rocket Pool';
    string public symbol = 'RPL';
    string public version = "1.0";
    // Set our token units
    uint8 public constant decimals = 18;
    uint256 public exponent = 10**uint256(decimals);
    uint256 public totalSupply = 0;                             // The total of tokens currently minted by sales agent contracts
    uint256 public totalSupplyCap = 50 * (10**6) * exponent;    // 50 Million tokens

    /**** Libs *****************/

    using SafeMath for uint;

    /*** Sale Addresses *********/

    mapping (address => salesAgent) private salesAgents;   // Our contract addresses of our sales contracts
    address[] private salesAgentsAddresses;                // Keep an array of all our sales agent addresses for iteration

    /*** Structs ***************/

    struct salesAgent {                     // These are contract addresses that are authorised to mint tokens
        address saleContractAddress;        // Address of the contract
        bytes32 saleContractType;           // Type of the contract ie. presale, crowdsale
        uint256 targetEthMax;               // The max amount of ether the agent is allowed raise
        uint256 targetEthMin;               // The min amount of ether to raise to consider this contracts sales a success
        uint256 tokensLimit;                // The maximum amount of tokens this sale contract is allowed to distribute
        uint256 tokensMinted;               // The current amount of tokens minted by this agent
        uint256 minDeposit;                 // The minimum deposit amount allowed
        uint256 maxDeposit;                 // The maximum deposit amount allowed
        uint256 startBlock;                 // The start block when allowed to mint tokens
        uint256 endBlock;                   // The end block when to finish minting tokens
        address depositAddress;             // The address that receives the ether for that sale contract
        bool depositAddressCheckedIn;       // The address that receives the ether for that sale contract must check in with its sale contract to verify its a valid address that can interact
        bool finalised;                     // Has this sales contract been completed and the ether sent to the deposit address?
        bool exists;                        // Check to see if the mapping exists
    }

    /*** Events ****************/

    event mintToken(address _agent, address _address, uint256 _value);
    event saleFinalised(address _agent, address _address, uint256 _value);

    /*** Tests *****************/

    event FlagUint(uint256 flag);
    event FlagAddress(address flag);

    /*** Modifiers *************/

    /// @dev Only allow access from the latest version of a sales contract
    modifier isSalesContract(address _sender) {
        // Is this an authorised sale contract?
        assert(salesAgents[_sender].exists == true);
        _;
    }

    /**** Methods ***********/

    /// @dev RPL Token Init
    function RocketPoolToken() {}

    // @dev General validation for a sales agent contract receiving a contribution, additional validation can be done in the sale contract if required
    // @param _value The value of the contribution in wei
    // @return A boolean that indicates if the operation was successful.
    function validateContribution(uint256 _value) isSalesContract(msg.sender) returns (bool) {
        // Get an instance of the sale agent contract
        SalesAgentInterface saleAgent = SalesAgentInterface(msg.sender);
        // Did they send anything from a proper address?
        assert(_value > 0);
        // Check the depositAddress has been verified by the account holder
        assert(salesAgents[msg.sender].depositAddressCheckedIn == true);
        // Check if we're ok to receive contributions, have we started?
        assert(block.number > salesAgents[msg.sender].startBlock);
        // Already ended? Or if the end block is 0, it's an open ended sale until finalised by the depositAddress
        assert(block.number < salesAgents[msg.sender].endBlock || salesAgents[msg.sender].endBlock == 0);
        // Is it above the min deposit amount?
        assert(_value >= salesAgents[msg.sender].minDeposit);
        // Is it below the max deposit allowed?
        assert(_value <= salesAgents[msg.sender].maxDeposit);
        // No contributions if the sale contract has finalised
        assert(salesAgents[msg.sender].finalised == false);
        // Does this deposit put it over the max target ether for the sale contract?
        assert(saleAgent.contributedTotal().add(_value) <= salesAgents[msg.sender].targetEthMax);
        // All good
        return true;
    }

    // @dev General validation for a sales agent contract that requires the user claim the tokens after the sale has finished
    // @param _sender The address sent the request
    // @return A boolean that indicates if the operation was successful.
    function validateClaimTokens(address _sender) isSalesContract(msg.sender) returns (bool) {
        // Get an instance of the sale agent contract
        SalesAgentInterface saleAgent = SalesAgentInterface(msg.sender);
        // Must have previously contributed
        assert(saleAgent.getContributionOf(_sender) > 0);
        // Sale contract completed
        assert(block.number > salesAgents[msg.sender].endBlock);
        // All good
        return true;
    }

    // @dev Mint the Rocket Pool Tokens (RPL)
    // @param _to The address that will receive the minted tokens.
    // @param _amount The amount of tokens to mint.
    // @return A boolean that indicates if the operation was successful.
    function mint(address _to, uint _amount) isSalesContract(msg.sender) returns (bool) {
        // Check if we're ok to mint new tokens, have we started?
        // We dont check for the end block as some sale agents mint tokens during the sale, and some after its finished (proportional sales)
        assert(block.number > salesAgents[msg.sender].startBlock);
        // Check the depositAddress has been verified by the designated account holder that will receive the funds from that agent
        assert(salesAgents[msg.sender].depositAddressCheckedIn == true);
        // No minting if the sale contract has finalised
        assert(salesAgents[msg.sender].finalised == false);
        // Check we don't exceed the assigned tokens of the sale agent
        assert(salesAgents[msg.sender].tokensLimit >= salesAgents[msg.sender].tokensMinted.add(_amount));
        // Verify ok balances and values
        assert(_amount > 0);
         // Check we don't exceed the supply limit
        assert(totalSupply.add(_amount) <= totalSupplyCap);
         // Ok all good, automatically checks for overflow with safeMath
        balances[_to] = balances[_to].add(_amount);
        // Add to the total minted for that agent, automatically checks for overflow with safeMath
        salesAgents[msg.sender].tokensMinted = salesAgents[msg.sender].tokensMinted.add(_amount);
        // Add to the overall total minted, automatically checks for overflow with safeMath
        totalSupply = totalSupply.add(_amount);
        // Fire the event
        mintToken(msg.sender, _to, _amount);
        // Completed
        return true;
    }

    /// @dev Returns the amount of tokens that can still be minted
    function getRemainingTokens() public constant returns(uint256)  {
        return totalSupplyCap.sub(totalSupply);
    }

    /// @dev Set the address of a new crowdsale/presale contract agent if needed, usefull for upgrading
    /// @param _saleAddress The address of the new token sale contract
    /// @param _saleContractType Type of the contract ie. presale, crowdsale, quarterly
    /// @param _targetEthMin The min amount of ether to raise to consider this contracts sales a success
    /// @param _targetEthMax The max amount of ether the agent is allowed raise
    /// @param _tokensLimit The maximum amount of tokens this sale contract is allowed to distribute
    /// @param _minDeposit The minimum deposit amount allowed
    /// @param _maxDeposit The maximum deposit amount allowed
    /// @param _startBlock The start block when allowed to mint tokens
    /// @param _endBlock The end block when to finish minting tokens
    /// @param _depositAddress The address that receives the ether for that sale contract
    function setSaleAgentContract(
        address _saleAddress,
         string _saleContractType,
        uint256 _targetEthMin,
        uint256 _targetEthMax,
        uint256 _tokensLimit,
        uint256 _minDeposit,
        uint256 _maxDeposit,
        uint256 _startBlock,
        uint256 _endBlock,
        address _depositAddress
    )
    // Only the owner can register a new sale agent
    public onlyOwner
    {
        // Valid addresses?
        assert(_saleAddress != 0x0 && _depositAddress != 0x0);
        // Must have some available tokens
        assert(_tokensLimit > 0 && _tokensLimit <= totalSupplyCap);
        // Make sure the min deposit is less than or equal to the max
        assert(_minDeposit <= _maxDeposit);
        // Add the new sales contract
        salesAgents[_saleAddress] = salesAgent({
            saleContractAddress: _saleAddress,
            saleContractType: sha3(_saleContractType),
            targetEthMin: _targetEthMin,
            targetEthMax: _targetEthMax,
            tokensLimit: _tokensLimit,
            tokensMinted: 0,
            minDeposit: _minDeposit,
            maxDeposit: _maxDeposit,
            startBlock: _startBlock,
            endBlock: _endBlock,
            depositAddress: _depositAddress,
            depositAddressCheckedIn: false,
            finalised: false,
            exists: true
        });
        // Store our agent address so we can iterate over it if needed
        salesAgentsAddresses.push(_saleAddress);
    }

    /// @dev Sets the contract sale agent process as completed, that sales agent is now retired
    function setSaleContractFinalised(address _sender) isSalesContract(msg.sender) public returns(bool)  {
        // Get an instance of the sale agent contract
        SalesAgentInterface saleAgent = SalesAgentInterface(msg.sender);
        // Finalise the crowdsale funds
        assert(!salesAgents[msg.sender].finalised);
        // The address that will receive this contracts deposit, should match the original senders
        assert(salesAgents[msg.sender].depositAddress == _sender);
        // If the end block is 0, it means an open ended crowdsale, once it's finalised, the end block is set to the current one
        if(salesAgents[msg.sender].endBlock == 0) {
            salesAgents[msg.sender].endBlock = block.number;
        }
        // Not yet finished?
        assert(block.number >= salesAgents[msg.sender].endBlock);
        // Not enough raised?
        assert(saleAgent.contributedTotal() >= salesAgents[msg.sender].targetEthMin);
        // We're done now
        salesAgents[msg.sender].finalised = true;
        // Fire the event
        saleFinalised(msg.sender, _sender, salesAgents[msg.sender].tokensMinted);
        // All good
        return true;
    }

    /// @dev Verifies if the current address matches the depositAddress
    /// @param _verifyAddress The address to verify it matches the depositAddress given for the sales agent
    function setSaleContractDepositAddressVerified(address _verifyAddress) isSalesContract(msg.sender) public  {
        // Check its verified
        assert(salesAgents[msg.sender].depositAddress == _verifyAddress && _verifyAddress != 0x0);
        // Ok set it now
        salesAgents[msg.sender].depositAddressCheckedIn = true;
    }

    /// @dev Returns true if this sales contract has finalised
    /// @param _salesAgentAddress The address of the token sale agent contract
    function getSaleContractIsFinalised(address _salesAgentAddress) constant isSalesContract(_salesAgentAddress) public returns(bool)  {
        return salesAgents[_salesAgentAddress].finalised;
    }

    /// @dev Returns the min target amount of ether the contract wants to raise
    /// @param _salesAgentAddress The address of the token sale agent contract
    function getSaleContractTargetEtherMin(address _salesAgentAddress) constant isSalesContract(_salesAgentAddress) public returns(uint256)  {
        return salesAgents[_salesAgentAddress].targetEthMin;
    }

    /// @dev Returns the max target amount of ether the contract can raise
    /// @param _salesAgentAddress The address of the token sale agent contract
    function getSaleContractTargetEtherMax(address _salesAgentAddress) constant isSalesContract(_salesAgentAddress) public returns(uint256)  {
        return salesAgents[_salesAgentAddress].targetEthMax;
    }

    /// @dev Returns the min deposit amount of ether
    /// @param _salesAgentAddress The address of the token sale agent contract
    function getSaleContractDepositEtherMin(address _salesAgentAddress) constant isSalesContract(_salesAgentAddress) public returns(uint256)  {
        return salesAgents[_salesAgentAddress].minDeposit;
    }

    /// @dev Returns the max deposit amount of ether
    /// @param _salesAgentAddress The address of the token sale agent contract
    function getSaleContractDepositEtherMax(address _salesAgentAddress) constant isSalesContract(_salesAgentAddress) public returns(uint256)  {
        return salesAgents[_salesAgentAddress].maxDeposit;
    }

    /// @dev Returns the address where the sale contracts ether will be deposited
    /// @param _salesAgentAddress The address of the token sale agent contract
    function getSaleContractDepositAddress(address _salesAgentAddress) constant isSalesContract(_salesAgentAddress) public returns(address)  {
        return salesAgents[_salesAgentAddress].depositAddress;
    }

    /// @dev Returns the true if the sale agents deposit address has been verified
    /// @param _salesAgentAddress The address of the token sale agent contract
    function getSaleContractDepositAddressVerified(address _salesAgentAddress) constant isSalesContract(_salesAgentAddress) public returns(bool)  {
        return salesAgents[_salesAgentAddress].depositAddressCheckedIn;
    }

    /// @dev Returns the start block for the sale agent
    /// @param _salesAgentAddress The address of the token sale agent contract
    function getSaleContractStartBlock(address _salesAgentAddress) constant isSalesContract(_salesAgentAddress) public returns(uint256)  {
        return salesAgents[_salesAgentAddress].startBlock;
    }

    /// @dev Returns the start block for the sale agent
    /// @param _salesAgentAddress The address of the token sale agent contract
    function getSaleContractEndBlock(address _salesAgentAddress) constant isSalesContract(_salesAgentAddress) public returns(uint256)  {
        return salesAgents[_salesAgentAddress].endBlock;
    }

    /// @dev Returns the max tokens for the sale agent
    /// @param _salesAgentAddress The address of the token sale agent contract
    function getSaleContractTokensLimit(address _salesAgentAddress) constant isSalesContract(_salesAgentAddress) public returns(uint256)  {
        return salesAgents[_salesAgentAddress].tokensLimit;
    }

    /// @dev Returns the token total currently minted by the sale agent
    /// @param _salesAgentAddress The address of the token sale agent contract
    function getSaleContractTokensMinted(address _salesAgentAddress) constant isSalesContract(_salesAgentAddress) public returns(uint256)  {
        return salesAgents[_salesAgentAddress].tokensMinted;
    }

}

pragma solidity ^0.4.11;
import "./base/Owned.sol";
import "./base/StandardToken.sol";
import "./interface/SalesAgentInterface.sol";
import "./lib/Arithmetic.sol";
import "./lib/SafeMath.sol";

/// @title The main Rocket Pool Token (RPL) contract
/// @author David Rugendyke - http://www.rocketpool.net

/*****************************************************************
*   This is the main Rocket Pool Token (RPL) contract. It features
*   Smart Agent compatibility. The Sale Agent is a new type of
*   contract that can authorise the minting of tokens on behalf of
*   the traditional ERC20 token contract. This allows you to
*   distribute your ICO tokens through multiple Sale Agents,
*   at various times, of various token quantities and of varying
*   fund targets. Once you’ve written a new Sale Agent contract,
*   you can register him with the main ERC20 token contract,
*   he’s then permitted to sell it’s tokens on your behalf using
*   guidelines such as the amount of tokens he’s allowed to sell,
*   the maximum ether he’s allowed to raise, the start block and
*   end blocks he’s allowed to sell between and more.
/****************************************************************/

contract RocketPoolToken is StandardToken, Owned {

     /**** Properties ***********/

    string public name = 'Rocket Pool';
    string public symbol = 'RPL';
    string public version = "1.0";
    // Set our token units
    uint8 public constant decimals = 18;
    uint256 public exponent = 10**uint256(decimals);
    uint256 public totalSupply = 0;                             // The total of tokens currently minted by sales agent contracts
    uint256 public totalSupplyCap = 50 * (10**6) * exponent;    // 50 Million tokens

    /*** Sale Addresses *********/

    mapping (address => salesAgent) private salesAgents;   // Our contract addresses of our sales contracts
    address[] private salesAgentsAddresses;                // Keep an array of all our sales agent addresses for iteration

    /*** Structs ***************/

    struct salesAgent {                     // These are contract addresses that are authorised to mint tokens
        address saleContractAddress;        // Address of the contract
        bytes32 saleContractType;           // Type of the contract ie. presale, crowdsale
        uint256 targetEthMax;               // The max amount of ether the agent is allowed raise
        uint256 targetEthMin;               // The min amount of ether to raise to consider this contracts sales a success
        uint256 tokensLimit;                // The maximum amount of tokens this sale contract is allowed to distribute
        uint256 tokensMinted;               // The current amount of tokens minted by this agent
        uint256 minDeposit;                 // The minimum deposit amount allowed
        uint256 maxDeposit;                 // The maximum deposit amount allowed
        uint256 startBlock;                 // The start block when allowed to mint tokens
        uint256 endBlock;                   // The end block when to finish minting tokens
        address depositAddress;             // The address that receives the ether for that sale contract
        bool depositAddressCheckedIn;       // The address that receives the ether for that sale contract must check in with its sale contract to verify its a valid address that can interact
        bool finalised;                     // Has this sales contract been completed and the ether sent to the deposit address?
        bool exists;                        // Check to see if the mapping exists
    }

    /*** Events ****************/

    event mintToken(address _agent, address _address, uint256 _value);
    event saleFinalised(address _agent, address _address, uint256 _value);

    /*** Tests *****************/

    event FlagUint(uint256 flag);
    event FlagAddress(address flag);

    /*** Modifiers *************/

    /// @dev Only allow access from the latest version of a sales contract
    modifier isSalesContract(address _sender) {
        // Is this an authorised sale contract?
        assert(salesAgents[_sender].exists == true);
        _;
    }

    /**** Methods ***********/

    /// @dev RPL Token Init
    function RocketPoolToken() {}

    // @dev General validation for a sales agent contract receiving a contribution, additional validation can be done in the sale contract if required
    // @param _value The value of the contribution in wei
    // @return A boolean that indicates if the operation was successful.
    function validateContribution(uint256 _value) isSalesContract(msg.sender) returns (bool) {
        // Get an instance of the sale agent contract
        SalesAgentInterface saleAgent = SalesAgentInterface(msg.sender);
        // Did they send anything from a proper address?
        assert(_value > 0);
        // Check the depositAddress has been verified by the account holder
        assert(salesAgents[msg.sender].depositAddressCheckedIn == true);
        // Check if we're ok to receive contributions, have we started?
        assert(block.number > salesAgents[msg.sender].startBlock);
        // Already ended? Or if the end block is 0, it's an open ended sale until finalised by the depositAddress
        assert(block.number < salesAgents[msg.sender].endBlock || salesAgents[msg.sender].endBlock == 0);
        // Is it above the min deposit amount?
        assert(_value >= salesAgents[msg.sender].minDeposit);
        // Is it below the max deposit allowed?
        assert(_value <= salesAgents[msg.sender].maxDeposit);
        // No contributions if the sale contract has finalised
        assert(salesAgents[msg.sender].finalised == false);
        // Does this deposit put it over the max target ether for the sale contract?
        assert(SafeMath.add(saleAgent.contributedTotal(), _value) <= salesAgents[msg.sender].targetEthMax);
        // All good
        return true;
    }

    // @dev General validation for a sales agent contract that requires the user claim the tokens after the sale has finished
    // @param _sender The address sent the request
    // @return A boolean that indicates if the operation was successful.
    function validateClaimTokens(address _sender) isSalesContract(msg.sender) returns (bool) {
        // Get an instance of the sale agent contract
        SalesAgentInterface saleAgent = SalesAgentInterface(msg.sender);
        // Must have previously contributed
        assert(saleAgent.getContributionOf(_sender) > 0);
        // Sale contract completed
        assert(block.number > salesAgents[msg.sender].endBlock);
        // All good
        return true;
    }

    // @dev Mint the Rocket Pool Tokens (RPL)
    // @param _to The address that will receive the minted tokens.
    // @param _amount The amount of tokens to mint.
    // @return A boolean that indicates if the operation was successful.
    function mint(address _to, uint _amount) isSalesContract(msg.sender) returns (bool) {
        // Check if we're ok to mint new tokens, have we started?
        // We dont check for the end block as some sale agents mint tokens during the sale, and some after its finished (proportional sales)
        assert(block.number > salesAgents[msg.sender].startBlock);
        // Check the depositAddress has been verified by the designated account holder that will receive the funds from that agent
        assert(salesAgents[msg.sender].depositAddressCheckedIn == true);
        // No minting if the sale contract has finalised
        assert(salesAgents[msg.sender].finalised == false);
        // Check we don't exceed the assigned tokens of the sale agent
        assert(salesAgents[msg.sender].tokensLimit >= SafeMath.add(salesAgents[msg.sender].tokensMinted, _amount));
        // Verify ok balances and values
        assert(_amount > 0);
         // Check we don't exceed the supply limit
        assert(SafeMath.add(totalSupply, _amount) <= totalSupplyCap);
         // Ok all good, automatically checks for overflow with safeMath
        balances[_to] = SafeMath.add(balances[_to], _amount);
        // Add to the total minted for that agent, automatically checks for overflow with safeMath
        salesAgents[msg.sender].tokensMinted = SafeMath.add(salesAgents[msg.sender].tokensMinted, _amount);
        // Add to the overall total minted, automatically checks for overflow with safeMath
        totalSupply = SafeMath.add(totalSupply, _amount);
        // Fire the event
        mintToken(msg.sender, _to, _amount);
        // Completed
        return true;
    }

    /// @dev Returns the amount of tokens that can still be minted
    function getRemainingTokens() public constant returns(uint256)  {
        return SafeMath.sub(totalSupplyCap, totalSupply);
    }

    /// @dev Set the address of a new crowdsale/presale contract agent if needed, usefull for upgrading
    /// @param _saleAddress The address of the new token sale contract
    /// @param _saleContractType Type of the contract ie. presale, crowdsale, quarterly
    /// @param _targetEthMin The min amount of ether to raise to consider this contracts sales a success
    /// @param _targetEthMax The max amount of ether the agent is allowed raise
    /// @param _tokensLimit The maximum amount of tokens this sale contract is allowed to distribute
    /// @param _minDeposit The minimum deposit amount allowed
    /// @param _maxDeposit The maximum deposit amount allowed
    /// @param _startBlock The start block when allowed to mint tokens
    /// @param _endBlock The end block when to finish minting tokens
    /// @param _depositAddress The address that receives the ether for that sale contract
    function setSaleAgentContract(
        address _saleAddress,
         string _saleContractType,
        uint256 _targetEthMin,
        uint256 _targetEthMax,
        uint256 _tokensLimit,
        uint256 _minDeposit,
        uint256 _maxDeposit,
        uint256 _startBlock,
        uint256 _endBlock,
        address _depositAddress
    )
    // Only the owner can register a new sale agent
    public onlyOwner
    {
        // Valid addresses?
        assert(_saleAddress != 0x0 && _depositAddress != 0x0);
        // Must have some available tokens
        assert(_tokensLimit > 0 && _tokensLimit <= totalSupplyCap);
        // Make sure the min deposit is less than or equal to the max
        assert(_minDeposit <= _maxDeposit);
        // Add the new sales contract
        salesAgents[_saleAddress] = salesAgent({
            saleContractAddress: _saleAddress,
            saleContractType: sha3(_saleContractType),
            targetEthMin: _targetEthMin,
            targetEthMax: _targetEthMax,
            tokensLimit: _tokensLimit,
            tokensMinted: 0,
            minDeposit: _minDeposit,
            maxDeposit: _maxDeposit,
            startBlock: _startBlock,
            endBlock: _endBlock,
            depositAddress: _depositAddress,
            depositAddressCheckedIn: false,
            finalised: false,
            exists: true
        });
        // Store our agent address so we can iterate over it if needed
        salesAgentsAddresses.push(_saleAddress);
    }

    /// @dev Sets the contract sale agent process as completed, that sales agent is now retired
    function setSaleContractFinalised(address _sender) isSalesContract(msg.sender) public returns(bool)  {
        // Get an instance of the sale agent contract
        SalesAgentInterface saleAgent = SalesAgentInterface(msg.sender);
        // Finalise the crowdsale funds
        assert(!salesAgents[msg.sender].finalised);
        // The address that will receive this contracts deposit, should match the original senders
        assert(salesAgents[msg.sender].depositAddress == _sender);
        // If the end block is 0, it means an open ended crowdsale, once it's finalised, the end block is set to the current one
        if(salesAgents[msg.sender].endBlock == 0) {
            salesAgents[msg.sender].endBlock = block.number;
        }
        // Not yet finished?
        assert(block.number >= salesAgents[msg.sender].endBlock);
        // Not enough raised?
        assert(saleAgent.contributedTotal() >= salesAgents[msg.sender].targetEthMin);
        // We're done now
        salesAgents[msg.sender].finalised = true;
        // Fire the event
        saleFinalised(msg.sender, _sender, salesAgents[msg.sender].tokensMinted);
        // All good
        return true;
    }

    /// @dev Verifies if the current address matches the depositAddress
    /// @param _verifyAddress The address to verify it matches the depositAddress given for the sales agent
    function setSaleContractDepositAddressVerified(address _verifyAddress) isSalesContract(msg.sender) public  {
        // Check its verified
        assert(salesAgents[msg.sender].depositAddress == _verifyAddress && _verifyAddress != 0x0);
        // Ok set it now
        salesAgents[msg.sender].depositAddressCheckedIn = true;
    }

    /// @dev Returns true if this sales contract has finalised
    /// @param _salesAgentAddress The address of the token sale agent contract
    function getSaleContractIsFinalised(address _salesAgentAddress) constant isSalesContract(_salesAgentAddress) public returns(bool)  {
        return salesAgents[_salesAgentAddress].finalised;
    }

    /// @dev Returns the min target amount of ether the contract wants to raise
    /// @param _salesAgentAddress The address of the token sale agent contract
    function getSaleContractTargetEtherMin(address _salesAgentAddress) constant isSalesContract(_salesAgentAddress) public returns(uint256)  {
        return salesAgents[_salesAgentAddress].targetEthMin;
    }

    /// @dev Returns the max target amount of ether the contract can raise
    /// @param _salesAgentAddress The address of the token sale agent contract
    function getSaleContractTargetEtherMax(address _salesAgentAddress) constant isSalesContract(_salesAgentAddress) public returns(uint256)  {
        return salesAgents[_salesAgentAddress].targetEthMax;
    }

    /// @dev Returns the min deposit amount of ether
    /// @param _salesAgentAddress The address of the token sale agent contract
    function getSaleContractDepositEtherMin(address _salesAgentAddress) constant isSalesContract(_salesAgentAddress) public returns(uint256)  {
        return salesAgents[_salesAgentAddress].minDeposit;
    }

    /// @dev Returns the max deposit amount of ether
    /// @param _salesAgentAddress The address of the token sale agent contract
    function getSaleContractDepositEtherMax(address _salesAgentAddress) constant isSalesContract(_salesAgentAddress) public returns(uint256)  {
        return salesAgents[_salesAgentAddress].maxDeposit;
    }

    /// @dev Returns the address where the sale contracts ether will be deposited
    /// @param _salesAgentAddress The address of the token sale agent contract
    function getSaleContractDepositAddress(address _salesAgentAddress) constant isSalesContract(_salesAgentAddress) public returns(address)  {
        return salesAgents[_salesAgentAddress].depositAddress;
    }

    /// @dev Returns the true if the sale agents deposit address has been verified
    /// @param _salesAgentAddress The address of the token sale agent contract
    function getSaleContractDepositAddressVerified(address _salesAgentAddress) constant isSalesContract(_salesAgentAddress) public returns(bool)  {
        return salesAgents[_salesAgentAddress].depositAddressCheckedIn;
    }

    /// @dev Returns the start block for the sale agent
    /// @param _salesAgentAddress The address of the token sale agent contract
    function getSaleContractStartBlock(address _salesAgentAddress) constant isSalesContract(_salesAgentAddress) public returns(uint256)  {
        return salesAgents[_salesAgentAddress].startBlock;
    }

    /// @dev Returns the start block for the sale agent
    /// @param _salesAgentAddress The address of the token sale agent contract
    function getSaleContractEndBlock(address _salesAgentAddress) constant isSalesContract(_salesAgentAddress) public returns(uint256)  {
        return salesAgents[_salesAgentAddress].endBlock;
    }

    /// @dev Returns the max tokens for the sale agent
    /// @param _salesAgentAddress The address of the token sale agent contract
    function getSaleContractTokensLimit(address _salesAgentAddress) constant isSalesContract(_salesAgentAddress) public returns(uint256)  {
        return salesAgents[_salesAgentAddress].tokensLimit;
    }

    /// @dev Returns the token total currently minted by the sale agent
    /// @param _salesAgentAddress The address of the token sale agent contract
    function getSaleContractTokensMinted(address _salesAgentAddress) constant isSalesContract(_salesAgentAddress) public returns(uint256)  {
        return salesAgents[_salesAgentAddress].tokensMinted;
    }

}


Fix Campaign

Fix Campaign

 contract communityContract {
  mapping (address => uint) public communitiesToOwner;
  function getMemberName(uint communityId, address _member) returns(bytes32) {}
}

contract CampaignContract {

  communityContract public community;

  struct Campaign {
    uint uuid;
    uint communityId;
    address owner;
    bytes32 name;
    bytes32 description;
    bytes32 image;
    uint amountNeed;
    uint amountReceive;
    bool done;
  }

  struct Collaborator {
    uint uuid;
    address owner;
    bytes32 name;
    bytes32 description;
    uint amount;
  }

  Campaign[] public campaigns;
  Collaborator[] public collaborators;

  mapping (address => uint[]) public ownerToCampaigns;
  mapping (uint => uint[]) public campaignToCollaborates;

  modifier isOwnerOfCommunity (uint communityId) {
    if ( community.communitiesToOwner(msg.sender) != communityId ) return;
    _
  }

  modifier isOwnerOfCampaign (uint campaignId) {
    uint[] campaignsOfSender = ownerToCampaigns[msg.sender];
    uint count = campaignsOfSender.length;
    bool found = false;
    if( count > 0 ){
      for( uint i = 0; i < count; i++ ){
        if( campaignsOfSender[i] == campaignId ){
          found = true;
          break;
        }
      }
    }
    if(!found) return;
    _
  }

  modifier campaignIsNotDone (uint campaign) {
    if ( campaigns[campaign].done ) return;
    _
  }

  function CampaignContract(communityContract _community){
    community = _community;
  }

  function createCampaign(uint _community, bytes32 _name, bytes32 _description, bytes32 _image) isOwnerOfCommunity (_community) {
    uint uuid = campaigns.length++;
    campaigns[uuid] = Campaign({
      uuid: uuid,
      communityId: _community,
      owner: msg.sender,
      name: _name,
      description: _description,
      image: _image,
      amountNeed: 0,
      amountReceive: 0,
      done: false
    });
    uint[] campaignsOfSender = ownerToCampaigns[msg.sender];
    campaignsOfSender[campaignsOfSender.length++] = uuid;
    ownerToCampaigns[msg.sender] = campaignsOfSender;
  }

  function addCollaborate(uint _campaign, address _collaborator, bytes32 _description, uint _amount) isOwnerOfCampaign(_campaign) campaignIsNotDone(_campaign) {
    uint uuid = collaborators.length++;
    Campaign camp = campaigns[_campaign];
    bytes32 memberName = community.getMemberName(camp.communityId, _collaborator);
    collaborators[uuid] = Collaborator({
      uuid: uuid,
      owner: _collaborator,
      name: memberName,
      description: _description,
      amount: _amount
    });
    camp.amountNeed += _amount;
    campaigns[_campaign] = camp;
    addCollaborateToCampaign(_campaign, uuid);
  }

  function addCollaborateToCampaign(uint _campaign, uint _collaborate) internal {
    uint[] campaignToCollaboratesIds = campaignToCollaborates[_campaign];
    campaignToCollaborates[_campaign][campaignToCollaboratesIds.length++] = _collaborate;
  }

  function donateToCampaign(uint _campaign, uint amount) campaignIsNotDone(_campaign) {
  }

  function concludeCampaign(uint _campaign) isOwnerOfCampaign(_campaign) campaignIsNotDone(_campaign) {

  }

  function () { throw; }
}

contract communityContract {
}

contract CampaignContract {

  struct Campaign {
    uint uuid;
    uint communityId;
    address owner;
    bytes32 name;
    bytes32 description;
    bytes32 image;
    uint amountNeed;
    uint amountReceive;
    bool done;
  }

  struct Collaborator {
    uint uuid;
    address owner;
    bytes32 name;
    bytes32 description;
    uint amount;
  }

  Campaign[] public compaigns;
  Collaborator[] public collaborators;

  mapping (address => uint[]) public ownerToCampaigns;
  mapping (uint => uint[]) public campaignToCollaborates;

  modifier isOwnerOfCommunity (communityId) {
    if ( communityContract.communitiesToOwner[msg.sender] != communityId ) return;
    _
  }

  modifier isOwnerOfCampaign (campaignId) {
    uint[] campaignsOfSender = ownerToCampaigns[msg.sender];
    uint count = campaignsOfSender.length;
    if( count > 0 ){
      for( uint i = 0; i < count; i++ ){
        if( campaignOfSender[i] == campaignId ){
          return true;
        }
      }
    }
    return false;
  }

  function createCampaign(uint _community, bytes32 _name, bytes32 _description, byte32 _image) isOwnerOfCommunity (_community) {
    uint uuid = campaigns.length++;
    campaigns[uuid] = Campaign({
      uuid: uuid,
      communityId: _community,
      owner: msg.sender,
      name: _name,
      description, _description,
      image: _image,
      amountNeed: 0,
      amountReceive: 0,
      done: false
    });
    uint[] campaignsOfSender = ownerToCampaigns[msg.sender];
    campaignsOfSender[campaignsOfSender.length++] = uuid;
    ownerToCampaigns[msg.sender] = campaignsOfSender;
  }

  function addCollaborate(uint _campaign, address _collaborator, bytes32 _description, uint _amount) isOwnerOfCampaign(_campaign) {
    uint uuid = collaborators.length++;
    Campaign camp = campaigns[_campaign];
    Member member = communityContract.getMemberName(camp.communityId, _collaborator);
    collaborators[uuid] = Collaborate({
      uuid: uuid,
      owner: number.address,
      name: member.name,
      description: _description,
      amount: _amount
    });
    camp.amountNeed += amount;
    campaigns[_campaign] = camp;
    uint[] campaignToCollaboratesIds = campaignToCollaborates[campaign];
    campaignToCollaborates[campaign][campaignToCollaboratesIds.length++] = uuid;
  }

  function donateToCampaign(uint _campaign, uint amount) {

  }

  function concludeCampaign(uint _campaign) isOwnerOfCampaign(_campaign) {

  }

  function () { throw; }
}


use modifier onlyOwner for method security

contract Token {
  address public owner;
  uint256 public maxTokens;

  mapping (address => uint256) public balances;
  /*array addresses;*/

  /* public event on the blockchain that will notify clients */
  /*event Transfer(address indexed from, address indexed to, uint256 value);*/

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

  function Token() {
    owner = msg.sender; // contract owner is contract creator
    maxTokens = 10000000;
  }

  // owner functions ----------------------------
  function setMaxTokens(uint256 _maxTokens) onlyOwner {
      maxTokens = _maxTokens;
  }

  function issue(address _to, uint256 _value) onlyOwner {
    if (_value <= maxTokens) {
      balances[_to] = _value;
    }
  }

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

  // user functions -------------------------------
  function transfer(address _to, uint256 _value) {
    if (balances[msg.sender] >= _value) {           // Check if the sender has enough*/
      if (balances[_to] + _value < balances[_to]) throw;  // Check for overflows

      balances[msg.sender] -= _value;                     // Subtract from the sender
      balances[_to] += _value;                            // Add the same to the recipient
    }
    /*Transfer(msg.sender, _to, _value);                   // Notify anyone listening that this transfer took place*/
  }

  function getBalance(address addr) returns(uint256) {
    return balances[addr];
  }

  /* This unnamed function is called whenever someone tries to transfer ether to it */
  function () {
    throw;     // Prevents accidental sending of ether
  }
}

contract Token {
  address public owner;
  uint256 public maxTokens;

  mapping (address => uint256) public balances;
  /*array addresses;*/

  /* public event on the blockchain that will notify clients */
  /*event Transfer(address indexed from, address indexed to, uint256 value);*/

  function Token() {
    owner = msg.sender; // contract owner is contract creator
    maxTokens = 10000000;
  }

  function setMaxTokens(uint256 _maxTokens) {
    if (msg.sender == owner) {
      maxTokens = _maxTokens;
    }
  }

  function issue(address _to, uint256 _value) {
    if (msg.sender == owner && _value <= maxTokens) {
      balances[_to] = _value;
    }
  }

  function transfer(address _to, uint256 _value) {
    if (balances[msg.sender] >= _value) {           // Check if the sender has enough*/
      if (balances[_to] + _value < balances[_to]) throw;  // Check for overflows

      balances[msg.sender] -= _value;                     // Subtract from the sender
      balances[_to] += _value;                            // Add the same to the recipient
    }
    /*Transfer(msg.sender, _to, _value);                   // Notify anyone listening that this transfer took place*/
  }

  function getBalance(address addr) returns(uint256) {
    return balances[addr];
  }

  function setOwner(address _newOwner) {
    if (msg.sender == owner) {
      owner = _newOwner;
    }
  }

  /* This unnamed function is called whenever someone tries to transfer ether to it */
  function () {
    throw;     // Prevents accidental sending of ether
  }
}


Consistent style on token.sol

Consistent style on token.sol

pragma solidity ^0.4.11;

import './ERC223ReceivingContract.sol';

/// @title Base Token contract - Functions to be implemented by token contracts.
contract Token {
    /*
     * Implements ERC 20 standard.
     * https://github.com/ethereum/EIPs/blob/f90864a3d2b2b45c4decf95efd26b3f0c276051a/EIPS/eip-20-token-standard.md
     * https://github.com/ethereum/EIPs/issues/20
     *
     *  Added support for the ERC 223 "tokenFallback" method in a "transfer" function with a payload.
     *  https://github.com/ethereum/EIPs/issues/223
     */

    /*
     * This is a slight change to the ERC20 base standard.
     * function totalSupply() constant returns (uint256 supply);
     * is replaced with:
     * uint256 public totalSupply;
     * This automatically creates a getter function for the totalSupply.
     * This is moved to the base contract since public getter functions are not
     * currently recognised as an implementation of the matching abstract
     * function by the compiler.
     */
    uint256 public totalSupply;

    /*
     * ERC 20
     */
    function balanceOf(address _owner) constant returns (uint256 balance);
    function transfer(address _to, uint256 _value) returns (bool success);
    function transferFrom(address _from, address _to, uint256 _value) returns (bool success);
    function approve(address _spender, uint256 _value) returns (bool success);
    function allowance(address _owner, address _spender) constant returns (uint256 remaining);

    /*
     * ERC 223
     */
    function transfer(address _to, uint256 _value, bytes _data) returns (bool success);

    /*
     * Events
     */
    event Transfer(address indexed _from, address indexed _to, uint256 _value);
    event Approval(address indexed _owner, address indexed _spender, uint256 _value);
}

/// @title Standard token contract - Standard token implementation.
contract StandardToken is Token {

    /*
     * Data structures
     */
    mapping (address => uint256) balances;
    mapping (address => mapping (address => uint256)) allowed;

    /*
     * Public functions
     */
    /// @notice Send `_value` tokens to `_to` from `msg.sender`.
    /// @dev Transfers sender's tokens to a given address. Returns success.
    /// @param _to Address of token receiver.
    /// @param _value Number of tokens to transfer.
    /// @return Returns success of function call.
    function transfer(address _to, uint256 _value) public returns (bool) {
        require(_to != 0x0);
        require(balances[msg.sender] >= _value);
        require(balances[_to] + _value >= balances[_to]);

        balances[msg.sender] -= _value;
        balances[_to] += _value;

        Transfer(msg.sender, _to, _value);

        return true;
    }

    /// @notice Send `_value` tokens to `_to` from `msg.sender` and trigger
    /// tokenFallback if sender is a contract.
    /// @dev Function that is called when a user or another contract wants to transfer funds.
    /// @param _to Address of token receiver.
    /// @param _value Number of tokens to transfer.
    /// @param _data Data to be sent to tokenFallback
    /// @return Returns success of function call.
    function transfer(
        address _to,
        uint256 _value,
        bytes _data)
        public
        returns (bool)
    {
        assert(transfer(_to, _value));

        uint codeLength;

        assembly {
            // Retrieve the size of the code on target address, this needs assembly.
            codeLength := extcodesize(_to)
        }

        if(codeLength > 0) {
            ERC223ReceivingContract receiver = ERC223ReceivingContract(_to);
            receiver.tokenFallback(msg.sender, _value, _data);
        }

        return true;
    }

    /// @notice Transfer `_value` tokens from `_from` to `_to` if `msg.sender` is allowed.
    /// @dev Allows for an approved third party to transfer tokens from one
    /// address to another. Returns success.
    /// @param _from Address from where tokens are withdrawn.
    /// @param _to Address to where tokens are sent.
    /// @param _value Number of tokens to transfer.
    /// @return Returns success of function call.
    function transferFrom(address _from, address _to, uint256 _value)
        public
        returns (bool)
    {
        require(_from != 0x0);
        require(_to != 0x0);
        require(balances[_from] >= _value);
        require(allowed[_from][msg.sender] >= _value);
        require(balances[_to] + _value >= balances[_to]);

        balances[_to] += _value;
        balances[_from] -= _value;
        allowed[_from][msg.sender] -= _value;

        Transfer(_from, _to, _value);

        return true;
    }

    /// @notice Allows `_spender` to transfer `_value` tokens from `msg.sender` to any address.
    /// @dev Sets approved amount of tokens for spender. Returns success.
    /// @param _spender Address of allowed account.
    /// @param _value Number of approved tokens.
    /// @return Returns success of function call.
    function approve(address _spender, uint256 _value) public returns (bool) {
        require(_spender != 0x0);
        require(_value > 0);

        allowed[msg.sender][_spender] = _value;
        Approval(msg.sender, _spender, _value);
        return true;
    }

    /*
     * Read functions
     */
    /// @dev Returns number of allowed tokens that a spender can transfer in
    /// behalf of a token owner.
    /// @param _owner Address of token owner.
    /// @param _spender Address of token spender.
    /// @return Returns remaining allowance for spender.
    function allowance(address _owner, address _spender)
        constant
        public
        returns (uint256)
    {
        return allowed[_owner][_spender];
    }

    /// @dev Returns number of tokens owned by the given address.
    /// @param _owner Address of token owner.
    /// @return Returns balance of owner.
    function balanceOf(address _owner) constant public returns (uint256) {
        return balances[_owner];
    }
}

/// @title Custom Token
contract CustomToken is StandardToken {

    /*
     *  Terminology:
     *  1 token unit = Tei
     *  1 token = TKN = Tei * multiplier
     *  multiplier set from token's number of decimals (i.e. 10**decimals)
     */

    /*
     *  Token metadata
     */
    string constant public name = "The Token";
    string constant public symbol = "TKN";
    uint8 constant public decimals = 18;
    uint constant multiplier = 10**uint(decimals);

    address public owner;
    address public auction_address;

    event Deployed(
        address indexed _auction,
        uint indexed _total_supply,
        uint indexed _auction_supply
    );
    event Burnt(
        address indexed _receiver,
        uint indexed _num,
        uint indexed _total_supply
    );

    /*
     *  Public functions
     */
    /// @dev Contract constructor function sets dutch auction contract address
    /// and assigns all tokens to dutch auction.
    /// @param auction Address of dutch auction contract.
    /// @param initial_supply Number of initially provided token units (Tei).
    /// @param owners Array of addresses receiving preassigned tokens.
    /// @param tokens Array of preassigned token units (Tei).
    function CustomToken(
        address auction,
        uint initial_supply,
        address[] owners,
        uint[] tokens)
        public
    {
        // Auction address should not be null.
        require(auction != 0x0);
        require(owners.length == tokens.length);
        // Initial supply is in Tei
        require(initial_supply > multiplier);

        owner = msg.sender;
        auction_address = auction;

        // Total supply of Tei at deployment
        totalSupply = initial_supply;

        // Preallocate tokens to beneficiaries
        uint prealloc_tokens;
        for (uint i=0; i<owners.length; i++) {
            // Address should not be null.
            require(owners[i] != 0x0);
            require(tokens[i] > 0);
            require(balances[owners[i]] + tokens[i] > balances[owners[i]]);
            require(prealloc_tokens + tokens[i] > prealloc_tokens);

            balances[owners[i]] += tokens[i];
            prealloc_tokens += tokens[i];
            Transfer(0, owners[i], tokens[i]);
        }

        balances[auction_address] = totalSupply - prealloc_tokens;
        Transfer(0, auction_address, balances[auction]);

        Deployed(auction_address, totalSupply, balances[auction]);

        assert(totalSupply == balances[auction_address] + prealloc_tokens);
    }

    /// @notice Allows `msg.sender` to simply destroy `num` token units (Tei),
    /// without receiving the corresponding amount of ether. This means the total
    /// token supply will decrease.
    /// @dev Allows to destroy token units (Tei) without receiving the
    /// corresponding amount of ether.
    /// @param num Number of token units (Tei) to burn.
    function burn(uint num) public {
        require(num > 0);
        require(balances[msg.sender] >= num);
        require(totalSupply >= num);

        uint pre_balance = balances[msg.sender];

        balances[msg.sender] -= num;
        totalSupply -= num;
        Burnt(msg.sender, num, totalSupply);

        assert(balances[msg.sender] == pre_balance - num);
    }

}

pragma solidity ^0.4.11;

import './ERC223ReceivingContract.sol';

/// @title Base Token contract - Functions to be implemented by token contracts.
contract Token {
    /*
        Implements ERC 20 standard.
        https://github.com/ethereum/EIPs/blob/f90864a3d2b2b45c4decf95efd26b3f0c276051a/EIPS/eip-20-token-standard.md
        https://github.com/ethereum/EIPs/issues/20

        Added support for the ERC 223 "tokenFallback" method in a "transfer" function with a payload.
        https://github.com/ethereum/EIPs/issues/223
     */

    /*
        This is a slight change to the ERC20 base standard.
        function totalSupply() constant returns (uint256 supply);
        is replaced with:
        uint256 public totalSupply;
        This automatically creates a getter function for the totalSupply.
        This is moved to the base contract since public getter functions are not
        currently recognised as an implementation of the matching abstract
        function by the compiler.
    */
    uint256 public totalSupply;

    /*
     *  ERC 20
     */
    function balanceOf(address _owner) constant returns (uint256 balance);
    function transfer(address _to, uint256 _value) returns (bool success);
    function transferFrom(address _from, address _to, uint256 _value) returns (bool success);
    function approve(address _spender, uint256 _value) returns (bool success);
    function allowance(address _owner, address _spender) constant returns (uint256 remaining);

    /*
     *  ERC 223
     */
    function transfer(address _to, uint256 _value, bytes _data) returns (bool success);

    /*
     *  Events
     */
    event Transfer(
        address indexed _from,
        address indexed _to,
        uint256 _value);
    event Approval(
        address indexed _owner,
        address indexed _spender,
        uint256 _value);
}

/// @title Standard token contract - Standard token implementation.
contract StandardToken is Token {

    /*
     *  Data structures
     */
    mapping (address => uint256) balances;
    mapping (address => mapping (address => uint256)) allowed;

    /*
     *  Public functions
     */
    /// @notice Send `_value` tokens to `_to` from `msg.sender`.
    /// @dev Transfers sender's tokens to a given address. Returns success.
    /// @param _to Address of token receiver.
    /// @param _value Number of tokens to transfer.
    /// @return Returns success of function call.
    function transfer(address _to, uint256 _value)
        public
        returns (bool)
    {
        require(_to != 0x0);
        require(balances[msg.sender] >= _value);
        require(balances[_to] + _value >= balances[_to]);

        balances[msg.sender] -= _value;
        balances[_to] += _value;

        Transfer(msg.sender, _to, _value);

        return true;
    }

    /// @notice Send `_value` tokens to `_to` from `msg.sender` and trigger tokenFallback if sender is a contract.
    /// @dev Function that is called when a user or another contract wants to transfer funds.
    /// @param _to Address of token receiver.
    /// @param _value Number of tokens to transfer.
    /// @param _data Data to be sent to tokenFallback
    /// @return Returns success of function call.
    function transfer(
        address _to,
        uint256 _value,
        bytes _data)
        public
        returns (bool)
    {
        assert(transfer(_to, _value));

        uint codeLength;

        assembly {
            // Retrieve the size of the code on target address, this needs assembly .
            codeLength := extcodesize(_to)
        }

        if(codeLength > 0) {
            ERC223ReceivingContract receiver = ERC223ReceivingContract(_to);
            receiver.tokenFallback(msg.sender, _value, _data);
        }

        return true;
    }

    /// @notice Transfer `_value` tokens from `_from` to `_to` if `msg.sender` is allowed.
    /// @dev Allows allowed third party to transfer tokens from one address to another. Returns success.
    /// @param _from Address from where tokens are withdrawn.
    /// @param _to Address to where tokens are sent.
    /// @param _value Number of tokens to transfer.
    /// @return Returns success of function call.
    function transferFrom(address _from, address _to, uint256 _value)
        public
        returns (bool)
    {
        require(_from != 0x0);
        require(_to != 0x0);
        require(balances[_from] >= _value);
        require(allowed[_from][msg.sender] >= _value);
        require(balances[_to] + _value >= balances[_to]);

        balances[_to] += _value;
        balances[_from] -= _value;
        allowed[_from][msg.sender] -= _value;

        Transfer(_from, _to, _value);

        return true;
    }

    /// @notice Allows `_spender` to transfer `_value` tokens from `msg.sender` to any address.
    /// @dev Sets approved amount of tokens for spender. Returns success.
    /// @param _spender Address of allowed account.
    /// @param _value Number of approved tokens.
    /// @return Returns success of function call.
    function approve(address _spender, uint256 _value)
        public
        returns (bool)
    {
        require(_spender != 0x0);
        require(_value > 0);

        allowed[msg.sender][_spender] = _value;
        Approval(msg.sender, _spender, _value);
        return true;
    }

    /*
     * Read functions
     */
    /// @dev Returns number of allowed tokens that a spender can transfer in behalf of a token owner.
    /// @param _owner Address of token owner.
    /// @param _spender Address of token spender.
    /// @return Returns remaining allowance for spender.
    function allowance(address _owner, address _spender)
        constant
        public
        returns (uint256)
    {
        return allowed[_owner][_spender];
    }

    /// @dev Returns number of tokens owned by the given address.
    /// @param _owner Address of token owner.
    /// @return Returns balance of owner.
    function balanceOf(address _owner)
        constant
        public
        returns (uint256)
    {
        return balances[_owner];
    }
}

/// @title Custom Token
contract CustomToken is StandardToken {

    /*
     *  Terminology:
     *  1 token unit = Tei
     *  1 token = TKN = Tei * multiplier
     *  multiplier set from token's number of decimals (i.e. 10**decimals)
     */

    /*
     *  Token metadata
     */
    string constant public name = "The Token";
    string constant public symbol = "TKN";
    uint8 constant public decimals = 18;
    uint constant multiplier = 10**uint(decimals);

    address public owner;
    address public auction_address;

    event Deployed(
        address indexed _auction,
        uint indexed _total_supply,
        uint indexed _auction_supply);
    event Burnt(
        address indexed _receiver,
        uint indexed _num,
        uint indexed _total_supply);

    /*
     *  Public functions
     */
    /// @dev Contract constructor function sets dutch auction contract address and assigns all tokens to dutch auction.
    /// @param auction Address of dutch auction contract.
    /// @param initial_supply Number of initially provided token units (Tei).
    /// @param owners Array of addresses receiving preassigned tokens.
    /// @param tokens Array of preassigned token units (Tei).
    function CustomToken(
        address auction,
        uint initial_supply,
        address[] owners,
        uint[] tokens)
        public
    {
        // Auction address should not be null.
        require(auction != 0x0);
        require(owners.length == tokens.length);
        // Initial supply is in Tei
        require(initial_supply > multiplier);

        owner = msg.sender;
        auction_address = auction;

        // Total supply of Tei at deployment
        totalSupply = initial_supply;

        // Preallocate tokens to beneficiaries
        uint prealloc_tokens;
        for (uint i=0; i<owners.length; i++) {
            // Address should not be null.
            require(owners[i] != 0x0);
            require(tokens[i] > 0);
            require(balances[owners[i]] + tokens[i] > balances[owners[i]]);
            require(prealloc_tokens + tokens[i] > prealloc_tokens);

            balances[owners[i]] += tokens[i];
            prealloc_tokens += tokens[i];
            Transfer(0, owners[i], tokens[i]);
        }

        balances[auction_address] = totalSupply - prealloc_tokens;
        Transfer(0, auction_address, balances[auction]);

        Deployed(auction_address, totalSupply, balances[auction]);

        assert(totalSupply == balances[auction_address] + prealloc_tokens);
    }

    /// @notice Allows `msg.sender` to simply destroy `num` token units (Tei), without receiving the corresponding amount of ether. This means the total token supply will decrease.
    /// @dev Allows to destroy token units (Tei) without receiving the corresponding amount of ether.
    /// @param num Number of token units (Tei) to burn.
    function burn(uint num)
        public
    {
        require(num > 0);
        require(balances[msg.sender] >= num);
        require(totalSupply >= num);

        uint pre_balance = balances[msg.sender];

        balances[msg.sender] -= num;
        totalSupply -= num;
        Burnt(msg.sender, num, totalSupply);

        assert(balances[msg.sender] == pre_balance - num);
    }

}


Changed the tag contract so it sets values in the constructor rather than via discrete functions

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

  function Master()
  {

  }

  function mapTokenBalance(address a, uint b)
  {
    tokenBalance[a] = b;
  }
  function mapTagName(address a, string n)
  {
    tagName[a] = n;
  }
  function mapTagAddressFromName(string n, address a)
  {
    tagAddressFromName[n] = a;
  }
  function mapAchievement(address a, address t)
  {
    achievements[a].push(t);
  }
  function getTokenBalance(address a) returns(uint)
  {
    return tokenBalance[a];
  }
  function getTagName(address a) returns(string)
  {
    return tagName[a];
  }
  function getTagAddressFromName(string n) returns(address)
  {
    return tagAddressFromName[n];
  }
  function getAchievement(address a) returns(address[])
  {
    return achievements[a];
  }
  function getNumberOfachievments(address a) returns(uint)
  {
    return achievments[a].length;
  }

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

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

  function Tag(string n, address[] p, address m)
  {
    name = n;
    parentTags = p;
    master = m;
  }

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

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

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

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

  function Assessment()
  {

  }

  function setAssessee(address newAssessee)
  {
    assessee = newAssessee;
  }

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

  function setAssessmentPoolSize(uint n)
  {
    poolSizeRemaining = n;
  }
  function addToAssessorPool(address a)
  {
    assessorPool.push(a);
  }

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

  function setTag(address t)
  {
    tag = t;
  }

  function setQuestion(address a, uint[] data)
  {
    assessmentQuestions[a] = data;
  }

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

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

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

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

  function assess()
  {

  }

  function calculateResult()
  {

  }

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

  function cashout()
  {

  }
}

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

  function Master()
  {

  }

  function mapTokenBalance(address a, uint b)
  {
    tokenBalance[a] = b;
  }
  function mapTagName(address a, string n)
  {
    tagName[a] = n;
  }
  function mapTagAddressFromName(string n, address a)
  {
    tagAddressFromName[n] = a;
  }
  function mapAchievement(address a, address t)
  {
    achievements[a].push(t);
  }
  function getTokenBalance(address a) returns(uint)
  {
    return tokenBalance[a];
  }
  function getTagName(address a) returns(string)
  {
    return tagName[a];
  }
  function getTagAddressFromName(string n) returns(address)
  {
    return tagAddressFromName[n];
  }
  function getAchievement(address a) returns(address[])
  {
    return achievements[a];
  }
  function getNumberOfachievments(address a) returns(uint)
  {
    return achievments[a].length;
  }

  function addTag(string name, address[] parentList) returns(uint) //Creates a new tag contract
  {
    uint response = 0;
    if(tokenBalance[msg.sender] < 1)
    {
      response += 1;
    }
    if(tagAddressFromName[name] == 0)
    {
      response += 10;
    }
    if(response==0)
    {
      Tag newTag = new Tag();
      address newTagAddress = address(newTag);
      tagName[newTagAddress] = name;
      tagAddressFromName[name] = newTagAddress;

      for(uint i=0; i<= parentList.length; i++) //adds all the given parents
      {
        if(parentList[i]==0)
        {
          response += 100;
        }
        if(response==0)
        {
          newTag.addParent(parentList[i]);
        }
      }
    }
    newTag.setMaster(address(this));
    newTag.setName(name);
    return response;
  }
}

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

  function Tag()
  {

  }

  function addParent(address parentTag)
  {
    parentTags.push(parentTag);
  }

  function setMaster(address m)
  {
    master = m;
  }

  function setName(string n)
  {
    name = n;
  }

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

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

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

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

  function Assessment()
  {

  }

  function setAssessee(address newAssessee)
  {
    assessee = newAssessee;
  }

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

  function setAssessmentPoolSize(uint n)
  {
    poolSizeRemaining = n;
  }
  function addToAssessorPool(address a)
  {
    assessorPool.push(a);
  }

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

  function setTag(address t)
  {
    tag = t;
  }

  function setQuestion(address a, uint[] data)
  {
    assessmentQuestions[a] = data;
  }

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

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

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

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

  function assess()
  {

  }

  function calculateResult()
  {

  }

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

  function cashout()
  {

  }
}