Contract optimization.

Contract optimization.

/**
 * Copyright 2016 Everex https://everex.io
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/* String utility library */
library strUtils {
    string constant CHAINY_JSON_ID = 'id:"CHAINY"';
    uint8 constant CHAINY_JSON_MIN_LEN = 32;

    /* Converts given number to base58, limited by _maxLength symbols */
    function toBase58(uint256 _value, uint8 _maxLength) internal returns (string) {
        string memory letters = "123456789abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ";
        bytes memory alphabet = bytes(letters);
        uint8 base = 58;
        uint8 len = 0;
        uint256 remainder = 0;
        bytes memory bytesReversed = bytes(new string(_maxLength));

        for (uint8 i = 0; i < _maxLength; i++) {
            remainder = _value % base;
            _value = uint256(_value / base);
            bytesReversed[i] = alphabet[remainder];
            len++;
            if(_value < base){
                break;
            }
        }

        // Reverse
        bytes memory result = bytes(new string(len));
        for (i = 0; i < len; i++) {
            result[i] = bytesReversed[len - i - 1];
        }
        return string(result);
    }

    /* Concatenates two strings */
    function concat(string _s1, string _s2) internal returns (string) {
        bytes memory bs1 = bytes(_s1);
        bytes memory bs2 = bytes(_s2);
        string memory s3 = new string(bs1.length + bs2.length);
        bytes memory bs3 = bytes(s3);

        uint256 j = 0;
        for (uint256 i = 0; i < bs1.length; i++) {
            bs3[j++] = bs1[i];
        }
        for (i = 0; i < bs2.length; i++) {
            bs3[j++] = bs2[i];
        }

        return string(bs3);
    }

    /* Checks if provided JSON string has valid Chainy format */
    function isValidChainyJson(string _json) internal returns (bool) {
        bytes memory json = bytes(_json);
        bytes memory id = bytes(CHAINY_JSON_ID);

        if (json.length < CHAINY_JSON_MIN_LEN) {
            return false;
        } else {
            uint len = 0;
            for (uint i = 0; i < json.length; i++) {
                if (i > 1) return false;
                if (json[i] == id[0]) {
                    len = 1;
                    while (len < id.length && (i + len) < json.length && json[i + len] == id[len]) {
                        len++;
                    }
                    if (len == id.length) {
                        return true;
                    }
                }
            }
        }

        return false;
    }
}

// Ownership
contract owned {
    address public owner;

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

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

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

// Mortality
contract mortal is owned {
    function kill() onlyOwner {
        if (this.balance > 0) {
            if (!msg.sender.send(this.balance)) throw;
        }
        suicide(msg.sender);
    }
}

contract Chainy is owned, mortal {
    string constant CHAINY_URL = "https://txn.me/";

    // Configuration
    mapping(string => uint256) private chainyConfig;

    // Service accounts
    mapping (address => bool) private srvAccount;

    // Fee receiver
    address private receiverAddress;

    struct data {uint256 timestamp; string json; address sender;}
    mapping (string => data) private chainy;

    event chainyShortLink(uint256 timestamp, string code);

    // Constructor
    function Chainy(){
        setConfig("fee", 0);
        setConfig("blockoffset", 1000000);
    }

    // Sets configuration option
    function setConfig(string _key, uint256 _value) onlyOwner {
        chainyConfig[_key] = _value;
    }

    // Returns configuration option
    function getConfig(string _key) constant returns (uint256 _value) {
        return chainyConfig[_key];
    }

    // Add/Remove service account
    function setServiceAccount(address _address, bool _value) onlyOwner {
        srvAccount[_address] = _value;
    }

    // Set receiver address
    function setReceiverAddress(address _address) onlyOwner {
        receiverAddress = _address;
    }

    // Add record
    function addChainyData(string json) {
        checkFormat(json);

        var code = generateShortLink();
        // Checks if the record exist
        if (getChainyTimestamp(code) > 0) throw;

        processFee();
        chainy[code] = data({
            timestamp: block.timestamp,
            json: json,
            sender: tx.origin
        });

        // Fire event
        var link = strUtils.concat(CHAINY_URL, code);
        chainyShortLink(block.timestamp, link);
    }

    // Get record timestamp
    function getChainyTimestamp(string code) constant returns (uint256) {
        return chainy[code].timestamp;
    }

    // Get record JSON
    function getChainyData(string code) constant returns (string) {
        return chainy[code].json;
    }

    // Get record sender
    function getChainySender(string code) constant returns (address) {
        return chainy[code].sender;
    }

    // Checks if enough fee provided
    function processFee() internal {
        var fee = getConfig("fee");
        if (srvAccount[msg.sender] || (fee == 0)) return;

        if (msg.value < fee)
            throw;
        else
            if (!receiverAddress.send(fee)) throw;
    }

    // Checks if provided string has valid format
    function checkFormat(string json) internal {
        if (!strUtils.isValidChainyJson(json)) throw;
    }

    function generateShortLink() internal returns (string) {
        var s1 = strUtils.toBase58(block.number - getConfig("blockoffset"), 10);
        var s2 = strUtils.toBase58(uint256(tx.origin), 2);

        var s = strUtils.concat(s1, s2);
        return s;
    }

}

/**
 * Copyright 2016 Everex https://everex.io
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/* String utility library */
library strUtils {
    string constant CHAINY_JSON_ID = 'id:"CHAINY"';
    uint8 constant CHAINY_JSON_MIN_LEN = 32;

    /* Converts given number to base58, limited by _maxLength symbols */
    function toBase58(uint256 _value, uint8 _maxLength) internal returns (string) {
        string memory letters = "123456789abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ";
        bytes memory alphabet = bytes(letters);
        uint8 base = 58;
        uint8 len = 0;
        uint256 remainder = 0;
        bytes memory bytesReversed = bytes(new string(_maxLength));

        for (uint8 i = 0; i < _maxLength; i++) {
            remainder = _value % base;
            _value = uint256(_value / base);
            bytesReversed[i] = alphabet[remainder];
            len++;
            if(_value < base){
                break;
            }
        }

        // Reverse
        bytes memory result = bytes(new string(len));
        for (i = 0; i < len; i++) {
            result[i] = bytesReversed[len - i - 1];
        }
        return string(result);
    }

    /* Concatenates two strings */
    function concat(string _s1, string _s2) internal returns (string) {
        bytes memory bs1 = bytes(_s1);
        bytes memory bs2 = bytes(_s2);
        string memory s3 = new string(bs1.length + bs2.length);
        bytes memory bs3 = bytes(s3);

        uint256 j = 0;
        for (uint256 i = 0; i < bs1.length; i++) {
            bs3[j++] = bs1[i];
        }
        for (i = 0; i < bs2.length; i++) {
            bs3[j++] = bs2[i];
        }

        return string(bs3);
    }

    /* Checks if provided JSON string has valid Chainy format */
    function isValidChainyJson(string _json) internal returns (bool) {
        bytes memory json = bytes(_json);
        bytes memory id = bytes(CHAINY_JSON_ID);

        if (json.length < CHAINY_JSON_MIN_LEN) {
            return false;
        } else {
            uint len = 0;
            for (uint i = 0; i < json.length; i++) {
                if (json[i] == id[0]) {
                    len = 1;
                    while (len < id.length && (i + len) < json.length && json[i + len] == id[len]) {
                        len++;
                    }
                    if (len == id.length) {
                        return true;
                    }
                }
            }
        }

        return false;
    }
}

// Ownership
contract owned {
    address public owner;

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

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

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

// Mortality
contract mortal is owned {
    function kill() onlyOwner {
        if (this.balance > 0) {
            if (!msg.sender.send(this.balance)) throw;
        }
        suicide(msg.sender);
    }
}

contract Chainy is owned, mortal {
    string constant CHAINY_URL = "https://txn.me/";

    // Configuration
    mapping(string => uint256) private chainyConfig;

    // Service accounts
    mapping (address => bool) private srvAccount;

    // Fee receiver
    address private receiverAddress;

    struct data {uint256 timestamp; string json; address sender;}
    mapping (string => data) private chainy;

    event chainyShortLink(uint256 timestamp, string code);

    // Constructor
    function Chainy(){
        setConfig("fee", 0);
    }

    // Sets configuration option
    function setConfig(string _key, uint256 _value) onlyOwner {
        chainyConfig[_key] = _value;
    }

    // Returns configuration option
    function getConfig(string _key) constant returns (uint256 _value) {
        return chainyConfig[_key];
    }

    // Add/Remove service account
    function setServiceAccount(address _address, bool _value) onlyOwner {
        srvAccount[_address] = _value;
    }

    // Set receiver address
    function setReceiverAddress(address _address) onlyOwner {
        receiverAddress = _address;
    }

    // Add record
    function addChainyData(string json) {
        checkFormat(json);

        var code = generateShortLink();
        // Checks if the record exist
        if (getChainyTimestamp(code) > 0) throw;

        processFee();
        chainy[code] = data({
            timestamp: block.timestamp,
            json: json,
            sender: tx.origin
        });

        // Fire event
        var link = strUtils.concat(CHAINY_URL, code);
        chainyShortLink(block.timestamp, link);
    }

    // Get record timestamp
    function getChainyTimestamp(string code) constant returns (uint256) {
        return chainy[code].timestamp;
    }

    // Get record JSON
    function getChainyData(string code) constant returns (string) {
        return chainy[code].json;
    }

    // Get record sender
    function getChainySender(string code) constant returns (address) {
        return chainy[code].sender;
    }

    // Checks if enough fee provided
    function processFee() internal {
        var fee = getConfig("fee");
        if (srvAccount[msg.sender] || (fee == 0)) return;

        if (msg.value < fee)
            throw;
        else
            if (!receiverAddress.send(fee)) throw;
    }

    // Checks if provided string has valid format
    function checkFormat(string json) internal {
        if (!strUtils.isValidChainyJson(json)) throw;
    }

    function generateShortLink() internal returns (string) {
        var s1 = strUtils.toBase58(block.number - 1000000, 10);
        var s2 = strUtils.toBase58(uint256(tx.origin), 2);

        var s = strUtils.concat(s1, s2);
        return s;
    }

}


Fixing really minor typo (#1911)

Fixing really minor typo (#1911)

pragma solidity ^0.5.0;

import "../../GSN/Context.sol";
import "./IERC20.sol";
import "../../math/SafeMath.sol";

/**
 * @dev Implementation of the {IERC20} interface.
 *
 * This implementation is agnostic to the way tokens are created. This means
 * that a supply mechanism has to be added in a derived contract using {_mint}.
 * For a generic mechanism see {ERC20Mintable}.
 *
 * TIP: For a detailed writeup see our guide
 * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How
 * to implement supply mechanisms].
 *
 * We have followed general OpenZeppelin guidelines: functions revert instead
 * of returning `false` on failure. This behavior is nonetheless conventional
 * and does not conflict with the expectations of ERC20 applications.
 *
 * Additionally, an {Approval} event is emitted on calls to {transferFrom}.
 * This allows applications to reconstruct the allowance for all accounts just
 * by listening to said events. Other implementations of the EIP may not emit
 * these events, as it isn't required by the specification.
 *
 * Finally, the non-standard {decreaseAllowance} and {increaseAllowance}
 * functions have been added to mitigate the well-known issues around setting
 * allowances. See {IERC20-approve}.
 */
contract ERC20 is Context, IERC20 {
    using SafeMath for uint256;

    mapping (address => uint256) private _balances;

    mapping (address => mapping (address => uint256)) private _allowances;

    uint256 private _totalSupply;

    /**
     * @dev See {IERC20-totalSupply}.
     */
    function totalSupply() public view returns (uint256) {
        return _totalSupply;
    }

    /**
     * @dev See {IERC20-balanceOf}.
     */
    function balanceOf(address account) public view returns (uint256) {
        return _balances[account];
    }

    /**
     * @dev See {IERC20-transfer}.
     *
     * Requirements:
     *
     * - `recipient` cannot be the zero address.
     * - the caller must have a balance of at least `amount`.
     */
    function transfer(address recipient, uint256 amount) public returns (bool) {
        _transfer(_msgSender(), recipient, amount);
        return true;
    }

    /**
     * @dev See {IERC20-allowance}.
     */
    function allowance(address owner, address spender) public view returns (uint256) {
        return _allowances[owner][spender];
    }

    /**
     * @dev See {IERC20-approve}.
     *
     * Requirements:
     *
     * - `spender` cannot be the zero address.
     */
    function approve(address spender, uint256 amount) public returns (bool) {
        _approve(_msgSender(), spender, amount);
        return true;
    }

    /**
     * @dev See {IERC20-transferFrom}.
     *
     * Emits an {Approval} event indicating the updated allowance. This is not
     * required by the EIP. See the note at the beginning of {ERC20};
     *
     * Requirements:
     * - `sender` and `recipient` cannot be the zero address.
     * - `sender` must have a balance of at least `amount`.
     * - the caller must have allowance for `sender`'s tokens of at least
     * `amount`.
     */
    function transferFrom(address sender, address recipient, uint256 amount) public returns (bool) {
        _transfer(sender, recipient, amount);
        _approve(sender, _msgSender(), _allowances[sender][_msgSender()].sub(amount, "ERC20: transfer amount exceeds allowance"));
        return true;
    }

    /**
     * @dev Atomically increases the allowance granted to `spender` by the caller.
     *
     * This is an alternative to {approve} that can be used as a mitigation for
     * problems described in {IERC20-approve}.
     *
     * Emits an {Approval} event indicating the updated allowance.
     *
     * Requirements:
     *
     * - `spender` cannot be the zero address.
     */
    function increaseAllowance(address spender, uint256 addedValue) public returns (bool) {
        _approve(_msgSender(), spender, _allowances[_msgSender()][spender].add(addedValue));
        return true;
    }

    /**
     * @dev Atomically decreases the allowance granted to `spender` by the caller.
     *
     * This is an alternative to {approve} that can be used as a mitigation for
     * problems described in {IERC20-approve}.
     *
     * Emits an {Approval} event indicating the updated allowance.
     *
     * Requirements:
     *
     * - `spender` cannot be the zero address.
     * - `spender` must have allowance for the caller of at least
     * `subtractedValue`.
     */
    function decreaseAllowance(address spender, uint256 subtractedValue) public returns (bool) {
        _approve(_msgSender(), spender, _allowances[_msgSender()][spender].sub(subtractedValue, "ERC20: decreased allowance below zero"));
        return true;
    }

    /**
     * @dev Moves tokens `amount` from `sender` to `recipient`.
     *
     * This is internal function is equivalent to {transfer}, and can be used to
     * e.g. implement automatic token fees, slashing mechanisms, etc.
     *
     * Emits a {Transfer} event.
     *
     * Requirements:
     *
     * - `sender` cannot be the zero address.
     * - `recipient` cannot be the zero address.
     * - `sender` must have a balance of at least `amount`.
     */
    function _transfer(address sender, address recipient, uint256 amount) internal {
        require(sender != address(0), "ERC20: transfer from the zero address");
        require(recipient != address(0), "ERC20: transfer to the zero address");

        _balances[sender] = _balances[sender].sub(amount, "ERC20: transfer amount exceeds balance");
        _balances[recipient] = _balances[recipient].add(amount);
        emit Transfer(sender, recipient, amount);
    }

    /** @dev Creates `amount` tokens and assigns them to `account`, increasing
     * the total supply.
     *
     * Emits a {Transfer} event with `from` set to the zero address.
     *
     * Requirements
     *
     * - `to` cannot be the zero address.
     */
    function _mint(address account, uint256 amount) internal {
        require(account != address(0), "ERC20: mint to the zero address");

        _totalSupply = _totalSupply.add(amount);
        _balances[account] = _balances[account].add(amount);
        emit Transfer(address(0), account, amount);
    }

    /**
     * @dev Destroys `amount` tokens from `account`, reducing the
     * total supply.
     *
     * Emits a {Transfer} event with `to` set to the zero address.
     *
     * Requirements
     *
     * - `account` cannot be the zero address.
     * - `account` must have at least `amount` tokens.
     */
    function _burn(address account, uint256 amount) internal {
        require(account != address(0), "ERC20: burn from the zero address");

        _balances[account] = _balances[account].sub(amount, "ERC20: burn amount exceeds balance");
        _totalSupply = _totalSupply.sub(amount);
        emit Transfer(account, address(0), amount);
    }

    /**
     * @dev Sets `amount` as the allowance of `spender` over the `owner`s tokens.
     *
     * This is internal function is equivalent to `approve`, and can be used to
     * e.g. set automatic allowances for certain subsystems, etc.
     *
     * Emits an {Approval} event.
     *
     * Requirements:
     *
     * - `owner` cannot be the zero address.
     * - `spender` cannot be the zero address.
     */
    function _approve(address owner, address spender, uint256 amount) internal {
        require(owner != address(0), "ERC20: approve from the zero address");
        require(spender != address(0), "ERC20: approve to the zero address");

        _allowances[owner][spender] = amount;
        emit Approval(owner, spender, amount);
    }

    /**
     * @dev Destroys `amount` tokens from `account`.`amount` is then deducted
     * from the caller's allowance.
     *
     * See {_burn} and {_approve}.
     */
    function _burnFrom(address account, uint256 amount) internal {
        _burn(account, amount);
        _approve(account, _msgSender(), _allowances[account][_msgSender()].sub(amount, "ERC20: burn amount exceeds allowance"));
    }
}


assessor state as enum

assessor state as enum

pragma solidity ^0.4.0;

import "math.sol";
import "userRegistry.sol";
import "concept.sol";
import "user.sol";
import "conceptRegistry.sol";

contract Assessment
{
  address assessee; //The address of the user being assessed
  address[] assessors;
  address[] finalAssessors; //The assessors who actually give an assessment
  mapping (address => State) assessorState;
  enum State
  {
    Called,
    Confirmed,
    Committed,
    Submitted,
    Done,
    Burned
  }
  address[] assessorPool; //The addresses of the user's that the assessors are randomly selected from
  address concept;
  address userRegistry;
  address conceptRegistry;
  address math = 0x90B66E80448eb60938FAed4A738dE0D5b630B2Fd;
  uint public startTime;
  uint public size;
  uint cost;
  mapping(address => string[]) public data; //IFFS hashes of data that can be passed between the assessors and the assessee for the assessment to occur
  mapping(address => bytes32) commits;
  mapping(address => uint) stake;
  uint done = 0;
  mapping(address => int8) scores; //could save gas by making this an int8
  mapping(int => bool) inRewardCluster;
  int finalScore;
  event DataSet(address _dataSetter, uint _index);

  /*
  @type: modifier
  @name: onlyThis
  @purpose: to only allow the this contract to call a function to which this modifier is applied
  */
  modifier onlyThis()
  {
    if(msg.sender != address(this)) //Checks if msg.sender is this contract
    {
      throw; //Throws out the function call if it isn't
    }
    _;
  }

  /*
  @type: modifier
  @name: onlyAssessorAssessee
  @purpose: to only allow the assessors and assessee to call a function to which this modifier is applied
  */
  modifier onlyAssessorAssessee()
  {
    if(msg.sender != assessee && uint(assessorState[msg.sender]) == 0) //Checks if msg.sender has the same address as either the assessee or an assessor
    {
      throw; //Throws the function call if not
    }
    _;
  }

  /*
  @type: modifier
  @name: onlyConceptAssessment
  @purpose: to only allow the this contract or the Concept contract that spawned it to call a function to which this modifier is applied
  */
  modifier onlyConceptAssessment()
  {
    if(msg.sender != address(this) && msg.sender != concept) //Checks if msg.sender has the same address as this contract or the Concept that spawned it
    {
      throw; //Throws the function call if not
    }
    _;
  }

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

  function Assessment(address _assessee, address _userRegistry, address _conceptRegistry, uint _size, uint _cost)
  {
    assessee = _assessee;
    concept = msg.sender;
    userRegistry = _userRegistry;
    conceptRegistry = _conceptRegistry;
    startTime = block.timestamp;
    size = _size;
    cost = _cost;
    User(assessee).notification(concept, 0); //Assessment made
  }

  function cancelAssessment() onlyConceptAssessment()
  {
    Concept(concept).setBalance(assessee, UserRegistry(userRegistry).getBalance(assessee) + cost*size);
    User(assessee).notification(concept, 3); //Assessment Cancled and you have been refunded
    for(uint i = 0; i < assessors.length; i++)
    {
      Concept(concept).setBalance(assessors[i], UserRegistry(userRegistry).getBalance(assessors[i]) + cost);
      User(assessors[i]).notification(concept, 3); //Assessment Cancled and you have been refunded
    }
    suicide(conceptRegistry);
  }

  function addAssessorToPool(address assessor) onlyConcept() returns(bool)
  {
    if(uint(assessorState[assessor]) == 0)
    {
      User(assessor).notification(concept, 1); //Called As A Potential Assessor
      assessorState[assessor] = State.Called;
      return true;
    }
    else
    {
      return false;
    }
  }

  /*
  @type: function
  @purpose: To recursively set the pool to draw assessors from in the assessment
  @param: uint seed = the seed number for random number generation
  @returns: nothing
  */
  function setAssessorPool(uint seed) onlyConceptAssessment()
  {
    if(Concept(ConceptRegistry(conceptRegistry).mewAddress()).getOwnerLength() < size*20) //Checks if the requested pool size is greater than the number of users in the system
    {
      for(uint i = 0; i < Concept(ConceptRegistry(conceptRegistry).mewAddress()).getOwnerLength(); i++) //If so, all users in the system are added to the pool
      {
        address assessor = Concept(ConceptRegistry(conceptRegistry).mewAddress()).owners(i);
        assessorPool.push(assessor);
        User(assessor).notification(concept, 1); //Called As A Potential Assessor
        assessorState[assessor] = State.Called;
      }
    }
    else
    {
      Concept(concept).getAssessors(size*20, seed, address(this));
    }
  }

  function confirmAssessor()
  {
    if(block.number - startTime <= 15 && assessorState[msg.sender] == State.Called && assessors.length < size && UserRegistry(userRegistry).getBalance(msg.sender) >= cost)
    {
      assessors.push(msg.sender);
      assessorState[msg.sender] = State.Confirmed;
      stake[msg.sender] = cost;
      Concept(concept).setBalance(msg.sender,UserRegistry(userRegistry).getBalance(msg.sender) - cost);
      User(msg.sender).notification(concept, 2); //Confirmed for assessing, stake has been taken
    }
    if(assessors.length == size)
    {
      notifyStart();
    }
    else if(block.number - startTime > 15 && assessors.length < size)
    {
      cancelAssessment();
    }
  }

  function notifyStart() onlyThis()
  {
    for(uint i = 0; i < assessors.length; i++)
    {
      User(assessors[i]).notification(concept, 4); //Assessment Has Started
    }
    User(assessee).notification(concept, 4); //Assessment Has Started
  }

  function setData(string _data) onlyAssessorAssessee()
  {
    data[msg.sender].push(_data);
    DataSet(msg.sender, data[msg.sender].length - 1);
  }

  function commit(bytes32 hash)
  {
    if(done > size/2)
    {
      for(uint i = 0; i < assessors.length; i++)
      {
        if(assessorState[assessors[i]] == State.Confirmed)
        {
          uint r = 38; //Inverse burn rate
          stake[assessors[i]] = cost*2**(-(now-startTime)/r) - 1;
        }
        if(stake[assessors[i]] == 0)
        {
          assessorState[assessors[i]] = State.Burned;
          done++;
        }
      }
    }
    if(done == size)
    {
      for(uint j = 0; j < assessors.length; j++)
      {
        if(assessorState[assessors[j]] == State.Committed)
        {
          User(assessors[j]).notification(concept, 5); //Send in Score
        }
      }
      startTime = block.number;
      done = 0;
    }
    if(assessorState[msg.sender] == State.Confirmed)
    {
      commits[msg.sender] = hash;
      assessorState[msg.sender] == State.Committed;
      done++;
      if(done <= size/2)
      {
        startTime = block.number;
      }
    }
  }

  function reveal(int8 score, bytes16 salt, address assessor)
  {
    if(block.number - startTime <= 10)
    {
      bytes32 hash = sha3(score,salt);
      if(commits[assessor] == hash)
      {
        if(msg.sender == assessor)
        {
          scores[msg.sender] = score;
          assessorState[assessor] = State.Done;
          done++;
        }
        else
        {
          Concept(concept).setBalance(msg.sender,UserRegistry(userRegistry).getBalance(msg.sender) + stake[assessor]);
          stake[assessor] = 0;
          assessorState[assessor] = State.Burned;
        }
      }
      else if(msg.sender == assessor)
      {
        stake[assessor] = 0;
        assessorState[assessor] = State.Burned;
        done++;
      }
    }
    else
    {
      for(uint i = 0; i < assessors.length; i++)
      {
        if(assessorState[assessors[i]] == State.Committed)
        {
          stake[assessors[i]] = 0;
          assessorState[assessors[i]] = State.Burned;
          done++;
        }
      }
    }
    if(done == size)
    {
      calculateResult();
    }
  }

  function calculateResult() onlyThis()
  {
    mapping(uint => int[]) clusters;
    for(uint j = 0; j < size; j++)
    {
      if(assessorState[assessors[i]] == State.Done)
      {
        finalAssessors.push(assessors[i]);
      }
    }
    int[] memory score = new int[] (finalAssessors.length);
    uint largestClusterIndex = 0;
    int averageScore;
    for(uint i = 0; i < finalAssessors.length; i++)
    {
      score[i] = scores[finalAssessors[i]];
    }
    int meanAbsoluteDeviation = Math(math).calculateMAD(score,int(finalAssessors.length));
    for(uint l = 0; l < score.length; l++)
    {
      for(uint m = 0; m < score.length; m++)
      {
        if(score[l] - score[m] <= meanAbsoluteDeviation)
        {
          clusters[l].push(score[m]);
        }
      }
      if(clusters[l].length > clusters[largestClusterIndex].length)
      {
        largestClusterIndex = l;
      }
    }
    for(uint o = 0; o < clusters[largestClusterIndex].length; o++)
    {
      averageScore += clusters[largestClusterIndex][o];
      inRewardCluster[clusters[largestClusterIndex][o]] = true;
    }
    averageScore /= int(clusters[largestClusterIndex].length);
    finalScore = averageScore;
    payout(clusters[largestClusterIndex].length);
  }

  function payout(uint largestSize) onlyThis()
  {
    for(uint i = 0; i < size; i++)
    {
      int score = scores[assessors[i]];
      int scoreDistance = ((score - finalScore)*100)/finalScore;
      if(scoreDistance < 0)
      {
        scoreDistance *= -1;
      }
      uint payoutValue = 1; // TODO Figure out new payout algorithm
      if(inRewardCluster[score] == true)
      {
        uint q = 1; //Inflation rate factor, WE NEED TO FIGURE THIS OUT AT SOME POINT
        payoutValue = q*cost*((100 - uint(scoreDistance))/100);
        Concept(concept).setBalance(assessors[i], UserRegistry(userRegistry).getBalance(assessors[i]) + payoutValue);
        User(assessors[i]).notification(concept, 15); //You Have Received Payment For Your Assessment
      }
      if(inRewardCluster[score] == false)
      {
        payoutValue = stake[assessors[i]]*((200 - uint(scoreDistance))/200);
        Concept(concept).setBalance(assessors[i], UserRegistry(userRegistry).getBalance(assessors[i]) + payoutValue);
        User(assessors[i]).notification(concept, 16); //You Have Received A Fine For Your Assessment
      }
    }
    Concept(concept).finishAssessment(finalScore, assessee, address(this));();
  }

}

pragma solidity ^0.4.0;

import "math.sol";
import "userRegistry.sol";
import "concept.sol";
import "user.sol";
import "conceptRegistry.sol";

contract Assessment
{
  address assessee; //The address of the user being assessed
  address[] assessors;
  address[] finalAssessors; //The assessors who actually give an assessment
  mapping (address => uint) assessorState;
  address[] assessorPool; //The addresses of the user's that the assessors are randomly selected from
  address concept;
  address userRegistry;
  address conceptRegistry;
  address math = 0x90B66E80448eb60938FAed4A738dE0D5b630B2Fd;
  uint public startTime;
  uint public size;
  uint cost;
  mapping(address => string[]) public data; //IFFS hashes of data that can be passed between the assessors and the assessee for the assessment to occur
  mapping(address => bytes32) commits;
  mapping(address => uint) stake;
  uint done = 0;
  mapping(address => int8) scores; //could save gas by making this an int8
  mapping(int => bool) inRewardCluster;
  int finalScore;
  event DataSet(address _dataSetter, uint _index);

  /*
  @type: modifier
  @name: onlyThis
  @purpose: to only allow the this contract to call a function to which this modifier is applied
  */
  modifier onlyThis()
  {
    if(msg.sender != address(this)) //Checks if msg.sender is this contract
    {
      throw; //Throws out the function call if it isn't
    }
    _;
  }

  /*
  @type: modifier
  @name: onlyAssessorAssessee
  @purpose: to only allow the assessors and assessee to call a function to which this modifier is applied
  */
  modifier onlyAssessorAssessee()
  {
    if(msg.sender != assessee && assessorState[msg.sender] == 0) //Checks if msg.sender has the same address as either the assessee or an assessor
    {
      throw; //Throws the function call if not
    }
    _;
  }

  /*
  @type: modifier
  @name: onlyConceptAssessment
  @purpose: to only allow the this contract or the Concept contract that spawned it to call a function to which this modifier is applied
  */
  modifier onlyConceptAssessment()
  {
    if(msg.sender != address(this) && msg.sender != concept) //Checks if msg.sender has the same address as this contract or the Concept that spawned it
    {
      throw; //Throws the function call if not
    }
    _;
  }

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

  function Assessment(address _assessee, address _userRegistry, address _conceptRegistry, uint _size, uint _cost)
  {
    assessee = _assessee;
    concept = msg.sender;
    userRegistry = _userRegistry;
    conceptRegistry = _conceptRegistry;
    startTime = block.timestamp;
    size = _size;
    cost = _cost;
    User(assessee).notification(concept, 0); //Assessment made
  }

  function cancelAssessment() onlyConceptAssessment()
  {
    Concept(concept).setBalance(assessee, UserRegistry(userRegistry).getBalance(assessee) + cost*size);
    User(assessee).notification(concept, 3); //Assessment Cancled and you have been refunded
    for(uint i = 0; i < assessors.length; i++)
    {
      Concept(concept).setBalance(assessors[i], UserRegistry(userRegistry).getBalance(assessors[i]) + cost);
      User(assessors[i]).notification(concept, 3); //Assessment Cancled and you have been refunded
    }
    suicide(conceptRegistry);
  }

  function addAssessorToPool(address assessor) onlyConcept() returns(bool)
  {
    if(assessorState[assessor] == 0)
    {
      User(assessor).notification(concept, 1); //Called As A Potential Assessor
      assessorState[assessor] = 1;
      return true;
    }
    else
    {
      return false;
    }
  }

  /*
  @type: function
  @purpose: To recursively set the pool to draw assessors from in the assessment
  @param: uint seed = the seed number for random number generation
  @returns: nothing
  */
  function setAssessorPool(uint seed) onlyConceptAssessment()
  {
    if(Concept(ConceptRegistry(conceptRegistry).mewAddress()).getOwnerLength() < size*20) //Checks if the requested pool size is greater than the number of users in the system
    {
      for(uint i = 0; i < Concept(ConceptRegistry(conceptRegistry).mewAddress()).getOwnerLength(); i++) //If so, all users in the system are added to the pool
      {
        address assessor = Concept(ConceptRegistry(conceptRegistry).mewAddress()).owners(i);
        assessorPool.push(assessor);
        User(assessor).notification(concept, 1); //Called As A Potential Assessor
        assessorState[assessor] = 1;
      }
    }
    else
    {
      Concept(concept).getAssessors(size*20, seed, address(this));
    }
  }

  function confirmAssessor()
  {
    if(block.number - startTime <= 15 && assessorState[msg.sender] == 1 && assessors.length < size && UserRegistry(userRegistry).getBalance(msg.sender) >= cost)
    {
      assessors.push(msg.sender);
      assessorState[msg.sender] = 2;
      stake[msg.sender] = cost;
      Concept(concept).setBalance(msg.sender,UserRegistry(userRegistry).getBalance(msg.sender) - cost);
      User(msg.sender).notification(concept, 2); //Confirmed for assessing, stake has been taken
    }
    if(assessors.length == size)
    {
      notifyStart();
    }
    else if(block.number - startTime > 15 && assessors.length < size)
    {
      cancelAssessment();
    }
  }

  function notifyStart() onlyThis()
  {
    for(uint i = 0; i < assessors.length; i++)
    {
      User(assessors[i]).notification(concept, 4); //Assessment Has Started
    }
    User(assessee).notification(concept, 4); //Assessment Has Started
  }

  function setData(string _data) onlyAssessorAssessee()
  {
    data[msg.sender].push(_data);
    DataSet(msg.sender, data[msg.sender].length - 1);
  }

  function commit(bytes32 hash)
  {
    if(done > size/2)
    {
      for(uint i = 0; i < assessors.length; i++)
      {
        if(assessorState[assessors[i]] == 2)
        {
          uint r = 38; //Inverse burn rate
          stake[assessors[i]] = cost*2**(-(now-startTime)/r) - 1;
        }
        if(stake[assessors[i]] == 0)
        {
          assessorState[assessors[i]] = 4;
          done++;
        }
      }
    }
    if(done == size)
    {
      for(uint j = 0; j < assessors.length; j++)
      {
        if(assessorState[assessors[j]] == 3)
        {
          User(assessors[j]).notification(concept, 5); //Send in Score
        }
      }
      startTime = block.number;
      done = 0;
    }
    if(assessorState[msg.sender] == 2)
    {
      commits[msg.sender] = hash;
      assessorState[msg.sender] == 3;
      done++;
      if(done <= size/2)
      {
        startTime = block.number;
      }
    }
  }

  function reveal(int8 score, bytes16 salt, address assessor)
  {
    if(block.number - startTime <= 10)
    {
      bytes32 hash = sha3(score,salt);
      if(commits[assessor] == hash)
      {
        if(msg.sender == assessor)
        {
          scores[msg.sender] = score;
          assessorState[assessor] = 5;
          done++;
        }
        else
        {
          Concept(concept).setBalance(msg.sender,UserRegistry(userRegistry).getBalance(msg.sender) + stake[assessor]);
          stake[assessor] = 0;
          assessorState[assessor] = 4;
        }
      }
      else if(msg.sender == assessor)
      {
        stake[assessor] = 0;
        assessorState[assessor] = 4;
        done++;
      }
    }
    else
    {
      for(uint i = 0; i < assessors.length; i++)
      {
        if(assessorState[assessors[i]] == 3)
        {
          stake[assessors[i]] = 0;
          assessorState[assessors[i]] = 4;
          done++;
        }
      }
    }
    if(done == size)
    {
      calculateResult();
    }
  }

  function calculateResult() onlyThis()
  {
    mapping(uint => int[]) clusters;
    for(uint j = 0; j < size; j++)
    {
      if(assessorState[assessors[i]] == 5)
      {
        finalAssessors.push(assessors[i]);
      }
    }
    int[] memory score = new int[] (finalAssessors.length);
    uint largestClusterIndex = 0;
    int averageScore;
    for(uint i = 0; i < finalAssessors.length; i++)
    {
      score[i] = scores[finalAssessors[i]];
    }
    int meanAbsoluteDeviation = Math(math).calculateMAD(score,int(finalAssessors.length));
    for(uint l = 0; l < score.length; l++)
    {
      for(uint m = 0; m < score.length; m++)
      {
        if(score[l] - score[m] <= meanAbsoluteDeviation)
        {
          clusters[l].push(score[m]);
        }
      }
      if(clusters[l].length > clusters[largestClusterIndex].length)
      {
        largestClusterIndex = l;
      }
    }
    for(uint o = 0; o < clusters[largestClusterIndex].length; o++)
    {
      averageScore += clusters[largestClusterIndex][o];
      inRewardCluster[clusters[largestClusterIndex][o]] = true;
    }
    averageScore /= int(clusters[largestClusterIndex].length);
    finalScore = averageScore;
    payout(clusters[largestClusterIndex].length);
  }

  function payout(uint largestSize) onlyThis()
  {
    for(uint i = 0; i < size; i++)
    {
      int score = scores[assessors[i]];
      int scoreDistance = ((score - finalScore)*100)/finalScore;
      if(scoreDistance < 0)
      {
        scoreDistance *= -1;
      }
      uint payoutValue = 1; // TODO Figure out new payout algorithm
      if(inRewardCluster[score] == true)
      {
        uint q = 1; //Inflation rate factor, WE NEED TO FIGURE THIS OUT AT SOME POINT
        payoutValue = q*cost*((100 - uint(scoreDistance))/100);
        Concept(concept).setBalance(assessors[i], UserRegistry(userRegistry).getBalance(assessors[i]) + payoutValue);
        User(assessors[i]).notification(concept, 15); //You Have Received Payment For Your Assessment
      }
      if(inRewardCluster[score] == false)
      {
        payoutValue = stake[assessors[i]]*((200 - uint(scoreDistance))/200);
        Concept(concept).setBalance(assessors[i], UserRegistry(userRegistry).getBalance(assessors[i]) + payoutValue);
        User(assessors[i]).notification(concept, 16); //You Have Received A Fine For Your Assessment
      }
    }
    Concept(concept).finishAssessment(finalScore, assessee, address(this));();
  }

}


Fix bug: an address has been changed wrong before

pragma solidity ^0.4.18;

import "./permission.sol";

/// @title Authorization about the permission and account
/// @notice Only be called by permission_management contract except query interface
contract Authorization {

    address permissionManagementAddr = 0x00000000000000000000000000000000013241b2;
    address newPermissionAddr = 0x00000000000000000000000000000000013241b5;
    address deletePermissionAddr = 0x00000000000000000000000000000000023241b5;
    address updatePermissionAddr = 0x00000000000000000000000000000000033241B5;
    address setAuthAddr = 0x00000000000000000000000000000000043241b5;
    address cancelAuthAddr = 0x00000000000000000000000000000000053241b5;

    mapping(address => address[]) permissions;
    mapping(address => address[]) accounts;

    address[] all_accounts;

    event AuthSetted(address indexed _account, address indexed _permission);
    event AuthCanceled(address indexed _account, address indexed _permission);
    event AuthCleared(address indexed _account);

    modifier onlyPermissionManagement {
        require(permissionManagementAddr == msg.sender);
        _;
    }

    /// @dev Initialize the superAdmin's auth
    function Authorization(address _superAdmin) public {
        // TODO
        _setAuth(_superAdmin, newPermissionAddr);
        _setAuth(_superAdmin, deletePermissionAddr);
        _setAuth(_superAdmin, updatePermissionAddr);
        _setAuth(_superAdmin, setAuthAddr);
        _setAuth(_superAdmin, cancelAuthAddr);
    }

    /// @dev Set authorization
    function setAuth(address _account, address _permission)
        public
        onlyPermissionManagement
        returns (bool)
    {
        return _setAuth(_account, _permission);
    }

    /// @dev Cancel authorization
    function cancelAuth(address _account, address _permission)
        public
        onlyPermissionManagement
        returns (bool)
    {
        addressDelete(_account, accounts[_permission]);
        addressDelete(_permission, permissions[_account]);
        AuthCanceled(_account, _permission);
        return true;
    }

    /// @dev Clear the account's auth
    function clearAuth(address _account)
        public
        onlyPermissionManagement
        returns (bool)
    {
        // Delete the account of all the account's permissions
        for (uint i = 0; i < permissions[_account].length; i++)
            addressDelete(_account, accounts[permissions[_account][i]]);

        delete permissions[_account];
        addressDelete(_account, all_accounts);

        AuthCleared(_account);
        return true;
    }

    /// @dev Clear the auth of the accounts who have the permission
    /// @notice TODO cancelAuthOfPermission
    function clearAuthOfPermission(address _permission)
        public
        onlyPermissionManagement
        returns (bool)
    {
        address[] memory _accounts = queryAccounts(_permission);

        for (uint i = 0; i < _accounts.length; i++)
            assert(cancelAuth(_accounts[i], _permission));

        return true;
    }

    /// @dev Query the account's permissions
    function queryPermissions(address _account)
        public
        view
        returns (address[] _permissions)
    {
        return permissions[_account];
    }

    /// @dev Query the permission's accounts
    function queryAccounts(address _permission)
        public
        view
        returns (address[] _accounts)
    {
        return accounts[_permission];
    }

    /// @dev Query all accounts
    function queryAllAccounts()
        public
        view
        returns (address[])
    {
        return all_accounts;
    }

    /// @dev Check Permission
    function checkPermission(address _account, address _cont, bytes4 _func)
        public
        view
        returns (bool)
    {
        address[] memory perms = queryPermissions(_account);

        for (uint i = 0; i < perms.length; i++) {
            Permission perm = Permission(perms[i]);
            if (perm.inPermission(_cont, _func))
                return true;
        }

        return false;
    }

    /// @dev Delete the value of the address array
    function addressDelete(address _value, address[] storage _array)
        private
        returns (bool)
    {
        var index = addressIndex(_value,  _array);
        // Not found
        if (index >= _array.length)
            return false;

        // Remove the gap
        for (uint i = index; i < _array.length-1; i++)
            _array[i] = _array[i+1];

        // Also delete the last element
        delete _array[_array.length-1];
        _array.length--;
        return true;
    }

    /// @dev Get the index of the value in the bytes32 array
    /// @return The index. If i == length, means not find
    function addressIndex(address _value, address[] _array)
        pure
        private
        returns (uint i)
    {
        // Find the index of the value in the array
        for (i = 0; i < _array.length; i++) {
            if (_value == _array[i])
                return i;
        }
    }

    /// @dev Set authorization
    function _setAuth(address _account, address _permission)
        private
        returns (bool)
    {
        permissions[_account].push(_permission);
        accounts[_permission].push(_account);
        all_accounts.push(_account);
        AuthSetted(_account, _permission);
        return true;
    }
}

pragma solidity ^0.4.18;

import "./permission.sol";

/// @title Authorization about the permission and account
/// @notice Only be called by permission_management contract except query interface
contract Authorization {

    address permissionManagementAddr = 0x00000000000000000000000000000000013241b2;
    address newPermissionAddr = 0x00000000000000000000000000000000013241b5;
    address deletePermissionAddr = 0x00000000000000000000000000000000023241b5;
    address updatePermissionAddr = 0x00000000000000000000000000000000053241b5;
    address setAuthAddr = 0x00000000000000000000000000000000043241b5;
    address cancelAuthAddr = 0x00000000000000000000000000000000053241b5;

    mapping(address => address[]) permissions;
    mapping(address => address[]) accounts;

    address[] all_accounts;

    event AuthSetted(address indexed _account, address indexed _permission);
    event AuthCanceled(address indexed _account, address indexed _permission);
    event AuthCleared(address indexed _account);

    modifier onlyPermissionManagement {
        require(permissionManagementAddr == msg.sender);
        _;
    }

    /// @dev Initialize the superAdmin's auth
    function Authorization(address _superAdmin) public {
        // TODO
        _setAuth(_superAdmin, newPermissionAddr);
        _setAuth(_superAdmin, deletePermissionAddr);
        _setAuth(_superAdmin, updatePermissionAddr);
        _setAuth(_superAdmin, setAuthAddr);
        _setAuth(_superAdmin, cancelAuthAddr);
    }

    /// @dev Set authorization
    function setAuth(address _account, address _permission)
        public
        onlyPermissionManagement
        returns (bool)
    {
        return _setAuth(_account, _permission);
    }

    /// @dev Cancel authorization
    function cancelAuth(address _account, address _permission)
        public
        onlyPermissionManagement
        returns (bool)
    {
        addressDelete(_account, accounts[_permission]);
        addressDelete(_permission, permissions[_account]);
        AuthCanceled(_account, _permission);
        return true;
    }

    /// @dev Clear the account's auth
    function clearAuth(address _account)
        public
        onlyPermissionManagement
        returns (bool)
    {
        // Delete the account of all the account's permissions
        for (uint i = 0; i < permissions[_account].length; i++)
            addressDelete(_account, accounts[permissions[_account][i]]);

        delete permissions[_account];
        addressDelete(_account, all_accounts);

        AuthCleared(_account);
        return true;
    }

    /// @dev Clear the auth of the accounts who have the permission
    /// @notice TODO cancelAuthOfPermission
    function clearAuthOfPermission(address _permission)
        public
        onlyPermissionManagement
        returns (bool)
    {
        address[] memory _accounts = queryAccounts(_permission);

        for (uint i = 0; i < _accounts.length; i++)
            assert(cancelAuth(_accounts[i], _permission));

        return true;
    }

    /// @dev Query the account's permissions
    function queryPermissions(address _account)
        public
        view
        returns (address[] _permissions)
    {
        return permissions[_account];
    }

    /// @dev Query the permission's accounts
    function queryAccounts(address _permission)
        public
        view
        returns (address[] _accounts)
    {
        return accounts[_permission];
    }

    /// @dev Query all accounts
    function queryAllAccounts()
        public
        view
        returns (address[])
    {
        return all_accounts;
    }

    /// @dev Check Permission
    function checkPermission(address _account, address _cont, bytes4 _func)
        public
        view
        returns (bool)
    {
        address[] memory perms = queryPermissions(_account);

        for (uint i = 0; i < perms.length; i++) {
            Permission perm = Permission(perms[i]);
            if (perm.inPermission(_cont, _func))
                return true;
        }

        return false;
    }

    /// @dev Delete the value of the address array
    function addressDelete(address _value, address[] storage _array)
        private
        returns (bool)
    {
        var index = addressIndex(_value,  _array);
        // Not found
        if (index >= _array.length)
            return false;

        // Remove the gap
        for (uint i = index; i < _array.length-1; i++)
            _array[i] = _array[i+1];

        // Also delete the last element
        delete _array[_array.length-1];
        _array.length--;
        return true;
    }

    /// @dev Get the index of the value in the bytes32 array
    /// @return The index. If i == length, means not find
    function addressIndex(address _value, address[] _array)
        pure
        private
        returns (uint i)
    {
        // Find the index of the value in the array
        for (i = 0; i < _array.length; i++) {
            if (_value == _array[i])
                return i;
        }
    }

    /// @dev Set authorization
    function _setAuth(address _account, address _permission)
        private
        returns (bool)
    {
        permissions[_account].push(_permission);
        accounts[_permission].push(_account);
        all_accounts.push(_account);
        AuthSetted(_account, _permission);
        return true;
    }
}


Fixed variable shadowing. (#1310)

Fixed variable shadowing. (#1310)

pragma solidity ^0.4.24;

import "./IERC721.sol";

/**
 * @title ERC-721 Non-Fungible Token Standard, optional metadata extension
 * @dev See https://github.com/ethereum/EIPs/blob/master/EIPS/eip-721.md
 */
contract IERC721Metadata is IERC721 {
  function name() external view returns (string);
  function symbol() external view returns (string);
  function tokenURI(uint256 tokenId) public view returns (string);
}

pragma solidity ^0.4.24;

import "./IERC721.sol";

/**
 * @title ERC-721 Non-Fungible Token Standard, optional metadata extension
 * @dev See https://github.com/ethereum/EIPs/blob/master/EIPS/eip-721.md
 */
contract IERC721Metadata is IERC721 {
  function name() external view returns (string name);
  function symbol() external view returns (string symbol);
  function tokenURI(uint256 tokenId) public view returns (string);
}


Required cheating player to sign both boards

This fixes an exploit where Alice can send a board to Bob. Bob plays and
signs the next board. Then Alice signs a different board that makes it
appear as if Bob is cheating. She can submit this to the blockchain and
falsely accuse Bob of cheating.

import "Rules.sol";
import "TicTacToeAdjudicator.sol";

/* Board state values are as follows:
 *  0 | 1 | 2
 *  ---------
 *  3 | 4 | 5
 *  ---------
 *  6 | 7 | 8
 *
 * 9: 4 if last player was O, 1 if the last player was X
 */
contract TicTacToeRules is Rules {

    event StateSent(bytes state);
    event Cheating(address cheater);
    event BoardWinner(address winner);
    event CheckedIn();

    uint constant BLANK = 0;
    uint constant X = 1;
    uint constant O = 4;

    address addressX;
    address addressO;
    uint timeout;

    /**
     * Creates a new TicTacToeRules
     * _addressX: the address of X
     * _addressO: the address of O
     * _timeout: the timeout before state can be closed
     */
    function TicTacToeRules(address _addressX, address _addressO, uint _timeout) {
        addressX = _addressX;
        addressO = _addressO;
        timeout = _timeout;
    }

    function createAdjudicator() internal returns (Adjudicator newAdjudicator) {
        newAdjudicator = new TicTacToeAdjudicator(addressX, addressO, timeout);
        delete timeout;
    }

    // Converts a grid coordinate to an index value
    function gridToIndex(uint x, uint y) constant internal returns (uint) {
        return x + 3*y;
    }

    /**
     * Send a state directly to the underlying state channel.
     * Allows for transactions to be closed without any adjudication fees.
     *
     * state: the state that will be sent
     * nonce: the nonce that will be sent
     * the rest are signature values for X and O, respectively
     * returns: true if state sent sucessfully, otherwise false
     */
    function sendState(
        bytes state,
        uint nonce,
        uint8 vX,
        bytes32 rX,
        bytes32 sX,
        uint8 vO,
        bytes32 rO,
        bytes32 sO
    ) external returns (bool) {
        uint8[] memory v = new uint8[](2);
        bytes32[] memory r = new bytes32[](2);
        bytes32[] memory s = new bytes32[](2);

        v[0] = vX;
        v[1] = vO;
        r[0] = rX;
        r[1] = rO;
        s[0] = sX;
        s[1] = sO;

        if (adjudicator.close(2, state, nonce, this, v, r, s)) {
            StateSent(state);
            return true;
        } else {
            return false;
        }
    }

    /**
     * Sends a unilateral ruling (0 signatures required) to underlying adjudicator.
     *
     * uintState: the state which will be sent
     * nonce: the nonce which will be sent
     * returns: true if the state was sent successfully, otherwise false
     */
    function unilateralRuling(uint8 uintState, uint nonce) internal returns (bool) {
        bytes memory state = new bytes(1);
        state[0] = byte(uintState);
        adjudicator.close(0, state, nonce, this, new uint8[](1), new bytes32[](1), new bytes32[](1));
    }

    /**
     * Sends a board to be adjudicated upon.
     *
     * board: the board to be adjudicated upon
     * nonce: the nonce that will be used
     * v, r, s: X's signature if last player was X, O's signature if last player was O
     * returns: true if adjudication was sucessful, otherwise false
     */
    function sendBoard(
        bytes10 board,
        uint nonce,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) external returns (bool) {
        uint x;
        uint y;
        uint i;
        uint8 uintState = uint(board[9]) == X ? 0x28 : 0x14;// by default, the person who didn't play will lose all deposits

        if (
            !((uint(board[9]) == X && addressX == ecrecover(sha3(board, nonce, address(this)), v, r, s))
            || (uint(board[9]) == O && addressO == ecrecover(sha3(board, nonce, address(this)), v, r, s)))
        ) {
            return false;
        }

        // do something about what happens if you send old boards???

        // checking wins
        // checking |
        for (x = 0; x < 3; x++) {
            i = 0;
            for (y = 0; y < 3; y++) {
                i += uint(board[gridToIndex(x, y)]);
            }
            if (i == X * 3) {
                if (unilateralRuling(uintState | 0x01, nonce)) {// give X the bet winnings
                    BoardWinner(addressX);
                    return true;
                } else {
                    return false;
                }
            } else if (i == O * 3) {
                if (unilateralRuling(uintState | 0x02, nonce)) {// give O the bet winnings
                    BoardWinner(addressO);
                    return true;
                } else {
                    return false;
                }
            }
        }

        // checking -
        for (y = 0; y < 3; y++) {
            i = 0;
            for (x = 0; x < 3; x++) {
                i += uint(board[gridToIndex(x, y)]);
            }
            if (i == X * 3) {
                if (unilateralRuling(uintState | 0x01, nonce)) {
                    BoardWinner(addressX);
                    return true;
                } else {
                    return false;
                }
            } else if (i == O * 3) {
                if (unilateralRuling(uintState | 0x02, nonce)) {
                    BoardWinner(addressO);
                    return true;
                } else {
                    return false;
                }
            }
        }

        // checking \
        i = 0;
        for (x = 0; x < 3; x++) {
            i += uint(board[gridToIndex(x, x)]);
        }
        if (i == X * 3) {
            if (unilateralRuling(uintState | 0x01, nonce)) {
                BoardWinner(addressX);
                return true;
            } else {
                return false;
            }
        } else if (i == O * 3) {
            if (unilateralRuling(uintState | 0x02, nonce)) {
                BoardWinner(addressO);
                return true;
            } else {
                return false;
            }
        }

        // checking /
        i = 0;
        for (x = 0; x < 3; x++) {
            i += uint(board[gridToIndex(x, 2 - x)]);
        }
        if (i == X * 3) {
            if (unilateralRuling(uintState | 0x01, nonce)) {
                BoardWinner(addressX);
                return true;
            } else {
                return false;
            }
        } else if (i == O * 3) {
            if (unilateralRuling(uintState | 0x02, nonce)) {
                BoardWinner(addressO);
                return true;
            } else {
                return false;
            }
        }

        // check if tie
        for (i = 0; i < 9; i++) {
            if (uint(board[i]) == BLANK) {
                // last player wins
                if (unilateralRuling(uintState | uint(board[9]) == X ? 0x01 : 0x02, nonce)) {// bets sent to last player
                    BoardWinner(uint(board[9]) == X ? addressX : addressO);
                    return true;
                } else {
                    return false;
                }
            }
        }
        // it is a tie
        if (unilateralRuling(uintState, nonce)) {// if tie, bets returned
            BoardWinner(0);
            return true;
        } else {
            return false;
        }
    }

    /**
     * Punishes a sender for sending an errornous board.
     *
     * oldBoard: the old board to be compared against
     * oldNonce: the old nonce to verify the old board
     * oldV, oldR, oldS: the signature for oldBoard, from the last player
     * newBoard: the new board which has an error
     * newNonce: the new nonce of newBoard
     * newV, newR, newS: the signatures for newBoard, from the last player
     */
    function badBoardSent(
        bytes10 oldBoard,
        uint oldNonce,
        uint8 oldV,
        bytes32 oldR,
        bytes32 oldS,
        bytes10 newBoard,
        uint newNonce,
        uint8 newV,
        bytes32 newR,
        bytes32 newS
    ) external returns (bool) {
        address signer = uint(newBoard[9]) == X ? addressX : addressO;
        // verify the integrity of the boards
        if (
            !(signer == ecrecover(sha3(oldBoard, oldNonce, this), oldV, oldR, oldS) &&
            signer == ecrecover(sha3(newBoard, newNonce, this), newV, newR, newS))
        ) {
            return false;
        }

        bool notChanged = true;
        for (uint i = 0; i < 9; i++) {
            if (oldBoard[i] == newBoard[i]) {
                continue;
            }
            if ((uint(newBoard[i]) == X || uint(newBoard[i]) == O) && (uint(oldBoard[i]) == BLANK) && notChanged && (newBoard[i] == newBoard[9])) {
                notChanged = false;
                continue;
            }
            // shenanigans
            if (unilateralRuling(uint(newBoard[9]) == X ? 0x5E : 0x6D, newNonce)) {
                Cheating(uint(newBoard[9]) == X ? addressX : addressO);
                return true;
            } else {
                return false;
            }
        }
        if (notChanged && unilateralRuling(uint(newBoard[9]) == X ? 0x5E : 0x6D, newNonce)) {
            // shenanigans
            Cheating(uint(newBoard[9]) == X ? addressX : addressO);
            return true;
        } else {
            // nothing fishy
            return false;
        }
    }

    /**
     * Lets the contract know that you have not disconnected.
     * Will modify the state such that the disconnect deposits will be
     * refunded and both party's adjudication deposits will be lost.
     *
     * returns: true if sucessful, otherwise false
     */
    function checkIn() external returns (bool) {
        uint8 uintState = uint8(adjudicator.getStateAt(0));

        // does not work if someone has cheated or if adjudicator wasn't used
        if (uintState & 0x40 != 0x00 || uintState & 0x3C == 0x00) {
            return false;
        }
        if (unilateralRuling(uintState & 0xCF | 0x0C, adjudicator.getNonce())) {
            CheckedIn();
            return true;
        } else {
            return false;
        }
    }
}

import "Rules.sol";
import "TicTacToeAdjudicator.sol";

/* Board state values are as follows:
 *  0 | 1 | 2
 *  ---------
 *  3 | 4 | 5
 *  ---------
 *  6 | 7 | 8
 *
 * 9: 4 if last player was O, 1 if the last player was X
 */
contract TicTacToeRules is Rules {

    event StateSent(bytes state);
    event Cheating(address cheater);
    event BoardWinner(address winner);
    event CheckedIn();

    uint constant BLANK = 0;
    uint constant X = 1;
    uint constant O = 4;

    address addressX;
    address addressO;
    uint timeout;

    /**
     * Creates a new TicTacToeRules
     * _addressX: the address of X
     * _addressO: the address of O
     * _timeout: the timeout before state can be closed
     */
    function TicTacToeRules(address _addressX, address _addressO, uint _timeout) {
        addressX = _addressX;
        addressO = _addressO;
        timeout = _timeout;
    }

    function createAdjudicator() internal returns (Adjudicator newAdjudicator) {
        newAdjudicator = new TicTacToeAdjudicator(addressX, addressO, timeout);
        delete timeout;
    }

    // Converts a grid coordinate to an index value
    function gridToIndex(uint x, uint y) constant internal returns (uint) {
        return x + 3*y;
    }

    /**
     * Send a state directly to the underlying state channel.
     * Allows for transactions to be closed without any adjudication fees.
     *
     * state: the state that will be sent
     * nonce: the nonce that will be sent
     * the rest are signature values for X and O, respectively
     * returns: true if state sent sucessfully, otherwise false
     */
    function sendState(
        bytes state,
        uint nonce,
        uint8 vX,
        bytes32 rX,
        bytes32 sX,
        uint8 vO,
        bytes32 rO,
        bytes32 sO
    ) external returns (bool) {
        uint8[] memory v = new uint8[](2);
        bytes32[] memory r = new bytes32[](2);
        bytes32[] memory s = new bytes32[](2);

        v[0] = vX;
        v[1] = vO;
        r[0] = rX;
        r[1] = rO;
        s[0] = sX;
        s[1] = sO;

        if (adjudicator.close(2, state, nonce, this, v, r, s)) {
            StateSent(state);
            return true;
        } else {
            return false;
        }
    }

    /**
     * Sends a unilateral ruling (0 signatures required) to underlying adjudicator.
     *
     * uintState: the state which will be sent
     * nonce: the nonce which will be sent
     * returns: true if the state was sent successfully, otherwise false
     */
    function unilateralRuling(uint8 uintState, uint nonce) internal returns (bool) {
        bytes memory state = new bytes(1);
        state[0] = byte(uintState);
        adjudicator.close(0, state, nonce, this, new uint8[](1), new bytes32[](1), new bytes32[](1));
    }

    /**
     * Sends a board to be adjudicated upon.
     *
     * board: the board to be adjudicated upon
     * nonce: the nonce that will be used
     * v, r, s: X's signature if last player was X, O's signature if last player was O
     * returns: true if adjudication was sucessful, otherwise false
     */
    function sendBoard(
        bytes10 board,
        uint nonce,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) external returns (bool) {
        uint x;
        uint y;
        uint i;
        uint8 uintState = uint(board[9]) == X ? 0x28 : 0x14;// by default, the person who didn't play will lose all deposits

        if (
            !((uint(board[9]) == X && addressX == ecrecover(sha3(board, nonce, address(this)), v, r, s))
            || (uint(board[9]) == O && addressO == ecrecover(sha3(board, nonce, address(this)), v, r, s)))
        ) {
            return false;
        }

        // do something about what happens if you send old boards???

        // checking wins
        // checking |
        for (x = 0; x < 3; x++) {
            i = 0;
            for (y = 0; y < 3; y++) {
                i += uint(board[gridToIndex(x, y)]);
            }
            if (i == X * 3) {
                if (unilateralRuling(uintState | 0x01, nonce)) {// give X the bet winnings
                    BoardWinner(addressX);
                    return true;
                } else {
                    return false;
                }
            } else if (i == O * 3) {
                if (unilateralRuling(uintState | 0x02, nonce)) {// give O the bet winnings
                    BoardWinner(addressO);
                    return true;
                } else {
                    return false;
                }
            }
        }

        // checking -
        for (y = 0; y < 3; y++) {
            i = 0;
            for (x = 0; x < 3; x++) {
                i += uint(board[gridToIndex(x, y)]);
            }
            if (i == X * 3) {
                if (unilateralRuling(uintState | 0x01, nonce)) {
                    BoardWinner(addressX);
                    return true;
                } else {
                    return false;
                }
            } else if (i == O * 3) {
                if (unilateralRuling(uintState | 0x02, nonce)) {
                    BoardWinner(addressO);
                    return true;
                } else {
                    return false;
                }
            }
        }

        // checking \
        i = 0;
        for (x = 0; x < 3; x++) {
            i += uint(board[gridToIndex(x, x)]);
        }
        if (i == X * 3) {
            if (unilateralRuling(uintState | 0x01, nonce)) {
                BoardWinner(addressX);
                return true;
            } else {
                return false;
            }
        } else if (i == O * 3) {
            if (unilateralRuling(uintState | 0x02, nonce)) {
                BoardWinner(addressO);
                return true;
            } else {
                return false;
            }
        }

        // checking /
        i = 0;
        for (x = 0; x < 3; x++) {
            i += uint(board[gridToIndex(x, 2 - x)]);
        }
        if (i == X * 3) {
            if (unilateralRuling(uintState | 0x01, nonce)) {
                BoardWinner(addressX);
                return true;
            } else {
                return false;
            }
        } else if (i == O * 3) {
            if (unilateralRuling(uintState | 0x02, nonce)) {
                BoardWinner(addressO);
                return true;
            } else {
                return false;
            }
        }

        // check if tie
        for (i = 0; i < 9; i++) {
            if (uint(board[i]) == BLANK) {
                // last player wins
                if (unilateralRuling(uintState | uint(board[9]) == X ? 0x01 : 0x02, nonce)) {// bets sent to last player
                    BoardWinner(uint(board[9]) == X ? addressX : addressO);
                    return true;
                } else {
                    return false;
                }
            }
        }
        // it is a tie
        if (unilateralRuling(uintState, nonce)) {// if tie, bets returned
            BoardWinner(0);
            return true;
        } else {
            return false;
        }
    }

    /**
     * Punishes a sender for sending an errornous board.
     *
     * oldBoard: the old board to be compared against
     * oldNonce: the old nonce to verify the old board
     * oldV, oldR, oldS: the signature for oldBoard, from the last player
     * newBoard: the new board which has an error
     * newNonce: the new nonce of newBoard
     * newV, newR, newS: the signatures for newBoard, from the last player
     */
    function badBoardSent(
        bytes10 oldBoard,
        uint oldNonce,
        uint8 oldV,
        bytes32 oldR,
        bytes32 oldS,
        bytes10 newBoard,
        uint newNonce,
        uint8 newV,
        bytes32 newR,
        bytes32 newS
    ) external returns (bool) {
        // verify the integrity of oldBoard
        if (
            !((uint(oldBoard[9]) == X && addressX == ecrecover(sha3(oldBoard, oldNonce, this), oldV, oldR, oldS))
            || (uint(oldBoard[9]) == O && addressO == ecrecover(sha3(oldBoard, oldNonce, this), oldV, oldR, oldS)))
        ) {
            return false;
        }

        // verify the integrity of newBoard
        if (
            !((uint(newBoard[9]) == X && addressX == ecrecover(sha3(newBoard, newNonce, this), newV, newR, newS))
            || (uint(newBoard[9]) == O && addressO == ecrecover(sha3(newBoard, newNonce, this), newV, newR, newS)))
        ) {
            return false;
        }

        bool notChanged = true;
        for (uint i = 0; i < 9; i++) {
            if (oldBoard[i] == newBoard[i]) {
                continue;
            }
            if ((uint(newBoard[i]) == X || uint(newBoard[i]) == O) && (uint(oldBoard[i]) == BLANK) && notChanged && (newBoard[i] == newBoard[9])) {
                notChanged = false;
                continue;
            }
            // shenanigans
            if (unilateralRuling(uint(newBoard[9]) == X ? 0x5E : 0x6D, newNonce)) {
                Cheating(uint(newBoard[9]) == X ? addressX : addressO);
                return true;
            } else {
                return false;
            }
        }
        if (notChanged && unilateralRuling(uint(newBoard[9]) == X ? 0x5E : 0x6D, newNonce)) {
            // shenanigans
            Cheating(uint(newBoard[9]) == X ? addressX : addressO);
            return true;
        } else {
            // nothing fishy
            return false;
        }
    }

    /**
     * Lets the contract know that you have not disconnected.
     * Will modify the state such that the disconnect deposits will be
     * refunded and both party's adjudication deposits will be lost.
     *
     * returns: true if sucessful, otherwise false
     */
    function checkIn() external returns (bool) {
        uint8 uintState = uint8(adjudicator.getStateAt(0));

        // does not work if someone has cheated or if adjudicator wasn't used
        if (uintState & 0x40 != 0x00 || uintState & 0x3C == 0x00) {
            return false;
        }
        if (unilateralRuling(uintState & 0xCF | 0x0C, adjudicator.getNonce())) {
            CheckedIn();
            return true;
        } else {
            return false;
        }
    }
}


finalize advisor and team token allocations

pragma solidity ^0.4.15;
import './ERC20Token.sol';
import './TokenHolder.sol';

contract ENJToken is ERC20Token, TokenHolder {

///////////////////////////////////////// VARIABLE INITIALIZATION /////////////////////////////////////////

    uint256 constant public ENJ_UNIT = 10 ** 18;
    uint256 public totalSupply = 1 * (10**9) * ENJ_UNIT;

    //  Constants
    uint256 constant public maxPresaleSupply = 600 * 10**6 * ENJ_UNIT;           // Total presale supply at max bonus
    uint256 constant public minCrowdsaleAllocation = 200 * 10**6 * ENJ_UNIT;     // Min amount for crowdsale
    uint256 constant public incentivisationAllocation = 100 * 10**6 * ENJ_UNIT;  // Incentivisation Allocation
    uint256 constant public advisorsAllocation = 26 * 10**6 * ENJ_UNIT;          // Advisors Allocation
    uint256 constant public enjinTeamAllocation = 74 * 10**6 * ENJ_UNIT;         // Enjin Team allocation

    address public crowdFundAddress;                                             // Address of the crowdfund
    address public advisorAddress;                                               // Enjin advisor's address
    address public incentivisationFundAddress;                                   // Address that holds the incentivization funds
    address public enjinTeamAddress;                                             // Enjin Team address

    //  Variables

    uint256 public totalAllocatedToAdvisors = 0;                                 // Counter to keep track of advisor token allocation
    uint256 public totalAllocatedToTeam = 0;                                     // Counter to keep track of team token allocation
    uint256 public totalAllocated = 0;                                           // Counter to keep track of overall token allocation
    uint256 constant public endTime = 1509494340;                                // 10/31/2017 @ 11:59pm (UTC) crowdsale end time (in seconds)

    bool internal isReleasedToPublic = false;                         // Flag to allow transfer/transferFrom before the end of the crowdfund

    uint256 internal teamTranchesReleased = 0;                          // Track how many tranches (allocations of 12.5% team tokens) have been released
    uint256 internal maxTeamTranches = 8;                               // The number of tranches allowed to the team until depleted

///////////////////////////////////////// MODIFIERS /////////////////////////////////////////

    // Enjin Team timelock
    modifier safeTimelock() {
        require(now >= endTime + 6 * 4 weeks);
        _;
    }

    // Advisor Team timelock
    modifier advisorTimelock() {
        require(now >= endTime + 2 * 4 weeks);
        _;
    }

    // Function only accessible by the Crowdfund contract
    modifier crowdfundOnly() {
        require(msg.sender == crowdFundAddress);
        _;
    }

    ///////////////////////////////////////// CONSTRUCTOR /////////////////////////////////////////

    /**
        @dev constructor
        @param _crowdFundAddress   Crowdfund address
        @param _advisorAddress     Advisor address
    */
    function ENJToken(address _crowdFundAddress, address _advisorAddress, address _incentivisationFundAddress, address _enjinTeamAddress)
    ERC20Token("Enjin Coin", "ENJ", 18)
     {
        crowdFundAddress = _crowdFundAddress;
        advisorAddress = _advisorAddress;
        enjinTeamAddress = _enjinTeamAddress;
        incentivisationFundAddress = _incentivisationFundAddress;
        balanceOf[_crowdFundAddress] = minCrowdsaleAllocation + maxPresaleSupply; // Total presale + crowdfund tokens
        balanceOf[_incentivisationFundAddress] = incentivisationAllocation;       // 10% Allocated for Marketing and Incentivisation
        totalAllocated += incentivisationAllocation;                              // Add to total Allocated funds
    }

///////////////////////////////////////// ERC20 OVERRIDE /////////////////////////////////////////

    /**
        @dev send coins
        throws on any error rather then return a false flag to minimize user errors
        in addition to the standard checks, the function throws if transfers are disabled

        @param _to      target address
        @param _value   transfer amount

        @return true if the transfer was successful, throws if it wasn't
    */
    function transfer(address _to, uint256 _value) public returns (bool success) {
        if (isTransferAllowed() == true || msg.sender == crowdFundAddress || msg.sender == incentivisationFundAddress) {
            assert(super.transfer(_to, _value));
            return true;
        }
        revert();
    }

    /**
        @dev an account/contract attempts to get the coins
        throws on any error rather then return a false flag to minimize user errors
        in addition to the standard checks, the function throws if transfers are disabled

        @param _from    source address
        @param _to      target address
        @param _value   transfer amount

        @return true if the transfer was successful, throws if it wasn't
    */
    function transferFrom(address _from, address _to, uint256 _value) public returns (bool success) {
        if (isTransferAllowed() == true || msg.sender == crowdFundAddress || msg.sender == incentivisationFundAddress) {
            assert(super.transferFrom(_from, _to, _value));
            return true;
        }
        revert();
    }

///////////////////////////////////////// ALLOCATION FUNCTIONS /////////////////////////////////////////

    /**
        @dev Release one single tranche of the Enjin Team Token allocation
        throws if before timelock (6 months) ends and if not initiated by the owner of the contract
        returns true if valid
        Schedule goes as follows:
        3 months: 12.5% (this tranche can only be released after the initial 6 months has passed)
        6 months: 12.5%
        9 months: 12.5%
        12 months: 12.5%
        15 months: 12.5%
        18 months: 12.5%
        21 months: 12.5%
        24 months: 12.5%
        @return true if successful, throws if not
    */
    function releaseEnjinTeamTokens() safeTimelock ownerOnly returns(bool success) {
        require(totalAllocatedToTeam < enjinTeamAllocation);

        uint256 enjinTeamAlloc = enjinTeamAllocation / 1000;
        uint256 currentTranche = uint256(now - endTime) / 12 weeks;     // "months" after crowdsale end time (division floored)

        if(teamTranchesReleased < maxTeamTranches && currentTranche > teamTranchesReleased) {
            teamTranchesReleased++;

            uint256 amount = safeMul(enjinTeamAlloc, 125);
            balanceOf[enjinTeamAddress] = safeAdd(balanceOf[enjinTeamAddress], amount);
            Transfer(0x0, enjinTeamAddress, amount);
            totalAllocated = safeAdd(totalAllocated, amount);
            totalAllocatedToTeam = safeAdd(totalAllocatedToTeam, amount);
            return true;
        }
        revert();
    }

    /**
        @dev release Advisors Token allocation
        throws if before timelock (2 months) ends or if no initiated by the advisors address
        or if there is no more allocation to give out
        returns true if valid

        @return true if successful, throws if not
    */
    function releaseAdvisorTokens() advisorTimelock ownerOnly returns(bool success) {
        require(totalAllocatedToAdvisors == 0);
        balanceOf[advisorAddress] = safeAdd(balanceOf[advisorAddress], advisorsAllocation);
        totalAllocated = safeAdd(totalAllocated, advisorsAllocation);
        totalAllocatedToAdvisors = advisorsAllocation;
        Transfer(0x0, advisorAddress, advisorsAllocation);
        return true;
    }

    /**
        @dev Retrieve unsold tokens from the crowdfund
        throws if before timelock (6 months from end of Crowdfund) ends and if no initiated by the owner of the contract
        returns true if valid

        @return true if successful, throws if not
    */
    function retrieveUnsoldTokens() safeTimelock ownerOnly returns(bool success) {
        uint256 amountOfTokens = balanceOf[crowdFundAddress];
        balanceOf[crowdFundAddress] = 0;
        balanceOf[incentivisationFundAddress] = safeAdd(balanceOf[incentivisationFundAddress], amountOfTokens);
        totalAllocated = safeAdd(totalAllocated, amountOfTokens);
        Transfer(crowdFundAddress, incentivisationFundAddress, amountOfTokens);
        return true;
    }

    /**
        @dev Keep track of token allocations
        can only be called by the crowdfund contract
    */
    function addToAllocation(uint256 _amount) crowdfundOnly {
        totalAllocated = safeAdd(totalAllocated, _amount);
    }

    /**
        @dev Function to allow transfers
        can only be called by the owner of the contract
        Transfers will be allowed regardless after the crowdfund end time.
    */
    function allowTransfers() ownerOnly {
        isReleasedToPublic = true;
    }

    /**
        @dev User transfers are allowed/rejected
        Transfers are forbidden before the end of the crowdfund
    */
    function isTransferAllowed() internal constant returns(bool) {
        if (now > endTime || isReleasedToPublic == true) {
            return true;
        }
        return false;
    }
}

pragma solidity ^0.4.15;
import './ERC20Token.sol';
import './TokenHolder.sol';

contract ENJToken is ERC20Token, TokenHolder {

///////////////////////////////////////// VARIABLE INITIALIZATION /////////////////////////////////////////

    uint256 constant public ENJ_UNIT = 10 ** 18;
    uint256 public totalSupply = 1 * (10**9) * ENJ_UNIT;

    //  Constants
    uint256 constant public maxPresaleSupply = 600 * 10**6 * ENJ_UNIT;           // Total presale supply at max bonus
    uint256 constant public minCrowdsaleAllocation = 200 * 10**6 * ENJ_UNIT;     // Min amount for crowdsale
    uint256 constant public incentivisationAllocation = 100 * 10**6 * ENJ_UNIT;  // Incentivisation Allocation
    uint256 constant public advisorsAllocation = 50 * 10**6 * ENJ_UNIT;          // Advisors Allocation
    uint256 constant public enjinTeamAllocation = 50 * 10**6 * ENJ_UNIT;         // Enjin Team allocation

    address public crowdFundAddress;                                             // Address of the crowdfund
    address public advisorAddress;                                               // Enjin advisor's address
    address public incentivisationFundAddress;                                   // Address that holds the incentivization funds
    address public enjinTeamAddress;                                             // Enjin Team address

    //  Variables

    uint256 public totalAllocatedToAdvisors = 0;                                 // Counter to keep track of advisor token allocation
    uint256 public totalAllocatedToTeam = 0;                                     // Counter to keep track of team token allocation
    uint256 public totalAllocated = 0;                                           // Counter to keep track of overall token allocation
    uint256 constant public endTime = 1509494340;                                // 10/31/2017 @ 11:59pm (UTC) crowdsale end time (in seconds)

    bool internal isReleasedToPublic = false;                         // Flag to allow transfer/transferFrom before the end of the crowdfund

    uint256 internal teamTranchesReleased = 0;                          // Track how many tranches (allocations of 12.5% team tokens) have been released
    uint256 internal maxTeamTranches = 8;                               // The number of tranches allowed to the team until depleted

///////////////////////////////////////// MODIFIERS /////////////////////////////////////////

    // Enjin Team timelock
    modifier safeTimelock() {
        require(now >= endTime + 6 * 4 weeks);
        _;
    }

    // Advisor Team timelock
    modifier advisorTimelock() {
        require(now >= endTime + 2 * 4 weeks);
        _;
    }

    // Function only accessible by the Crowdfund contract
    modifier crowdfundOnly() {
        require(msg.sender == crowdFundAddress);
        _;
    }

    ///////////////////////////////////////// CONSTRUCTOR /////////////////////////////////////////

    /**
        @dev constructor
        @param _crowdFundAddress   Crowdfund address
        @param _advisorAddress     Advisor address
    */
    function ENJToken(address _crowdFundAddress, address _advisorAddress, address _incentivisationFundAddress, address _enjinTeamAddress)
    ERC20Token("Enjin Coin", "ENJ", 18)
     {
        crowdFundAddress = _crowdFundAddress;
        advisorAddress = _advisorAddress;
        enjinTeamAddress = _enjinTeamAddress;
        incentivisationFundAddress = _incentivisationFundAddress;
        balanceOf[_crowdFundAddress] = minCrowdsaleAllocation + maxPresaleSupply; // Total presale + crowdfund tokens
        balanceOf[_incentivisationFundAddress] = incentivisationAllocation;       // 10% Allocated for Marketing and Incentivisation
        totalAllocated += incentivisationAllocation;                              // Add to total Allocated funds
    }

///////////////////////////////////////// ERC20 OVERRIDE /////////////////////////////////////////

    /**
        @dev send coins
        throws on any error rather then return a false flag to minimize user errors
        in addition to the standard checks, the function throws if transfers are disabled

        @param _to      target address
        @param _value   transfer amount

        @return true if the transfer was successful, throws if it wasn't
    */
    function transfer(address _to, uint256 _value) public returns (bool success) {
        if (isTransferAllowed() == true || msg.sender == crowdFundAddress || msg.sender == incentivisationFundAddress) {
            assert(super.transfer(_to, _value));
            return true;
        }
        revert();
    }

    /**
        @dev an account/contract attempts to get the coins
        throws on any error rather then return a false flag to minimize user errors
        in addition to the standard checks, the function throws if transfers are disabled

        @param _from    source address
        @param _to      target address
        @param _value   transfer amount

        @return true if the transfer was successful, throws if it wasn't
    */
    function transferFrom(address _from, address _to, uint256 _value) public returns (bool success) {
        if (isTransferAllowed() == true || msg.sender == crowdFundAddress || msg.sender == incentivisationFundAddress) {
            assert(super.transferFrom(_from, _to, _value));
            return true;
        }
        revert();
    }

///////////////////////////////////////// ALLOCATION FUNCTIONS /////////////////////////////////////////

    /**
        @dev Release one single tranche of the Enjin Team Token allocation
        throws if before timelock (6 months) ends and if not initiated by the owner of the contract
        returns true if valid
        Schedule goes as follows:
        3 months: 12.5% (this tranche can only be released after the initial 6 months has passed)
        6 months: 12.5%
        9 months: 12.5%
        12 months: 12.5%
        15 months: 12.5%
        18 months: 12.5%
        21 months: 12.5%
        24 months: 12.5%
        @return true if successful, throws if not
    */
    function releaseEnjinTeamTokens() safeTimelock ownerOnly returns(bool success) {
        require(totalAllocatedToTeam < enjinTeamAllocation);

        uint256 enjinTeamAlloc = enjinTeamAllocation / 1000;
        uint256 currentTranche = uint256(now - endTime) / 12 weeks;     // "months" after crowdsale end time (division floored)

        if(teamTranchesReleased < maxTeamTranches && currentTranche > teamTranchesReleased) {
            teamTranchesReleased++;

            uint256 amount = safeMul(enjinTeamAlloc, 125);
            balanceOf[enjinTeamAddress] = safeAdd(balanceOf[enjinTeamAddress], amount);
            Transfer(0x0, enjinTeamAddress, amount);
            totalAllocated = safeAdd(totalAllocated, amount);
            totalAllocatedToTeam = safeAdd(totalAllocatedToTeam, amount);
            return true;
        }
        revert();
    }

    /**
        @dev release Advisors Token allocation
        throws if before timelock (2 months) ends or if no initiated by the advisors address
        or if there is no more allocation to give out
        returns true if valid

        @return true if successful, throws if not
    */
    function releaseAdvisorTokens() advisorTimelock ownerOnly returns(bool success) {
        require(totalAllocatedToAdvisors == 0);
        balanceOf[advisorAddress] = safeAdd(balanceOf[advisorAddress], advisorsAllocation);
        totalAllocated = safeAdd(totalAllocated, advisorsAllocation);
        totalAllocatedToAdvisors = advisorsAllocation;
        Transfer(0x0, advisorAddress, advisorsAllocation);
        return true;
    }

    /**
        @dev Retrieve unsold tokens from the crowdfund
        throws if before timelock (6 months from end of Crowdfund) ends and if no initiated by the owner of the contract
        returns true if valid

        @return true if successful, throws if not
    */
    function retrieveUnsoldTokens() safeTimelock ownerOnly returns(bool success) {
        uint256 amountOfTokens = balanceOf[crowdFundAddress];
        balanceOf[crowdFundAddress] = 0;
        balanceOf[incentivisationFundAddress] = safeAdd(balanceOf[incentivisationFundAddress], amountOfTokens);
        totalAllocated = safeAdd(totalAllocated, amountOfTokens);
        Transfer(crowdFundAddress, incentivisationFundAddress, amountOfTokens);
        return true;
    }

    /**
        @dev Keep track of token allocations
        can only be called by the crowdfund contract
    */
    function addToAllocation(uint256 _amount) crowdfundOnly {
        totalAllocated = safeAdd(totalAllocated, _amount);
    }

    /**
        @dev Function to allow transfers
        can only be called by the owner of the contract
        Transfers will be allowed regardless after the crowdfund end time.
    */
    function allowTransfers() ownerOnly {
        isReleasedToPublic = true;
    }

    /**
        @dev User transfers are allowed/rejected
        Transfers are forbidden before the end of the crowdfund
    */
    function isTransferAllowed() internal constant returns(bool) {
        if (now > endTime || isReleasedToPublic == true) {
            return true;
        }
        return false;
    }
}


Add create payroll event when creating the SpiceHours contract.

pragma solidity ^0.4.2;

import "SpiceControlled.sol";
import "SpicePayroll.sol";

contract SpiceHours is SpiceControlled {
    address[] public payrolls;

    event MarkHours(bytes32 indexed info, bytes32 indexed description, int duration, bool success);
    event ProcessPayroll(address indexed payroll, uint maxDuration);
    event CreatePayroll(address indexed payroll);

    function SpiceHours(address _members) SpiceControlled(_members) {
        payrolls[payrolls.length++] = new SpicePayroll(members);
        CreatePayroll(payrolls[payrolls.length-1]);
    }

    function markHours(bytes32 _info, bytes32 _description, int _duration) onlyMember {
        if (!hasManagerAccess(msg.sender) && members.memberInfo(msg.sender) != _info) throw;

        SpicePayroll payroll = SpicePayroll(payrolls[payrolls.length-1]);
        bool success = payroll.addMarking(_info, _description, _duration);
        MarkHours(_info, _description, _duration, success);
    }

    function processPayroll(address _calculator, uint _maxDuration) onlyDirector {
        SpicePayroll payroll = SpicePayroll(payrolls[payrolls.length-1]);
        payroll.processMarkings(_calculator, _maxDuration);
        ProcessPayroll(payroll, _maxDuration);

        payrolls[payrolls.length++] = new SpicePayroll(members);
        CreatePayroll(payrolls[payrolls.length-1]);
    }

    function hasPayroll(address _address) constant returns (bool) {
        for (uint i; i < payrolls.length; i++) {
            if (payrolls[i] == _address) return true;
        }
        return false;
    }

    function payrollCount() constant returns (uint) {
        return payrolls.length;
    }
}

pragma solidity ^0.4.2;

import "SpiceControlled.sol";
import "SpicePayroll.sol";

contract SpiceHours is SpiceControlled {
    address[] public payrolls;

    event MarkHours(bytes32 indexed info, bytes32 indexed description, int duration, bool success);
    event ProcessPayroll(address indexed payroll, uint maxDuration);
    event CreatePayroll(address indexed payroll);

    function SpiceHours(address _members) SpiceControlled(_members) {
        payrolls[payrolls.length++] = new SpicePayroll(members);
    }

    function markHours(bytes32 _info, bytes32 _description, int _duration) onlyMember {
        if (!hasManagerAccess(msg.sender) && members.memberInfo(msg.sender) != _info) throw;

        SpicePayroll payroll = SpicePayroll(payrolls[payrolls.length-1]);
        bool success = payroll.addMarking(_info, _description, _duration);
        MarkHours(_info, _description, _duration, success);
    }

    function processPayroll(address _calculator, uint _maxDuration) onlyDirector {
        SpicePayroll payroll = SpicePayroll(payrolls[payrolls.length-1]);
        payroll.processMarkings(_calculator, _maxDuration);
        ProcessPayroll(payroll, _maxDuration);

        payrolls[payrolls.length++] = new SpicePayroll(members);
        CreatePayroll(payrolls[payrolls.length-1]);
    }

    function hasPayroll(address _address) constant returns (bool) {
        for (uint i; i < payrolls.length; i++) {
            if (payrolls[i] == _address) return true;
        }
        return false;
    }

    function payrollCount() constant returns (uint) {
        return payrolls.length;
    }
}