Figured out how to get implementations from addresses and removed the now uneasily code we were using to do this before.

contract Master
{
  function Master()
  {

  }
  //Initialize master data store
  mapping (address => uint) tokenBalance;
  mapping (address => string) tagName;
  mapping (string => address) tagAddressFromName;
  mapping (address => address[]) acheivements;

  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 mapAcheivement(address a, address t)
  {
    acheivements[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 getAcheivement(address a) returns(address[])
  {
    return acheivements[a];
  }
  function getNumberOfAcheivements(address a) returns(uint)
  {
    return acheivements[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 getAssessors(uint randomNumber)
  {

  }
  function startAssessment(address assessee, address[] assessors)
  {
    Assessment newAssessment;
    newAssessment.setAssessee(assessee);
    newAssessment.setAssessors(assessors);
    newAssessment.setTag(address(this));
  }
  function getAssessmentResults(bool result, uint score, address assessee, address assessment) returns(bool)
  {
    if(result == true)
    {
      owners.push(assessee);
      scores[assessee] = score;
      Master(master).mapAcheivement(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[] assessors;
  address tag;
  mapping(address => uint[]) assessmentData; //Given by the assessors as IPFS hashes
  mapping(address => uint[]) assessmentAnswers; //Given by the assessee as IPFS hashes
  mapping(address => bool[]) assessmentResults; //Pass/Fail given by assessors
  mapping(address => uint[]) assessmentScores; //Numerical score given by assessors

  function Assessment()
  {

  }
  function setAssessee(address newAssessee)
  {
    assessee = newAssessee;
  }
  function setAssessors(address[] newAssessors)
  {
    assessors = newAssessors;
  }
  function setTag(address t)
  {
    tag = t;
  }
  function assess()
  {

  }
  function cashout()
  {

  }
}

contract Master
{
  function Master()
  {

  }
  //Initialize master data store
  mapping(address => uint) tokenBalance;
  mapping(address => string) tagName;
  mapping(string => address) tagAddressFromName;
  mapping(address => Tag) tagImplementation;
  //mapping(Tag => address) tagAddressFromImplementation;
  mapping(address => string[]) acheivements;

  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 mapTagImplementation(address a, Tag t)
  {
    tagImplementation[a] = t;
  }
  function mapAcheivement(address a, string n)
  {
    acheivements[a].push(n);
  }
  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 getTagImplementation(address a) returns(Tag)
  {
    return tagImplementation[a];
  }
  function getAcheivement(address a, uint i) returns(string)
  {
    return acheivements[a][i];
  }
  function getNumberOfAcheivements(address a) returns(uint)
  {
    return acheivements[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;
      address newTagAddress = address(newTag);
      tagName[newTagAddress] = name;
      tagAddressFromName[name] = newTagAddress;
      tagImplementation[newTagAddress] = newTag;
      //tagAddressFromImplementation[newTag] = 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(tagImplementation[parentList[i]]);
        }
      }
    }
    newTag.setMaster(this);
    newTag.setName(name);
    return response;
  }
}

//Defines the meta-contract for a Tag
contract Tag
{
  Tag[] parentTags;
  Master 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(Tag parentTag)
  {
    parentTags.push(parentTag);
  }
  function setMaster(Master m)
  {
    master = m;
  }
  function setName(string n)
  {
    name = n;
  }
  function getAssessors(uint randomNumber)
  {

  }
  function startAssessment(address assessee, address[] assessors)
  {
    Assessment newAssessment;
    newAssessment.setAssessee(assessee);
    newAssessment.setAssessors(assessors);
    newAssessment.setTag(this);
  }
  function getAssessmentResults(bool result, uint score, address assessee, address assessment) returns(bool)
  {
    if(result == true)
    {
      owners.push(assessee);
      scores[assessee] = score;
      master.mapAcheivement(assessee,name);
    }
    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[] assessors;
  Tag tag;
  mapping(address => uint[]) assessmentData; //Given by the assessors as IPFS hashes
  mapping(address => uint[]) assessmentAnswers; //Given by the assessee as IPFS hashes
  mapping(address => bool[]) assessmentResults; //Pass/Fail given by assessors
  mapping(address => uint[]) assessmentScores; //Numerical score given by assessors

  function Assessment()
  {

  }
  function setAssessee(address newAssessee)
  {
    assessee = newAssessee;
  }
  function setAssessors(address[] newAssessors)
  {
    assessors = newAssessors;
  }
  function setTag(Tag t)
  {
    tag = t;
  }
  function assess()
  {

  }
  function cashout()
  {

  }
}


Create Crowdsale on ChainX

Create Crowdsale on ChainX

pragma solidity ^0.4.8;

import "./SafeMathLib.sol";
import "./Haltable.sol";
import "./PricingStrategy.sol";
import "./FinalizeAgent.sol";
import "./FractionalERC20.sol";

/**
 * Abstract base contract for token sales.
 *
 * Handle
 * - start and end dates
 * - accepting investments
 * - minimum funding goal and refund
 * - various statistics during the crowdfund
 * - different pricing strategies
 * - different investment policies (require server side customer id, allow only whitelisted addresses)
 *
 */
contract Crowdsale is Haltable {

  /* Max investment count when we are still allowed to change the multisig address */
  uint public MAX_INVESTMENTS_BEFORE_MULTISIG_CHANGE = 5;

  using SafeMathLib for uint;

  /* The token we are selling */
  FractionalERC20 public token;

  /* How we are going to price our offering */
  PricingStrategy public pricingStrategy;

  /* Post-success callback */
  FinalizeAgent public finalizeAgent;

  /* tokens will be transfered from this address */
  address public multisigWallet;

  /* if the funding goal is not reached, investors may withdraw their funds */
  uint public minimumFundingGoal;

  /* the UNIX timestamp start date of the crowdsale */
  uint public startsAt;

  /* the UNIX timestamp end date of the crowdsale */
  uint public endsAt;

  /* the number of tokens already sold through this contract*/
  uint public tokensSold = 0;

  /* How many wei of funding we have raised */
  uint public weiRaised = 0;

  /* How many distinct addresses have invested */
  uint public investorCount = 0;

  /* How much wei we have returned back to the contract after a failed crowdfund. */
  uint public loadedRefund = 0;

  /* How much wei we have given back to investors.*/
  uint public weiRefunded = 0;

  /* Has this crowdsale been finalized */
  bool public finalized;

  /* Do we need to have unique contributor id for each customer */
  bool public requireCustomerId;

  /**
    * Do we verify that contributor has been cleared on the server side (accredited investors only).
    * This method was first used in FirstBlood crowdsale to ensure all contributors have accepted terms on sale (on the web).
    */
  bool public requiredSignedAddress;

  /* Server side address that signed allowed contributors (chainx addresses) that can participate the crowdsale */
  address public signerAddress;

  /** How much Chainx each address has invested to this crowdsale */
  mapping (address => uint256) public investedAmountOf;

  /** How much tokens this crowdsale has credited for each investor address */
  mapping (address => uint256) public tokenAmountOf;

  /** Addresses that are allowed to invest even before ICO offical opens. For testing, for ICO partners, etc. */
  mapping (address => bool) public earlyParticipantWhitelist;

  /** This is for manul testing for the interaction from owner wallet. You can set it to any value and inspect this in blockchain explorer to see that crowdsale interaction works. */
  uint public ownerTestValue;

  /** State machine
   *
   * - Preparing: All contract initialization calls and variables have not been set yet
   * - Prefunding: We have not passed start time yet
   * - Funding: Active crowdsale
   * - Success: Minimum funding goal reached
   * - Failure: Minimum funding goal not reached before ending time
   * - Finalized: The finalized has been called and succesfully executed
   * - Refunding: Refunds are loaded on the contract for reclaim.
   */
  enum State{Unknown, Preparing, PreFunding, Funding, Success, Failure, Finalized, Refunding}

  // A new investment was made
  event Invested(address investor, uint weiAmount, uint tokenAmount, uint128 customerId);

  // Refund was processed for a contributor
  event Refund(address investor, uint weiAmount);

  // The rules were changed what kind of investments we accept
  event InvestmentPolicyChanged(bool requireCustomerId, bool requiredSignedAddress, address signerAddress);

  // Address early participation whitelist status changed
  event Whitelisted(address addr, bool status);

  // Crowdsale end time has been changed
  event EndsAtChanged(uint endsAt);

  function Crowdsale(address _token, PricingStrategy _pricingStrategy, address _multisigWallet, uint _start, uint _end, uint _minimumFundingGoal) {

    owner = msg.sender;

    token = FractionalERC20(_token);

    setPricingStrategy(_pricingStrategy);

    multisigWallet = _multisigWallet;
    if(multisigWallet == 0) {
        throw;
    }

    if(_start == 0) {
        throw;
    }

    startsAt = _start;

    if(_end == 0) {
        throw;
    }

    endsAt = _end;

    // Don't mess the dates
    if(startsAt >= endsAt) {
        throw;
    }

    // Minimum funding goal can be zero
    minimumFundingGoal = _minimumFundingGoal;
  }

  /**
   * Don't expect to just send in money and get tokens.
   */
  function() payable {
    throw;
  }

  /**
   * Make an investment.
   *
   * Crowdsale must be running for one to invest.
   * We must have not pressed the emergency brake.
   *
   * @param receiver The ChainX address who receives the tokens
   * @param customerId (optional) UUID v4 to track the successful payments on the server side
   *
   */
  function investInternal(address receiver, uint128 customerId) stopInEmergency private {

    // Determine if it's a good time to accept investment from this participant
    if(getState() == State.PreFunding) {
      // Are we whitelisted for early deposit
      if(!earlyParticipantWhitelist[receiver]) {
        throw;
      }
    } else if(getState() == State.Funding) {
      // Retail participants can only come in when the crowdsale is running
      // pass
    } else {
      // Unwanted state
      throw;
    }

    uint weiAmount = msg.value;
    uint tokenAmount = pricingStrategy.calculatePrice(weiAmount, weiRaised, tokensSold, msg.sender, token.decimals());

    if(tokenAmount == 0) {
      // Dust transaction
      throw;
    }

    if(investedAmountOf[receiver] == 0) {
       // A new investor
       investorCount++;
    }

    // Update investor
    investedAmountOf[receiver] = investedAmountOf[receiver].plus(weiAmount);
    tokenAmountOf[receiver] = tokenAmountOf[receiver].plus(tokenAmount);

    // Update totals
    weiRaised = weiRaised.plus(weiAmount);
    tokensSold = tokensSold.plus(tokenAmount);

    // Check that we did not bust the cap
    if(isBreakingCap(weiAmount, tokenAmount, weiRaised, tokensSold)) {
      throw;
    }

    assignTokens(receiver, tokenAmount);

    // Pocket the money
    if(!multisigWallet.send(weiAmount)) throw;

    // Tell us invest was success
    Invested(receiver, weiAmount, tokenAmount, customerId);
  }

  /**
   * Preallocate tokens for the early investors.
   *
   * Preallocated tokens have been sold before the actual crowdsale opens.
   * This function mints the tokens and moves the crowdsale needle.
   *
   * Investor count is not handled; it is assumed this goes for multiple investors
   * and the token distribution happens outside the smart contract flow.
   *
   * No money is exchanged, as the crowdsale team already have received the payment.
   *
   * @param fullTokens tokens as full tokens - decimal places added internally
   * @param weiPrice Price of a single full token in wei
   *
   */
  function preallocate(address receiver, uint fullTokens, uint weiPrice) public onlyOwner {

    uint tokenAmount = fullTokens * 10**token.decimals();
    uint weiAmount = weiPrice * fullTokens; // This can be also 0, we give out tokens for free

    weiRaised = weiRaised.plus(weiAmount);
    tokensSold = tokensSold.plus(tokenAmount);

    investedAmountOf[receiver] = investedAmountOf[receiver].plus(weiAmount);
    tokenAmountOf[receiver] = tokenAmountOf[receiver].plus(tokenAmount);

    assignTokens(receiver, tokenAmount);

    // Tell us invest was success
    Invested(receiver, weiAmount, tokenAmount, 0);
  }

  /**
   * Allow anonymous contributions to this crowdsale.
   */
  function investWithSignedAddress(address addr, uint128 customerId, uint8 v, bytes32 r, bytes32 s) public payable {
     bytes32 hash = sha256(addr);
     if (ecrecover(hash, v, r, s) != signerAddress) throw;
     if(customerId == 0) throw;  // UUIDv4 sanity check
     investInternal(addr, customerId);
  }

  /**
   * Track who is the customer making the payment so we can send thank you email.
   */
  function investWithCustomerId(address addr, uint128 customerId) public payable {
    if(requiredSignedAddress) throw; // Crowdsale allows only server-side signed participants
    if(customerId == 0) throw;  // UUIDv4 sanity check
    investInternal(addr, customerId);
  }

  /**
   * Allow anonymous contributions to this crowdsale.
   */
  function invest(address addr) public payable {
    if(requireCustomerId) throw; // Crowdsale needs to track partipants for thank you email
    if(requiredSignedAddress) throw; // Crowdsale allows only server-side signed participants
    investInternal(addr, 0);
  }

  /**
   * Invest to tokens, recognize the payer and clear his address.
   *
   */
  function buyWithSignedAddress(uint128 customerId, uint8 v, bytes32 r, bytes32 s) public payable {
    investWithSignedAddress(msg.sender, customerId, v, r, s);
  }

  /**
   * Invest to tokens, recognize the payer.
   *
   */
  function buyWithCustomerId(uint128 customerId) public payable {
    investWithCustomerId(msg.sender, customerId);
}

error: pathspec 'Contracts/ICO/Crowdsale.sol' did not match any file(s) known to git


Document functions lnUpperBound and floorLog2

pragma solidity ^0.4.11;
import './SafeMath.sol';
import './interfaces/IBancorFormula.sol';

/*
    Open issues:
    - The formula is not yet super accurate, especially for very small/very high ratios
    - Improve dynamic precision support
*/

contract BancorFormula is IBancorFormula, SafeMath {

    uint256 constant MAX_FIXED_EXP_32 = 0x386bfdba29;
    string public version = '0.2';

    function BancorFormula() {
    }

    /**
        @dev given a token supply, reserve, CRR and a deposit amount (in the reserve token), calculates the return for a given change (in the main token)

        Formula:
        Return = _supply * ((1 + _depositAmount / _reserveBalance) ^ (_reserveRatio / 100) - 1)

        @param _supply             token total supply
        @param _reserveBalance     total reserve
        @param _reserveRatio       constant reserve ratio, 1-100
        @param _depositAmount      deposit amount, in reserve token

        @return purchase return amount
    */
    function calculatePurchaseReturn(uint256 _supply, uint256 _reserveBalance, uint16 _reserveRatio, uint256 _depositAmount) public constant returns (uint256) {
        // validate input
        require(_supply != 0 && _reserveBalance != 0 && _reserveRatio > 0 && _reserveRatio <= 100);

        // special case for 0 deposit amount
        if (_depositAmount == 0)
            return 0;

        uint256 baseN = safeAdd(_depositAmount, _reserveBalance);
        uint256 temp;

        // special case if the CRR = 100
        if (_reserveRatio == 100) {
            temp = safeMul(_supply, baseN) / _reserveBalance;
            return safeSub(temp, _supply);
        }

        uint8 precision = getBestPrecision(baseN, _reserveBalance, _reserveRatio, 100);
        uint256 resN = power(baseN, _reserveBalance, _reserveRatio, 100, precision);

        temp = safeMul(_supply, resN) >> precision;

        return safeSub(temp, _supply);
     }

    /**
        @dev given a token supply, reserve, CRR and a sell amount (in the main token), calculates the return for a given change (in the reserve token)

        Formula:
        Return = _reserveBalance * (1 - (1 - _sellAmount / _supply) ^ (1 / (_reserveRatio / 100)))

        @param _supply             token total supply
        @param _reserveBalance     total reserve
        @param _reserveRatio       constant reserve ratio, 1-100
        @param _sellAmount         sell amount, in the token itself

        @return sale return amount
    */
    function calculateSaleReturn(uint256 _supply, uint256 _reserveBalance, uint16 _reserveRatio, uint256 _sellAmount) public constant returns (uint256) {
        // validate input
        require(_supply != 0 && _reserveBalance != 0 && _reserveRatio > 0 && _reserveRatio <= 100 && _sellAmount <= _supply);

        // special case for 0 sell amount
        if (_sellAmount == 0)
            return 0;

        uint256 baseD = safeSub(_supply, _sellAmount);
        uint256 temp1;
        uint256 temp2;

        // special case if the CRR = 100
        if (_reserveRatio == 100) {
            temp1 = safeMul(_reserveBalance, _supply);
            temp2 = safeMul(_reserveBalance, baseD);
            return safeSub(temp1, temp2) / _supply;
        }

        // special case for selling the entire supply
        if (_sellAmount == _supply)
            return _reserveBalance;

        uint8 precision = getBestPrecision(_supply, baseD, 100, _reserveRatio);
        uint256 resN = power(_supply, baseD, 100, _reserveRatio, precision);

        temp1 = safeMul(_reserveBalance, resN);
        temp2 = safeMul(_reserveBalance, uint256(1) << precision);

        return safeSub(temp1, temp2) / resN;
    }

    /**
        @dev Calculate (_baseN / _baseD) ^ (_expN / _expD)
        Returns result upshifted by precision

        This method is overflow-safe
    */
    function power(uint256 _baseN, uint256 _baseD, uint32 _expN, uint32 _expD, uint8 _precision) constant returns (uint256 resN) {
        uint256 logbase = ln(_baseN, _baseD, _precision);
        // Not using safeDiv here, since safeDiv protects against
        // precision loss. It's unavoidable, however
        // Both `ln` and `fixedExp` are overflow-safe.
        resN = fixedExp(safeMul(logbase, _expN) / _expD, _precision);
        return resN;
    }

    /**
        input range:
            - numerator: [1, uint256_max >> precision]
            - denominator: [1, uint256_max >> precision]
        output range:
            [0, 0x9b43d4f8d6]

        This method asserts outside of bounds

    */
    function ln(uint256 _numerator, uint256 _denominator, uint8 _precision) public constant returns (uint256) {
        // denominator > numerator: less than one yields negative values. Unsupported
        assert(_denominator <= _numerator);

        // log(1) is the lowest we can go
        assert(_denominator != 0 && _numerator != 0);

        // Upper bits are scaled off by precision
        uint256 MAX_VAL = uint256(1) << (256 - _precision);
        assert(_numerator < MAX_VAL);
        assert(_denominator < MAX_VAL);

        return fixedLoge( (_numerator << _precision) / _denominator, _precision);
    }

    /**
        input range:
            [0x100000000,uint256_max]
        output range:
            [0, 0x9b43d4f8d6]

        This method asserts outside of bounds

    */
    function fixedLoge(uint256 _x, uint8 _precision) constant returns (uint256 logE) {
        /*
        Since `fixedLog2_min` output range is max `0xdfffffffff`
        (40 bits, or 5 bytes), we can use a very large approximation
        for `ln(2)`. This one is used since it's the max accuracy
        of Python `ln(2)`

        0xb17217f7d1cf78 = ln(2) * (1 << 56)

        */
        //Cannot represent negative numbers (below 1)
        assert(_x >= uint256(1) << _precision);

        uint256 log2 = fixedLog2(_x, _precision);
        logE = (log2 * 0xb17217f7d1cf78) >> 56;
    }

    /**
        Returns log2(x >> 32) << 32 [1]
        So x is assumed to be already upshifted 32 bits, and
        the result is also upshifted 32 bits.

        [1] The function returns a number which is lower than the
        actual value

        input-range :
            [0x100000000,uint256_max]
        output-range:
            [0,0xdfffffffff]

        This method asserts outside of bounds

    */
    function fixedLog2(uint256 _x, uint8 _precision) constant returns (uint256) {
        uint256 FIXED_ONE = uint256(1) << _precision;
        uint256 FIXED_TWO = uint256(2) << _precision;

        // Numbers below 1 are negative.
        assert( _x >= FIXED_ONE);

        uint256 hi = 0;
        while (_x >= FIXED_TWO) {
            _x >>= 1;
            hi += FIXED_ONE;
        }

        for (uint8 i = 0; i < _precision; ++i) {
            _x = (_x * _x) / FIXED_ONE;
            if (_x >= FIXED_TWO) {
                _x >>= 1;
                hi += uint256(1) << (_precision - 1 - i);
            }
        }

        return hi;
    }

    /**
        fixedExp is a 'protected' version of `fixedExpUnsafe`, which
        asserts instead of overflows
    */
    function fixedExp(uint256 _x, uint8 _precision) constant returns (uint256) {
        uint256 maxExp = MAX_FIXED_EXP_32;
        for (uint8 p = 32; p < _precision; p += 2)
            maxExp = maxExp * 367765941410054209 / 100000000000000000;

        assert(_x <= maxExp);
        return fixedExpUnsafe(_x, _precision);
    }

    /**
        fixedExp
        Calculates e^x according to maclauren summation:

        e^x = 1+x+x^2/2!...+x^n/n!

        and returns e^(x>>32) << 32, that is, upshifted for accuracy

        Input range:
            - Function ok at    <= 242329958953
            - Function fails at >= 242329958954

        This method is is visible for testcases, but not meant for direct use.

        The values in this method been generated via the following python snippet:

        def calculateFactorials():
            """Method to print out the factorials for fixedExp"""

            ni = []
            ni.append( 295232799039604140847618609643520000000) # 34!
            ITERATIONS = 34
            for n in range( 1,  ITERATIONS,1 ) :
                ni.append(math.floor(ni[n - 1] / n))
            print( "\n        ".join(["xi = (xi * _x) >> _precision;\n        res += xi * %s;" % hex(int(x)) for x in ni]))

    */
    function fixedExpUnsafe(uint256 _x, uint8 _precision) constant returns (uint256) {
        uint256 xi = _x;
        uint256 res = uint256(0xde1bc4d19efcac82445da75b00000000) << _precision;

        res += xi * 0xde1bc4d19efcac82445da75b00000000;
        xi = (xi * _x) >> _precision;
        res += xi * 0x6f0de268cf7e5641222ed3ad80000000;
        xi = (xi * _x) >> _precision;
        res += xi * 0x2504a0cd9a7f7215b60f9be480000000;
        xi = (xi * _x) >> _precision;
        res += xi * 0x9412833669fdc856d83e6f920000000;
        xi = (xi * _x) >> _precision;
        res += xi * 0x1d9d4d714865f4de2b3fafea0000000;
        xi = (xi * _x) >> _precision;
        res += xi * 0x4ef8ce836bba8cfb1dff2a70000000;
        xi = (xi * _x) >> _precision;
        res += xi * 0xb481d807d1aa66d04490610000000;
        xi = (xi * _x) >> _precision;
        res += xi * 0x16903b00fa354cda08920c2000000;
        xi = (xi * _x) >> _precision;
        res += xi * 0x281cdaac677b334ab9e732000000;
        xi = (xi * _x) >> _precision;
        res += xi * 0x402e2aad725eb8778fd85000000;
        xi = (xi * _x) >> _precision;
        res += xi * 0x5d5a6c9f31fe2396a2af000000;
        xi = (xi * _x) >> _precision;
        res += xi * 0x7c7890d442a82f73839400000;
        xi = (xi * _x) >> _precision;
        res += xi * 0x9931ed54034526b58e400000;
        xi = (xi * _x) >> _precision;
        res += xi * 0xaf147cf24ce150cf7e00000;
        xi = (xi * _x) >> _precision;
        res += xi * 0xbac08546b867cdaa200000;
        xi = (xi * _x) >> _precision;
        res += xi * 0xbac08546b867cdaa20000;
        xi = (xi * _x) >> _precision;
        res += xi * 0xafc441338061b2820000;
        xi = (xi * _x) >> _precision;
        res += xi * 0x9c3cabbc0056d790000;
        xi = (xi * _x) >> _precision;
        res += xi * 0x839168328705c30000;
        xi = (xi * _x) >> _precision;
        res += xi * 0x694120286c049c000;
        xi = (xi * _x) >> _precision;
        res += xi * 0x50319e98b3d2c000;
        xi = (xi * _x) >> _precision;
        res += xi * 0x3a52a1e36b82000;
        xi = (xi * _x) >> _precision;
        res += xi * 0x289286e0fce000;
        xi = (xi * _x) >> _precision;
        res += xi * 0x1b0c59eb53400;
        xi = (xi * _x) >> _precision;
        res += xi * 0x114f95b55400;
        xi = (xi * _x) >> _precision;
        res += xi * 0xaa7210d200;
        xi = (xi * _x) >> _precision;
        res += xi * 0x650139600;
        xi = (xi * _x) >> _precision;
        res += xi * 0x39b78e80;
        xi = (xi * _x) >> _precision;
        res += xi * 0x1fd8080;
        xi = (xi * _x) >> _precision;
        res += xi * 0x10fbc0;
        xi = (xi * _x) >> _precision;
        res += xi * 0x8c40;
        xi = (xi * _x) >> _precision;
        res += xi * 0x462;
        xi = (xi * _x) >> _precision;
        res += xi * 0x22;

        return res / 0xde1bc4d19efcac82445da75b00000000;
    }

    function getBestPrecision(uint256 _baseN, uint256 _baseD, uint256 _expN, uint256 _expD) constant returns (uint8) {
        uint8 precision = floorLog2(MAX_FIXED_EXP_32 * _expD / (lnUpperBound(_baseN,_baseD) * _expN));
        if (precision <= 32)
            return 32;
        if (precision >= 48)
            return 64;
        return precision * 2 - 32;
    }

    /**
        lnUpperBound
        Takes a rational number (baseN/baseD) as input.
        Returns an estimated upper-bound integer of the natural logarithm of the input.
        We can generally use floorLog2, although there is possibly a tighter bound.
        We cannot use floorLog2 when the input is smaller than 8.
        Complexity is O(log(input)).
    */
    function lnUpperBound(uint256 baseN, uint256 baseD) constant returns (uint8) {
        assert(baseN > baseD);

        uint256 scaledBaseN = baseN * 100000;
        if (scaledBaseN <= baseD *  271828) // baseN / baseD < e^1 (floorLog2 will return 0 if baseN/baseD < 2)
            return 1;
        if (scaledBaseN <= baseD *  738905) // baseN / baseD < e^2 (floorLog2 will return 1 if baseN/baseD < 4)
            return 2;
        if (scaledBaseN <= baseD * 2008553) // baseN / baseD < e^3 (floorLog2 will return 2 if baseN/baseD < 8)
            return 3;

        return floorLog2(baseN/baseD);
    }

    /**
        floorLog2
        Takes a natural number (n) as input.
        Returns the largest integer smaller than or equal to the binary logarithm of the input.
        Complexity is O(log(input)).
    */
    function floorLog2(uint256 n) constant returns (uint8) {
        uint256 t = 0;
        for (int k = 7; k >= 0; k--) {
            if (n > (uint256(1) << (1 << k)) - 1) {
                uint256 s = uint256(1) << k;
                n >>= s;
                t |= s;
            }
        }

        return uint8(t | (n >> 1));
    }
}

pragma solidity ^0.4.11;
import './SafeMath.sol';
import './interfaces/IBancorFormula.sol';

/*
    Open issues:
    - The formula is not yet super accurate, especially for very small/very high ratios
    - Improve dynamic precision support
*/

contract BancorFormula is IBancorFormula, SafeMath {

    uint256 constant MAX_FIXED_EXP_32 = 0x386bfdba29;
    string public version = '0.2';

    function BancorFormula() {
    }

    /**
        @dev given a token supply, reserve, CRR and a deposit amount (in the reserve token), calculates the return for a given change (in the main token)

        Formula:
        Return = _supply * ((1 + _depositAmount / _reserveBalance) ^ (_reserveRatio / 100) - 1)

        @param _supply             token total supply
        @param _reserveBalance     total reserve
        @param _reserveRatio       constant reserve ratio, 1-100
        @param _depositAmount      deposit amount, in reserve token

        @return purchase return amount
    */
    function calculatePurchaseReturn(uint256 _supply, uint256 _reserveBalance, uint16 _reserveRatio, uint256 _depositAmount) public constant returns (uint256) {
        // validate input
        require(_supply != 0 && _reserveBalance != 0 && _reserveRatio > 0 && _reserveRatio <= 100);

        // special case for 0 deposit amount
        if (_depositAmount == 0)
            return 0;

        uint256 baseN = safeAdd(_depositAmount, _reserveBalance);
        uint256 temp;

        // special case if the CRR = 100
        if (_reserveRatio == 100) {
            temp = safeMul(_supply, baseN) / _reserveBalance;
            return safeSub(temp, _supply);
        }

        uint8 precision = getBestPrecision(baseN, _reserveBalance, _reserveRatio, 100);
        uint256 resN = power(baseN, _reserveBalance, _reserveRatio, 100, precision);

        temp = safeMul(_supply, resN) >> precision;

        return safeSub(temp, _supply);
     }

    /**
        @dev given a token supply, reserve, CRR and a sell amount (in the main token), calculates the return for a given change (in the reserve token)

        Formula:
        Return = _reserveBalance * (1 - (1 - _sellAmount / _supply) ^ (1 / (_reserveRatio / 100)))

        @param _supply             token total supply
        @param _reserveBalance     total reserve
        @param _reserveRatio       constant reserve ratio, 1-100
        @param _sellAmount         sell amount, in the token itself

        @return sale return amount
    */
    function calculateSaleReturn(uint256 _supply, uint256 _reserveBalance, uint16 _reserveRatio, uint256 _sellAmount) public constant returns (uint256) {
        // validate input
        require(_supply != 0 && _reserveBalance != 0 && _reserveRatio > 0 && _reserveRatio <= 100 && _sellAmount <= _supply);

        // special case for 0 sell amount
        if (_sellAmount == 0)
            return 0;

        uint256 baseD = safeSub(_supply, _sellAmount);
        uint256 temp1;
        uint256 temp2;

        // special case if the CRR = 100
        if (_reserveRatio == 100) {
            temp1 = safeMul(_reserveBalance, _supply);
            temp2 = safeMul(_reserveBalance, baseD);
            return safeSub(temp1, temp2) / _supply;
        }

        // special case for selling the entire supply
        if (_sellAmount == _supply)
            return _reserveBalance;

        uint8 precision = getBestPrecision(_supply, baseD, 100, _reserveRatio);
        uint256 resN = power(_supply, baseD, 100, _reserveRatio, precision);

        temp1 = safeMul(_reserveBalance, resN);
        temp2 = safeMul(_reserveBalance, uint256(1) << precision);

        return safeSub(temp1, temp2) / resN;
    }

    /**
        @dev Calculate (_baseN / _baseD) ^ (_expN / _expD)
        Returns result upshifted by precision

        This method is overflow-safe
    */
    function power(uint256 _baseN, uint256 _baseD, uint32 _expN, uint32 _expD, uint8 _precision) constant returns (uint256 resN) {
        uint256 logbase = ln(_baseN, _baseD, _precision);
        // Not using safeDiv here, since safeDiv protects against
        // precision loss. It's unavoidable, however
        // Both `ln` and `fixedExp` are overflow-safe.
        resN = fixedExp(safeMul(logbase, _expN) / _expD, _precision);
        return resN;
    }

    /**
        input range:
            - numerator: [1, uint256_max >> precision]
            - denominator: [1, uint256_max >> precision]
        output range:
            [0, 0x9b43d4f8d6]

        This method asserts outside of bounds

    */
    function ln(uint256 _numerator, uint256 _denominator, uint8 _precision) public constant returns (uint256) {
        // denominator > numerator: less than one yields negative values. Unsupported
        assert(_denominator <= _numerator);

        // log(1) is the lowest we can go
        assert(_denominator != 0 && _numerator != 0);

        // Upper bits are scaled off by precision
        uint256 MAX_VAL = uint256(1) << (256 - _precision);
        assert(_numerator < MAX_VAL);
        assert(_denominator < MAX_VAL);

        return fixedLoge( (_numerator << _precision) / _denominator, _precision);
    }

    /**
        input range:
            [0x100000000,uint256_max]
        output range:
            [0, 0x9b43d4f8d6]

        This method asserts outside of bounds

    */
    function fixedLoge(uint256 _x, uint8 _precision) constant returns (uint256 logE) {
        /*
        Since `fixedLog2_min` output range is max `0xdfffffffff`
        (40 bits, or 5 bytes), we can use a very large approximation
        for `ln(2)`. This one is used since it's the max accuracy
        of Python `ln(2)`

        0xb17217f7d1cf78 = ln(2) * (1 << 56)

        */
        //Cannot represent negative numbers (below 1)
        assert(_x >= uint256(1) << _precision);

        uint256 log2 = fixedLog2(_x, _precision);
        logE = (log2 * 0xb17217f7d1cf78) >> 56;
    }

    /**
        Returns log2(x >> 32) << 32 [1]
        So x is assumed to be already upshifted 32 bits, and
        the result is also upshifted 32 bits.

        [1] The function returns a number which is lower than the
        actual value

        input-range :
            [0x100000000,uint256_max]
        output-range:
            [0,0xdfffffffff]

        This method asserts outside of bounds

    */
    function fixedLog2(uint256 _x, uint8 _precision) constant returns (uint256) {
        uint256 FIXED_ONE = uint256(1) << _precision;
        uint256 FIXED_TWO = uint256(2) << _precision;

        // Numbers below 1 are negative.
        assert( _x >= FIXED_ONE);

        uint256 hi = 0;
        while (_x >= FIXED_TWO) {
            _x >>= 1;
            hi += FIXED_ONE;
        }

        for (uint8 i = 0; i < _precision; ++i) {
            _x = (_x * _x) / FIXED_ONE;
            if (_x >= FIXED_TWO) {
                _x >>= 1;
                hi += uint256(1) << (_precision - 1 - i);
            }
        }

        return hi;
    }

    /**
        fixedExp is a 'protected' version of `fixedExpUnsafe`, which
        asserts instead of overflows
    */
    function fixedExp(uint256 _x, uint8 _precision) constant returns (uint256) {
        uint256 maxExp = MAX_FIXED_EXP_32;
        for (uint8 p = 32; p < _precision; p += 2)
            maxExp = maxExp * 367765941410054209 / 100000000000000000;

        assert(_x <= maxExp);
        return fixedExpUnsafe(_x, _precision);
    }

    /**
        fixedExp
        Calculates e^x according to maclauren summation:

        e^x = 1+x+x^2/2!...+x^n/n!

        and returns e^(x>>32) << 32, that is, upshifted for accuracy

        Input range:
            - Function ok at    <= 242329958953
            - Function fails at >= 242329958954

        This method is is visible for testcases, but not meant for direct use.

        The values in this method been generated via the following python snippet:

        def calculateFactorials():
            """Method to print out the factorials for fixedExp"""

            ni = []
            ni.append( 295232799039604140847618609643520000000) # 34!
            ITERATIONS = 34
            for n in range( 1,  ITERATIONS,1 ) :
                ni.append(math.floor(ni[n - 1] / n))
            print( "\n        ".join(["xi = (xi * _x) >> _precision;\n        res += xi * %s;" % hex(int(x)) for x in ni]))

    */
    function fixedExpUnsafe(uint256 _x, uint8 _precision) constant returns (uint256) {
        uint256 xi = _x;
        uint256 res = uint256(0xde1bc4d19efcac82445da75b00000000) << _precision;

        res += xi * 0xde1bc4d19efcac82445da75b00000000;
        xi = (xi * _x) >> _precision;
        res += xi * 0x6f0de268cf7e5641222ed3ad80000000;
        xi = (xi * _x) >> _precision;
        res += xi * 0x2504a0cd9a7f7215b60f9be480000000;
        xi = (xi * _x) >> _precision;
        res += xi * 0x9412833669fdc856d83e6f920000000;
        xi = (xi * _x) >> _precision;
        res += xi * 0x1d9d4d714865f4de2b3fafea0000000;
        xi = (xi * _x) >> _precision;
        res += xi * 0x4ef8ce836bba8cfb1dff2a70000000;
        xi = (xi * _x) >> _precision;
        res += xi * 0xb481d807d1aa66d04490610000000;
        xi = (xi * _x) >> _precision;
        res += xi * 0x16903b00fa354cda08920c2000000;
        xi = (xi * _x) >> _precision;
        res += xi * 0x281cdaac677b334ab9e732000000;
        xi = (xi * _x) >> _precision;
        res += xi * 0x402e2aad725eb8778fd85000000;
        xi = (xi * _x) >> _precision;
        res += xi * 0x5d5a6c9f31fe2396a2af000000;
        xi = (xi * _x) >> _precision;
        res += xi * 0x7c7890d442a82f73839400000;
        xi = (xi * _x) >> _precision;
        res += xi * 0x9931ed54034526b58e400000;
        xi = (xi * _x) >> _precision;
        res += xi * 0xaf147cf24ce150cf7e00000;
        xi = (xi * _x) >> _precision;
        res += xi * 0xbac08546b867cdaa200000;
        xi = (xi * _x) >> _precision;
        res += xi * 0xbac08546b867cdaa20000;
        xi = (xi * _x) >> _precision;
        res += xi * 0xafc441338061b2820000;
        xi = (xi * _x) >> _precision;
        res += xi * 0x9c3cabbc0056d790000;
        xi = (xi * _x) >> _precision;
        res += xi * 0x839168328705c30000;
        xi = (xi * _x) >> _precision;
        res += xi * 0x694120286c049c000;
        xi = (xi * _x) >> _precision;
        res += xi * 0x50319e98b3d2c000;
        xi = (xi * _x) >> _precision;
        res += xi * 0x3a52a1e36b82000;
        xi = (xi * _x) >> _precision;
        res += xi * 0x289286e0fce000;
        xi = (xi * _x) >> _precision;
        res += xi * 0x1b0c59eb53400;
        xi = (xi * _x) >> _precision;
        res += xi * 0x114f95b55400;
        xi = (xi * _x) >> _precision;
        res += xi * 0xaa7210d200;
        xi = (xi * _x) >> _precision;
        res += xi * 0x650139600;
        xi = (xi * _x) >> _precision;
        res += xi * 0x39b78e80;
        xi = (xi * _x) >> _precision;
        res += xi * 0x1fd8080;
        xi = (xi * _x) >> _precision;
        res += xi * 0x10fbc0;
        xi = (xi * _x) >> _precision;
        res += xi * 0x8c40;
        xi = (xi * _x) >> _precision;
        res += xi * 0x462;
        xi = (xi * _x) >> _precision;
        res += xi * 0x22;

        return res / 0xde1bc4d19efcac82445da75b00000000;
    }

    function getBestPrecision(uint256 _baseN, uint256 _baseD, uint256 _expN, uint256 _expD) constant returns (uint8) {
        uint8 precision = floorLog2(MAX_FIXED_EXP_32 * _expD / (lnUpperBound(_baseN,_baseD) * _expN));
        if (precision <= 32)
            return 32;
        if (precision >= 48)
            return 64;
        return precision * 2 - 32;
    }

    function lnUpperBound(uint256 baseN, uint256 baseD) constant returns (uint8) {
        assert(baseN > baseD);

        uint256 scaledBaseN = baseN * 100000;
        if (scaledBaseN <= baseD *  271828) // baseN / baseD < e^1
            return 1;
        if (scaledBaseN <= baseD *  738905) // baseN / baseD < e^2
            return 2;
        if (scaledBaseN <= baseD * 2008553) // baseN / baseD < e^3
            return 3;

        return floorLog2(baseN/baseD);
    }

    function floorLog2(uint256 n) constant returns (uint8) {
        uint256 t = 0;
        for (int k = 7; k >= 0; k--) {
            if (n > (uint256(1) << (1 << k)) - 1) {
                uint256 s = uint256(1) << k;
                n >>= s;
                t |= s;
            }
        }

        return uint8(t | (n >> 1));
    }
}


ICO: updated pre-collected ether

ICO: updated pre-collected ether

pragma solidity 0.4.15;

import './ownership/multiowned.sol';
import './crowdsale/FixedTimeBonuses.sol';
import './crowdsale/FundsRegistry.sol';
import './crowdsale/InvestmentAnalytics.sol';
import './security/ArgumentsChecker.sol';
import './STQToken.sol';
import 'zeppelin-solidity/contracts/ReentrancyGuard.sol';
import 'zeppelin-solidity/contracts/math/Math.sol';
import 'zeppelin-solidity/contracts/math/SafeMath.sol';

/// @title Storiqa ICO contract
contract STQCrowdsale is ArgumentsChecker, ReentrancyGuard, multiowned, InvestmentAnalytics {
    using Math for uint256;
    using SafeMath for uint256;
    using FixedTimeBonuses for FixedTimeBonuses.Data;

    enum IcoState { INIT, ICO, PAUSED, FAILED, DISTRIBUTING_BONUSES, SUCCEEDED }

    /// @dev bookkeeping for last investment bonus
    struct LastInvestment {
        address investor;
        uint payment;

        // time-based bonus which was already received by the investor
        uint timeBonus;
    }

    event StateChanged(IcoState _state);
    event FundTransfer(address backer, uint amount, bool isContribution);

    modifier requiresState(IcoState _state) {
        require(m_state == _state);
        _;
    }

    /// @dev triggers some state changes based on current time
    /// @param investor optional refund parameter
    /// @param payment optional refund parameter
    /// note: function body could be skipped!
    modifier timedStateChange(address investor, uint payment) {
        if (IcoState.INIT == m_state && getCurrentTime() >= getStartTime())
            changeState(IcoState.ICO);

        if (IcoState.ICO == m_state && getCurrentTime() >= getEndTime()) {
            finishICO();

            if (payment > 0)
                investor.transfer(payment);
            // note that execution of further (but not preceding!) modifiers and functions ends here
        } else {
            _;
        }
    }

    /// @dev automatic check for unaccounted withdrawals
    /// @param investor optional refund parameter
    /// @param payment optional refund parameter
    modifier fundsChecker(address investor, uint payment) {
        uint atTheBeginning = m_funds.balance;
        if (atTheBeginning < m_lastFundsAmount) {
            changeState(IcoState.PAUSED);
            if (payment > 0)
                investor.transfer(payment);     // we cant throw (have to save state), so refunding this way
            // note that execution of further (but not preceding!) modifiers and functions ends here
        } else {
            _;

            if (m_funds.balance < atTheBeginning) {
                changeState(IcoState.PAUSED);
            } else {
                m_lastFundsAmount = m_funds.balance;
            }
        }
    }

    // PUBLIC interface

    function STQCrowdsale(address[] _owners, address _token, address _funds, address _teamTokens)
        multiowned(_owners, 2)
        validAddress(_token)
        validAddress(_funds)
        validAddress(_teamTokens)
    {
        require(3 == _owners.length);

        m_token = STQToken(_token);
        m_funds = FundsRegistry(_funds);
        m_teamTokens = _teamTokens;

        m_bonuses.bonuses.push(FixedTimeBonuses.Bonus({endTime: c_startTime + (1 weeks), bonus: 30}));
        m_bonuses.bonuses.push(FixedTimeBonuses.Bonus({endTime: c_startTime + (2 weeks), bonus: 25}));
        m_bonuses.bonuses.push(FixedTimeBonuses.Bonus({endTime: c_startTime + (3 weeks), bonus: 20}));
        m_bonuses.bonuses.push(FixedTimeBonuses.Bonus({endTime: c_startTime + (4 weeks), bonus: 15}));
        m_bonuses.bonuses.push(FixedTimeBonuses.Bonus({endTime: c_startTime + (5 weeks), bonus: 10}));
        m_bonuses.bonuses.push(FixedTimeBonuses.Bonus({endTime: c_startTime + (8 weeks), bonus: 5}));
        m_bonuses.bonuses.push(FixedTimeBonuses.Bonus({endTime: 1514246400, bonus: 0}));
        m_bonuses.validate(true);

        deployer = msg.sender;
    }

    // PUBLIC interface: payments

    // fallback function as a shortcut
    function() payable {
        require(0 == msg.data.length);
        buy();  // only internal call here!
    }

    /// @notice ICO participation
    function buy() public payable {     // dont mark as external!
        iaOnInvested(msg.sender, msg.value, false);
    }

    function iaOnInvested(address investor, uint payment, bool usingPaymentChannel)
        internal
        nonReentrant
        timedStateChange(investor, payment)
        fundsChecker(investor, payment)
    {
        require(m_state == IcoState.ICO || m_state == IcoState.INIT && isOwner(investor) /* for final test */);

        require(payment >= c_MinInvestment);

        uint startingInvariant = this.balance.add(m_funds.balance);

        // checking for max cap
        uint fundsAllowed = getMaximumFunds().sub(getTotalInvested());
        assert(0 != fundsAllowed);  // in this case state must not be IcoState.ICO
        payment = fundsAllowed.min256(payment);
        uint256 change = msg.value.sub(payment);

        // issue tokens
        var (stq, timeBonus) = calcSTQAmount(payment, usingPaymentChannel ? c_paymentChannelBonusPercent : 0);
        m_token.mint(investor, stq);

        // record payment
        m_funds.invested.value(payment)(investor);
        FundTransfer(investor, payment, true);

        recordInvestment(investor, payment, timeBonus);

        // check if ICO must be closed early
        if (change > 0)
        {
            assert(getMaximumFunds() == getTotalInvested());
            finishICO();

            // send change
            investor.transfer(change);
            assert(startingInvariant == this.balance.add(m_funds.balance).add(change));
        }
        else
            assert(startingInvariant == this.balance.add(m_funds.balance));
    }

    // PUBLIC interface: owners: maintenance

    /// @notice pauses ICO
    function pause()
        external
        timedStateChange(address(0), 0)
        requiresState(IcoState.ICO)
        onlyowner
    {
        changeState(IcoState.PAUSED);
    }

    /// @notice resume paused ICO
    function unpause()
        external
        timedStateChange(address(0), 0)
        requiresState(IcoState.PAUSED)
        onlymanyowners(sha3(msg.data))
    {
        changeState(IcoState.ICO);
        checkTime();
    }

    /// @notice consider paused ICO as failed
    function fail()
        external
        timedStateChange(address(0), 0)
        requiresState(IcoState.PAUSED)
        onlymanyowners(sha3(msg.data))
    {
        changeState(IcoState.FAILED);
    }

    /// @notice In case we need to attach to existent token
    function setToken(address _token)
        external
        validAddress(_token)
        timedStateChange(address(0), 0)
        requiresState(IcoState.PAUSED)
        onlymanyowners(sha3(msg.data))
    {
        m_token = STQToken(_token);
    }

    /// @notice In case we need to attach to existent funds
    function setFundsRegistry(address _funds)
        external
        validAddress(_funds)
        timedStateChange(address(0), 0)
        requiresState(IcoState.PAUSED)
        onlymanyowners(sha3(msg.data))
    {
        m_funds = FundsRegistry(_funds);
    }

    /// @notice explicit trigger for timed state changes
    function checkTime()
        public
        timedStateChange(address(0), 0)
        onlyowner
    {
    }

    /// @notice computing and distributing post-ICO bonuses
    function distributeBonuses(uint investorsLimit)
        external
        timedStateChange(address(0), 0)
        requiresState(IcoState.DISTRIBUTING_BONUSES)
    {
        uint limitIndex = uint(m_lastInvestments.length).min256(m_nextUndestributedBonusIndex + investorsLimit);
        uint iterations = 0;
        uint startingGas = msg.gas;
        while (m_nextUndestributedBonusIndex < limitIndex) {
            if (c_lastInvestmentsBonus > m_lastInvestments[m_nextUndestributedBonusIndex].timeBonus) {
                uint bonus = c_lastInvestmentsBonus.sub(m_lastInvestments[m_nextUndestributedBonusIndex].timeBonus);
                uint bonusSTQ = m_lastInvestments[m_nextUndestributedBonusIndex].payment.mul(c_STQperETH).mul(bonus).div(100);

                m_token.mint(m_lastInvestments[m_nextUndestributedBonusIndex].investor, bonusSTQ);
            }
            m_nextUndestributedBonusIndex++;

            // preventing gas limit hit
            uint avgGasPerIteration = startingGas.sub(msg.gas).div(++iterations);
            if (msg.gas < avgGasPerIteration * 3)
                break;
        }

        if (m_nextUndestributedBonusIndex == m_lastInvestments.length)
            changeState(IcoState.SUCCEEDED);
    }

    function createMorePaymentChannels(uint limit) external returns (uint) {
        require(isOwner(msg.sender) || msg.sender == deployer);
        return createMorePaymentChannelsInternal(limit);
    }

    // INTERNAL functions

    function finishICO() private {
        if (getTotalInvested() < getMinFunds())
            changeState(IcoState.FAILED);
        else
            changeState(IcoState.DISTRIBUTING_BONUSES);
    }

    /// @dev performs only allowed state transitions
    function changeState(IcoState _newState) private {
        assert(m_state != _newState);

        if (IcoState.INIT == m_state) {        assert(IcoState.ICO == _newState); }
        else if (IcoState.ICO == m_state) {    assert(IcoState.PAUSED == _newState || IcoState.FAILED == _newState || IcoState.DISTRIBUTING_BONUSES == _newState); }
        else if (IcoState.PAUSED == m_state) { assert(IcoState.ICO == _newState || IcoState.FAILED == _newState); }
        else if (IcoState.DISTRIBUTING_BONUSES == m_state) { assert(IcoState.SUCCEEDED == _newState); }
        else assert(false);

        m_state = _newState;
        StateChanged(m_state);

        // this should be tightly linked
        if (IcoState.SUCCEEDED == m_state) {
            onSuccess();
        } else if (IcoState.FAILED == m_state) {
            onFailure();
        }
    }

    function onSuccess() private {
        // mint tokens for owners
        uint tokensForTeam = m_token.totalSupply().mul(40).div(60);
        m_token.mint(m_teamTokens, tokensForTeam);

        m_funds.changeState(FundsRegistry.State.SUCCEEDED);
        m_funds.detachController();

        m_token.disableMinting();
        m_token.startCirculation();
        m_token.detachController();
    }

    function onFailure() private {
        m_funds.changeState(FundsRegistry.State.REFUNDING);
        m_funds.detachController();
    }

    function getLargePaymentBonus(uint payment) private constant returns (uint) {
        if (payment > 5000 ether) return 20;
        if (payment > 3000 ether) return 15;
        if (payment > 1000 ether) return 10;
        if (payment > 800 ether) return 8;
        if (payment > 500 ether) return 5;
        if (payment > 200 ether) return 2;
        return 0;
    }

    /// @dev calculates amount of STQ to which payer of _wei is entitled
    function calcSTQAmount(uint _wei, uint extraBonus) private constant returns (uint stq, uint timeBonus) {
        timeBonus = m_bonuses.getBonus(getCurrentTime());
        uint bonus = extraBonus.add(timeBonus).add(getLargePaymentBonus(_wei));

        // apply bonus
        stq = _wei.mul(c_STQperETH).mul(bonus.add(100)).div(100);
    }

    /// @dev records investments in a circular buffer
    function recordInvestment(address investor, uint payment, uint timeBonus) private {
        uint writeTo;
        assert(m_lastInvestments.length <= getLastMaxInvestments());
        if (m_lastInvestments.length < getLastMaxInvestments()) {
            // buffer is still expanding
            writeTo = m_lastInvestments.length++;
        }
        else {
            // reusing buffer
            writeTo = m_nextFreeLastInvestmentIndex++;
            if (m_nextFreeLastInvestmentIndex == m_lastInvestments.length)
                m_nextFreeLastInvestmentIndex = 0;
        }

        assert(writeTo < m_lastInvestments.length);
        m_lastInvestments[writeTo] = LastInvestment(investor, payment, timeBonus);
    }

    /// @dev start time of the ICO, inclusive
    function getStartTime() private constant returns (uint) {
        return c_startTime;
    }

    /// @dev end time of the ICO, inclusive
    function getEndTime() private constant returns (uint) {
        return m_bonuses.getLastTime();
    }

    /// @dev to be overridden in tests
    function getCurrentTime() internal constant returns (uint) {
        return now;
    }

    /// @dev to be overridden in tests
    function getMinFunds() internal constant returns (uint) {
        return c_MinFunds;
    }

    /// @dev to be overridden in tests
    function getMaximumFunds() internal constant returns (uint) {
        return c_MaximumFunds;
    }

    /// @dev amount of investments during all crowdsales
    function getTotalInvested() internal constant returns (uint) {
        return m_funds.totalInvested().add(4281 ether /* FIXME update me */);
    }

    /// @dev to be overridden in tests
    function getLastMaxInvestments() internal constant returns (uint) {
        return c_maxLastInvestments;
    }

    // FIELDS

    /// @notice starting exchange rate of STQ
    uint public constant c_STQperETH = 100000;

    /// @notice minimum investment
    uint public constant c_MinInvestment = 10 finney;

    /// @notice minimum investments to consider ICO as a success
    uint public constant c_MinFunds = 30000 ether;

    /// @notice maximum investments to be accepted during ICO
    uint public constant c_MaximumFunds = 90000 ether;

    /// @notice start time of the ICO
    uint public constant c_startTime = 1508889600;

    /// @notice authorised payment bonus
    uint public constant c_paymentChannelBonusPercent = 2;

    /// @notice timed bonuses
    FixedTimeBonuses.Data m_bonuses;

    uint public constant c_maxLastInvestments = 100;

    uint public constant c_lastInvestmentsBonus = 30;

    /// @dev bookkeeping for last investment bonus
    LastInvestment[] public m_lastInvestments;

    uint m_nextFreeLastInvestmentIndex;

    uint m_nextUndestributedBonusIndex;

    /// @dev state of the ICO
    IcoState public m_state = IcoState.INIT;

    /// @dev contract responsible for token accounting
    STQToken public m_token;

    address public m_teamTokens;

    address public deployer;

    /// @dev contract responsible for investments accounting
    FundsRegistry public m_funds;

    /// @dev last recorded funds
    uint256 public m_lastFundsAmount;
}

pragma solidity 0.4.15;

import './ownership/multiowned.sol';
import './crowdsale/FixedTimeBonuses.sol';
import './crowdsale/FundsRegistry.sol';
import './crowdsale/InvestmentAnalytics.sol';
import './security/ArgumentsChecker.sol';
import './STQToken.sol';
import 'zeppelin-solidity/contracts/ReentrancyGuard.sol';
import 'zeppelin-solidity/contracts/math/Math.sol';
import 'zeppelin-solidity/contracts/math/SafeMath.sol';

/// @title Storiqa ICO contract
contract STQCrowdsale is ArgumentsChecker, ReentrancyGuard, multiowned, InvestmentAnalytics {
    using Math for uint256;
    using SafeMath for uint256;
    using FixedTimeBonuses for FixedTimeBonuses.Data;

    enum IcoState { INIT, ICO, PAUSED, FAILED, DISTRIBUTING_BONUSES, SUCCEEDED }

    /// @dev bookkeeping for last investment bonus
    struct LastInvestment {
        address investor;
        uint payment;

        // time-based bonus which was already received by the investor
        uint timeBonus;
    }

    event StateChanged(IcoState _state);
    event FundTransfer(address backer, uint amount, bool isContribution);

    modifier requiresState(IcoState _state) {
        require(m_state == _state);
        _;
    }

    /// @dev triggers some state changes based on current time
    /// @param investor optional refund parameter
    /// @param payment optional refund parameter
    /// note: function body could be skipped!
    modifier timedStateChange(address investor, uint payment) {
        if (IcoState.INIT == m_state && getCurrentTime() >= getStartTime())
            changeState(IcoState.ICO);

        if (IcoState.ICO == m_state && getCurrentTime() >= getEndTime()) {
            finishICO();

            if (payment > 0)
                investor.transfer(payment);
            // note that execution of further (but not preceding!) modifiers and functions ends here
        } else {
            _;
        }
    }

    /// @dev automatic check for unaccounted withdrawals
    /// @param investor optional refund parameter
    /// @param payment optional refund parameter
    modifier fundsChecker(address investor, uint payment) {
        uint atTheBeginning = m_funds.balance;
        if (atTheBeginning < m_lastFundsAmount) {
            changeState(IcoState.PAUSED);
            if (payment > 0)
                investor.transfer(payment);     // we cant throw (have to save state), so refunding this way
            // note that execution of further (but not preceding!) modifiers and functions ends here
        } else {
            _;

            if (m_funds.balance < atTheBeginning) {
                changeState(IcoState.PAUSED);
            } else {
                m_lastFundsAmount = m_funds.balance;
            }
        }
    }

    // PUBLIC interface

    function STQCrowdsale(address[] _owners, address _token, address _funds, address _teamTokens)
        multiowned(_owners, 2)
        validAddress(_token)
        validAddress(_funds)
        validAddress(_teamTokens)
    {
        require(3 == _owners.length);

        m_token = STQToken(_token);
        m_funds = FundsRegistry(_funds);
        m_teamTokens = _teamTokens;

        m_bonuses.bonuses.push(FixedTimeBonuses.Bonus({endTime: c_startTime + (1 weeks), bonus: 30}));
        m_bonuses.bonuses.push(FixedTimeBonuses.Bonus({endTime: c_startTime + (2 weeks), bonus: 25}));
        m_bonuses.bonuses.push(FixedTimeBonuses.Bonus({endTime: c_startTime + (3 weeks), bonus: 20}));
        m_bonuses.bonuses.push(FixedTimeBonuses.Bonus({endTime: c_startTime + (4 weeks), bonus: 15}));
        m_bonuses.bonuses.push(FixedTimeBonuses.Bonus({endTime: c_startTime + (5 weeks), bonus: 10}));
        m_bonuses.bonuses.push(FixedTimeBonuses.Bonus({endTime: c_startTime + (8 weeks), bonus: 5}));
        m_bonuses.bonuses.push(FixedTimeBonuses.Bonus({endTime: 1514246400, bonus: 0}));
        m_bonuses.validate(true);

        deployer = msg.sender;
    }

    // PUBLIC interface: payments

    // fallback function as a shortcut
    function() payable {
        require(0 == msg.data.length);
        buy();  // only internal call here!
    }

    /// @notice ICO participation
    function buy() public payable {     // dont mark as external!
        iaOnInvested(msg.sender, msg.value, false);
    }

    function iaOnInvested(address investor, uint payment, bool usingPaymentChannel)
        internal
        nonReentrant
        timedStateChange(investor, payment)
        fundsChecker(investor, payment)
    {
        require(m_state == IcoState.ICO || m_state == IcoState.INIT && isOwner(investor) /* for final test */);

        require(payment >= c_MinInvestment);

        uint startingInvariant = this.balance.add(m_funds.balance);

        // checking for max cap
        uint fundsAllowed = getMaximumFunds().sub(getTotalInvested());
        assert(0 != fundsAllowed);  // in this case state must not be IcoState.ICO
        payment = fundsAllowed.min256(payment);
        uint256 change = msg.value.sub(payment);

        // issue tokens
        var (stq, timeBonus) = calcSTQAmount(payment, usingPaymentChannel ? c_paymentChannelBonusPercent : 0);
        m_token.mint(investor, stq);

        // record payment
        m_funds.invested.value(payment)(investor);
        FundTransfer(investor, payment, true);

        recordInvestment(investor, payment, timeBonus);

        // check if ICO must be closed early
        if (change > 0)
        {
            assert(getMaximumFunds() == getTotalInvested());
            finishICO();

            // send change
            investor.transfer(change);
            assert(startingInvariant == this.balance.add(m_funds.balance).add(change));
        }
        else
            assert(startingInvariant == this.balance.add(m_funds.balance));
    }

    // PUBLIC interface: owners: maintenance

    /// @notice pauses ICO
    function pause()
        external
        timedStateChange(address(0), 0)
        requiresState(IcoState.ICO)
        onlyowner
    {
        changeState(IcoState.PAUSED);
    }

    /// @notice resume paused ICO
    function unpause()
        external
        timedStateChange(address(0), 0)
        requiresState(IcoState.PAUSED)
        onlymanyowners(sha3(msg.data))
    {
        changeState(IcoState.ICO);
        checkTime();
    }

    /// @notice consider paused ICO as failed
    function fail()
        external
        timedStateChange(address(0), 0)
        requiresState(IcoState.PAUSED)
        onlymanyowners(sha3(msg.data))
    {
        changeState(IcoState.FAILED);
    }

    /// @notice In case we need to attach to existent token
    function setToken(address _token)
        external
        validAddress(_token)
        timedStateChange(address(0), 0)
        requiresState(IcoState.PAUSED)
        onlymanyowners(sha3(msg.data))
    {
        m_token = STQToken(_token);
    }

    /// @notice In case we need to attach to existent funds
    function setFundsRegistry(address _funds)
        external
        validAddress(_funds)
        timedStateChange(address(0), 0)
        requiresState(IcoState.PAUSED)
        onlymanyowners(sha3(msg.data))
    {
        m_funds = FundsRegistry(_funds);
    }

    /// @notice explicit trigger for timed state changes
    function checkTime()
        public
        timedStateChange(address(0), 0)
        onlyowner
    {
    }

    /// @notice computing and distributing post-ICO bonuses
    function distributeBonuses(uint investorsLimit)
        external
        timedStateChange(address(0), 0)
        requiresState(IcoState.DISTRIBUTING_BONUSES)
    {
        uint limitIndex = uint(m_lastInvestments.length).min256(m_nextUndestributedBonusIndex + investorsLimit);
        uint iterations = 0;
        uint startingGas = msg.gas;
        while (m_nextUndestributedBonusIndex < limitIndex) {
            if (c_lastInvestmentsBonus > m_lastInvestments[m_nextUndestributedBonusIndex].timeBonus) {
                uint bonus = c_lastInvestmentsBonus.sub(m_lastInvestments[m_nextUndestributedBonusIndex].timeBonus);
                uint bonusSTQ = m_lastInvestments[m_nextUndestributedBonusIndex].payment.mul(c_STQperETH).mul(bonus).div(100);

                m_token.mint(m_lastInvestments[m_nextUndestributedBonusIndex].investor, bonusSTQ);
            }
            m_nextUndestributedBonusIndex++;

            // preventing gas limit hit
            uint avgGasPerIteration = startingGas.sub(msg.gas).div(++iterations);
            if (msg.gas < avgGasPerIteration * 3)
                break;
        }

        if (m_nextUndestributedBonusIndex == m_lastInvestments.length)
            changeState(IcoState.SUCCEEDED);
    }

    function createMorePaymentChannels(uint limit) external returns (uint) {
        require(isOwner(msg.sender) || msg.sender == deployer);
        return createMorePaymentChannelsInternal(limit);
    }

    // INTERNAL functions

    function finishICO() private {
        if (getTotalInvested() < getMinFunds())
            changeState(IcoState.FAILED);
        else
            changeState(IcoState.DISTRIBUTING_BONUSES);
    }

    /// @dev performs only allowed state transitions
    function changeState(IcoState _newState) private {
        assert(m_state != _newState);

        if (IcoState.INIT == m_state) {        assert(IcoState.ICO == _newState); }
        else if (IcoState.ICO == m_state) {    assert(IcoState.PAUSED == _newState || IcoState.FAILED == _newState || IcoState.DISTRIBUTING_BONUSES == _newState); }
        else if (IcoState.PAUSED == m_state) { assert(IcoState.ICO == _newState || IcoState.FAILED == _newState); }
        else if (IcoState.DISTRIBUTING_BONUSES == m_state) { assert(IcoState.SUCCEEDED == _newState); }
        else assert(false);

        m_state = _newState;
        StateChanged(m_state);

        // this should be tightly linked
        if (IcoState.SUCCEEDED == m_state) {
            onSuccess();
        } else if (IcoState.FAILED == m_state) {
            onFailure();
        }
    }

    function onSuccess() private {
        // mint tokens for owners
        uint tokensForTeam = m_token.totalSupply().mul(40).div(60);
        m_token.mint(m_teamTokens, tokensForTeam);

        m_funds.changeState(FundsRegistry.State.SUCCEEDED);
        m_funds.detachController();

        m_token.disableMinting();
        m_token.startCirculation();
        m_token.detachController();
    }

    function onFailure() private {
        m_funds.changeState(FundsRegistry.State.REFUNDING);
        m_funds.detachController();
    }

    function getLargePaymentBonus(uint payment) private constant returns (uint) {
        if (payment > 5000 ether) return 20;
        if (payment > 3000 ether) return 15;
        if (payment > 1000 ether) return 10;
        if (payment > 800 ether) return 8;
        if (payment > 500 ether) return 5;
        if (payment > 200 ether) return 2;
        return 0;
    }

    /// @dev calculates amount of STQ to which payer of _wei is entitled
    function calcSTQAmount(uint _wei, uint extraBonus) private constant returns (uint stq, uint timeBonus) {
        timeBonus = m_bonuses.getBonus(getCurrentTime());
        uint bonus = extraBonus.add(timeBonus).add(getLargePaymentBonus(_wei));

        // apply bonus
        stq = _wei.mul(c_STQperETH).mul(bonus.add(100)).div(100);
    }

    /// @dev records investments in a circular buffer
    function recordInvestment(address investor, uint payment, uint timeBonus) private {
        uint writeTo;
        assert(m_lastInvestments.length <= getLastMaxInvestments());
        if (m_lastInvestments.length < getLastMaxInvestments()) {
            // buffer is still expanding
            writeTo = m_lastInvestments.length++;
        }
        else {
            // reusing buffer
            writeTo = m_nextFreeLastInvestmentIndex++;
            if (m_nextFreeLastInvestmentIndex == m_lastInvestments.length)
                m_nextFreeLastInvestmentIndex = 0;
        }

        assert(writeTo < m_lastInvestments.length);
        m_lastInvestments[writeTo] = LastInvestment(investor, payment, timeBonus);
    }

    /// @dev start time of the ICO, inclusive
    function getStartTime() private constant returns (uint) {
        return c_startTime;
    }

    /// @dev end time of the ICO, inclusive
    function getEndTime() private constant returns (uint) {
        return m_bonuses.getLastTime();
    }

    /// @dev to be overridden in tests
    function getCurrentTime() internal constant returns (uint) {
        return now;
    }

    /// @dev to be overridden in tests
    function getMinFunds() internal constant returns (uint) {
        return c_MinFunds;
    }

    /// @dev to be overridden in tests
    function getMaximumFunds() internal constant returns (uint) {
        return c_MaximumFunds;
    }

    /// @dev amount of investments during all crowdsales
    function getTotalInvested() internal constant returns (uint) {
        return m_funds.totalInvested().add(2468 ether /* FIXME update me */);
    }

    /// @dev to be overridden in tests
    function getLastMaxInvestments() internal constant returns (uint) {
        return c_maxLastInvestments;
    }

    // FIELDS

    /// @notice starting exchange rate of STQ
    uint public constant c_STQperETH = 100000;

    /// @notice minimum investment
    uint public constant c_MinInvestment = 10 finney;

    /// @notice minimum investments to consider ICO as a success
    uint public constant c_MinFunds = 30000 ether;

    /// @notice maximum investments to be accepted during ICO
    uint public constant c_MaximumFunds = 90000 ether;

    /// @notice start time of the ICO
    uint public constant c_startTime = 1508889600;

    /// @notice authorised payment bonus
    uint public constant c_paymentChannelBonusPercent = 2;

    /// @notice timed bonuses
    FixedTimeBonuses.Data m_bonuses;

    uint public constant c_maxLastInvestments = 100;

    uint public constant c_lastInvestmentsBonus = 30;

    /// @dev bookkeeping for last investment bonus
    LastInvestment[] public m_lastInvestments;

    uint m_nextFreeLastInvestmentIndex;

    uint m_nextUndestributedBonusIndex;

    /// @dev state of the ICO
    IcoState public m_state = IcoState.INIT;

    /// @dev contract responsible for token accounting
    STQToken public m_token;

    address public m_teamTokens;

    address public deployer;

    /// @dev contract responsible for investments accounting
    FundsRegistry public m_funds;

    /// @dev last recorded funds
    uint256 public m_lastFundsAmount;
}


Expose participantsIndex as public attribute

contract Conference {
	string public name;
	uint256 public balance;
	uint256 public deposit;
	uint public capacity;
	uint public registered;
	uint public attended;
	mapping (address => Participant) public participants;
	mapping (uint => address) public participantsIndex;
	bool paid;
	uint256 _pot;

	struct Participant {
		address addr;
		bool attended;
	}

	event Register(address addr, uint256 balance, uint256 value);
	event Attend(address addr, uint256 balance);
	event Payback(address addr, uint256 _pot, uint256 balance, bool paid);

	function Conference() {
		name = 'CodeUp';
		deposit = 1000000000000000000;		// 1 ETH = 10**18 wai
		balance = 0;
		registered = 0;
		attended = 0;
	}

	function register(){
		Register(msg.sender, msg.sender.balance, msg.value);
		if (msg.value != deposit) throw;
		if (isRegistered()) throw;
		registered++;
		participantsIndex[registered] = msg.sender;
		participants[msg.sender] = Participant(msg.sender, false);
		balance = balance + (deposit * 1);
	}

	function attend(){
		if (isRegistered() != true) throw;
		Attend(msg.sender, msg.sender.balance);
		participants[msg.sender].attended = true;
		attended++;
	}

	function isRegistered() returns (bool){
		return participants[msg.sender].addr != 0x0;
	}

	function isAttended() returns (bool){
		return isRegistered() && participants[msg.sender].attended;
	}

	function pot() returns(uint256){
		return balance / uint(attended);
	}

	function payback(){
		for(uint i=1;i<=registered;i++)
		{
			if(participants[participantsIndex[i]].attended){
				Payback(participantsIndex[i], pot(), participantsIndex[i].balance,  true);
				participantsIndex[i].send(pot());
			}else{
				Payback(participantsIndex[i], pot(), participantsIndex[i].balance, false);
			}
		}
		balance = 0;
	}
}

contract Conference {
	string public name;
	uint256 public balance;
	uint256 public deposit;
	uint public capacity;
	uint public registered;
	uint public attended;
	mapping (address => Participant) public participants;
	mapping (uint => address) participantsIndex;
	bool paid;
	uint256 _pot;

	struct Participant {
		address addr;
		bool attended;
	}

	event Register(address addr, uint256 balance, uint256 value);
	event Attend(address addr, uint256 balance);
	event Payback(address addr, uint256 _pot, uint256 balance, bool paid);

	function Conference() {
		name = 'CodeUp';
		deposit = 1000000000000000000;		// 1 ETH = 10**18 wai
		balance = 0;
		registered = 0;
		attended = 0;
	}

	function register(){
		Register(msg.sender, msg.sender.balance, msg.value);
		if (msg.value != deposit) throw;
		if (isRegistered()) throw;
		registered++;
		participantsIndex[registered] = msg.sender;
		participants[msg.sender] = Participant(msg.sender, false);
		balance = balance + (deposit * 1);
	}

	function attend(){
		if (isRegistered() != true) throw;
		Attend(msg.sender, msg.sender.balance);
		participants[msg.sender].attended = true;
		attended++;
	}

	function isRegistered() returns (bool){
		return participants[msg.sender].addr != 0x0;
	}

	function isAttended() returns (bool){
		return isRegistered() && participants[msg.sender].attended;
	}

	function pot() returns(uint256){
		return balance / uint(attended);
	}

	function payback(){
		for(uint i=1;i<=registered;i++)
		{
			if(participants[participantsIndex[i]].attended){
				Payback(participantsIndex[i], pot(), participantsIndex[i].balance,  true);
				participantsIndex[i].send(pot());
			}else{
				Payback(participantsIndex[i], pot(), participantsIndex[i].balance, false);
			}
		}
		balance = 0;
	}
}


Tokens to comply with ChainX Network

Tokens to comply with ChainX Network

pragma solidity ^0.4.8;

/*
 * Ownable
 *
 * Base contract with an owner.
 * Provides onlyOwner modifier, which prevents function from running if it is called by anyone other than the owner.
 */

contract Ownable {
    address public owner;

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

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

    function transferOwnership(address newOwner) onlyOwner {
        if (newOwner != address(0)) {
            owner = newOwner;
        }
}

error: pathspec 'Contracts/Base/Ownable.sol' did not match any file(s) known to git