refactored payoutFunction

refactored payoutFunction

pragma solidity ^0.4.0;

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

contract Assessment {
    address assessee;
    address[] assessors;
    address[] finalAssessors;
    mapping (address => State) assessorState;
    mapping(uint => int[]) clusters;
    State public assessmentStage;
    enum State {
        None,
        Called,
        Confirmed,
        Committed,
        Done,
        Burned
    }

    uint public assessorPoolLength;
    address concept;
    address userRegistry;
    address conceptRegistry;
    uint public checkpoint; //marks creation of assessment / start of commit phase / start of reveal phase (time in seconds)
    uint burnRate;
    uint public size;
    uint cost;
    mapping(address => string[]) public data;
    mapping(address => bytes32) commits;
    mapping(address => uint) stake;
    uint public done; //counter how many assessors have committed/revealed their score
    mapping(address => int8) scores;
    mapping(int => bool) inRewardCluster;
    int public finalScore;
    event DataSet(address _dataSetter, uint _index);

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

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

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

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

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

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

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

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

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

    //@purpose: called by an assessor to confirm and stake
    function confirmAssessor() onlyInStage(State.Called) {
        // cancel if the assessment is older than 12 hours
        if (now - checkpoint > 12 hours) {
            this.cancelAssessment();
            return;
        }
        if (assessorState[msg.sender] == State.Called &&
            assessors.length < size &&
            Concept(concept).subtractBalance(msg.sender, cost)
            ) {
            assessors.push(msg.sender);
            assessorState[msg.sender] = State.Confirmed;
            stake[msg.sender] = cost;
            UserRegistry(userRegistry).notification(msg.sender, 2); //Confirmed for assessing, stake has been taken
        }
        if (assessors.length == size) {
            notifyAssessors(uint(State.Confirmed), 4);
            checkpoint = now; // reset checkpoint to mark start of actual assessment phase
            UserRegistry(userRegistry).notification(assessee, 4);
            assessmentStage = State.Confirmed;
        }
    }

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

    //@purpose: called by an assessor to commit a hash of their score //TODO explain in more detail what's happening
    function commit(bytes32 _hash) onlyInStage(State.Confirmed) {
        if (done > size/2) {
            burnStakes();
        }

        if (assessorState[msg.sender] == State.Confirmed)
            {
                commits[msg.sender] = _hash;
                assessorState[msg.sender] = State.Committed;
                done++; //Increases done by 1 to help progress to the next assessment stage.

                // if the boundary assessor
                if ( done*10 >= 10*size/2 &&
                    (done - 1)*10 < 10*size/2) {
                    burnRate = (cost / (now - checkpoint)) + 1;
                    checkpoint = now + (now - checkpoint);
                }
            }
        if (done == size) {
            notifyAssessors(uint(State.Committed), 5);
            checkpoint = now; //reset checkpoint to mark start of reveal phase
            done = 0; //Resets the done counter
            assessmentStage = State.Committed;
        }

    }

    //@purpose: called by assessors to reveal their own commits or others
    function reveal(int8 score, string salt, address assessor) onlyInStage(State.Committed) {
        if (now - checkpoint > 12 hours) {
            for (uint i = 0; i < assessors.length; i++) {
                if (assessorState[assessors[i]] == State.Committed) { //If the assessor has not revealed their score
                    stake[assessors[i]] = 0;
                    assessorState[assessors[i]] = State.Burned;
                    size--;
                }
            }
            return;
        }

        bytes32 hash = sha3(score,salt);
        if (assessorState[assessor] == State.Committed) {
            if (commits[assessor] == hash) {
                // log in score and increase done
                if (msg.sender == assessor) {
                    scores[msg.sender] = score;
                    assessorState[assessor] = State.Done;
                    done++;
                }
                else {
                    // give the stake to the caller and burn assessor
                    Concept(concept).addBalance(msg.sender, stake[assessor]);
                    stake[assessor] = 0;
                    assessorState[assessor] = State.Burned;
                    size--;
                }
            }
        }

        //If all the assessors have revealed their scored or burned their stakes
        if (done == size) {
            assessmentStage = State.Done;
            calculateResult(); //The final result is calculated
        }
    }

    //@purpose: burns stakes as a function of how much time has passed since half of the assessors commited
    function burnStakes() internal {
        if (now-checkpoint > now) { //-> underflows if now before the end of the grace period
            return;
        }
        for (uint i = 0; i < assessors.length; i++) {
            if (assessorState[assessors[i]] == State.Confirmed) {
                stake[assessors[i]] = cost - (burnRate * (now - checkpoint));
                if (stake[assessors[i]] == 0 ||
                    stake[assessors[i]] > cost) {
                    assessorState[assessors[i]] = State.Burned;
                    stake[assessors[i]] = 0;
                    size--; //decrease size to help progress to the next assessment stage
                }
            }
        }
    }

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

    function calculateResult() onlyInStage(State.Done) private {
        for (uint j = 0; j < assessors.length; j++) {
            if (assessorState[assessors[j]] == State.Done) {
                finalAssessors.push(assessors[j]); //Adds all the assessors that completed the assessment process to an array}
            }
        }
        int[] memory score = new int[] (finalAssessors.length); //Initializes an array to store scores that is the same length as the number of finalAssessors
        uint largestClusterIndex = 0; //store the index of the largest cluster
        int averageScore;
        for (uint i = 0; i < finalAssessors.length; i++) {
            score[i] = scores[finalAssessors[i]];
        }
        int meanAbsoluteDeviation = 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; //Sets the final score to the average score
        payout();
        //Sends assessment info to the concept so that it can update its records
        Concept(concept).finishAssessment(finalScore, assessee, address(this));
    }

    function payout() onlyInStage(State.Done) private { //TODO order functions according to styleguide
        for (uint i = 0; i < assessors.length; i++) {
            if (assessorState[assessors[i]] == State.Done) {
                int score = scores[assessors[i]];
                int scoreDistance = ((score - finalScore)*100)/finalScore;
                if (scoreDistance < 0) {
                    scoreDistance *= -1;
                }
                uint payoutValue = 0; //Initializes the payoutValue for the assessor
                if (inRewardCluster[score]) {
                    uint q = 1; //Inflation rate factor, WE NEED TO FIGURE THIS OUT AT SOME POINT
                    //The assessor's payout is their stake plus some constant times a proportion of the user's tokens determined by their distance to the final score
                    payoutValue = (q*cost*((100 - uint(scoreDistance))/100)) + stake[assessors[i]];
                }
                else {
                    //The assessor's payout will be a propotion of their remaining stake determined by their distance from the final score
                    payoutValue = stake[assessors[i]]*((200 - uint(scoreDistance))/200);
                }
                Concept(concept).addBalance(assessors[i], payoutValue);
                UserRegistry(userRegistry).notification(assessors[i], 6); //You  got paid!
            }
        }
    }
}

pragma solidity ^0.4.0;

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

contract Assessment {
    address assessee;
    address[] assessors;
    address[] finalAssessors;
    mapping (address => State) assessorState;
    mapping(uint => int[]) clusters;
    State public assessmentStage;
    enum State {
        None,
        Called,
        Confirmed,
        Committed,
        Done,
        Burned
    }

    uint public assessorPoolLength;
    address concept;
    address userRegistry;
    address conceptRegistry;
    uint public checkpoint; //marks creation of assessment / start of commit phase / start of reveal phase (time in seconds)
    uint burnRate;
    uint public size;
    uint cost;
    mapping(address => string[]) public data;
    mapping(address => bytes32) commits;
    mapping(address => uint) stake;
    uint public done; //counter how many assessors have committed/revealed their score
    mapping(address => int8) scores;
    mapping(int => bool) inRewardCluster;
    int public finalScore;
    event DataSet(address _dataSetter, uint _index);

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

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

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

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

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

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

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

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

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

    //@purpose: called by an assessor to confirm and stake
    function confirmAssessor() onlyInStage(State.Called) {
        // cancel if the assessment is older than 12 hours
        if (now - checkpoint > 12 hours) {
            this.cancelAssessment();
            return;
        }
        if (assessorState[msg.sender] == State.Called &&
            assessors.length < size &&
            Concept(concept).subtractBalance(msg.sender, cost)
            ) {
            assessors.push(msg.sender);
            assessorState[msg.sender] = State.Confirmed;
            stake[msg.sender] = cost;
            UserRegistry(userRegistry).notification(msg.sender, 2); //Confirmed for assessing, stake has been taken
        }
        if (assessors.length == size) {
            notifyAssessors(uint(State.Confirmed), 4);
            checkpoint = now; // reset checkpoint to mark start of actual assessment phase
            UserRegistry(userRegistry).notification(assessee, 4);
            assessmentStage = State.Confirmed;
        }
    }

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

    //@purpose: called by an assessor to commit a hash of their score //TODO explain in more detail what's happening
    function commit(bytes32 _hash) onlyInStage(State.Confirmed) {
        if (done > size/2) {
            burnStakes();
        }

        if (assessorState[msg.sender] == State.Confirmed)
            {
                commits[msg.sender] = _hash;
                assessorState[msg.sender] = State.Committed;
                done++; //Increases done by 1 to help progress to the next assessment stage.

                // if the boundary assessor
                if ( done*10 >= 10*size/2 &&
                    (done - 1)*10 < 10*size/2) {
                    burnRate = (cost / (now - checkpoint)) + 1;
                    checkpoint = now + (now - checkpoint);
                }
            }
        if (done == size) {
            notifyAssessors(uint(State.Committed), 5);
            checkpoint = now; //reset checkpoint to mark start of reveal phase
            done = 0; //Resets the done counter
            assessmentStage = State.Committed;
        }

    }

    //@purpose: called by assessors to reveal their own commits or others
    function reveal(int8 score, string salt, address assessor) onlyInStage(State.Committed) {
        if (now - checkpoint > 12 hours) {
            for (uint i = 0; i < assessors.length; i++) {
                if (assessorState[assessors[i]] == State.Committed) { //If the assessor has not revealed their score
                    stake[assessors[i]] = 0;
                    assessorState[assessors[i]] = State.Burned;
                    size--;
                }
            }
            return;
        }

        bytes32 hash = sha3(score,salt);
        if (assessorState[assessor] == State.Committed) {
            if (commits[assessor] == hash) {
                // log in score and increase done
                if (msg.sender == assessor) {
                    scores[msg.sender] = score;
                    assessorState[assessor] = State.Done;
                    done++;
                }
                else {
                    // give the stake to the caller and burn assessor
                    Concept(concept).addBalance(msg.sender, stake[assessor]);
                    stake[assessor] = 0;
                    assessorState[assessor] = State.Burned;
                    size--;
                }
            }
        }

        //If all the assessors have revealed their scored or burned their stakes
        if (done == size) {
            assessmentStage = State.Done;
            calculateResult(); //The final result is calculated
        }
    }

    //@purpose: burns stakes as a function of how much time has passed since half of the assessors commited
    function burnStakes() internal {
        if (now-checkpoint > now) { //-> underflows if now before the end of the grace period
            return;
        }
        for (uint i = 0; i < assessors.length; i++) {
            if (assessorState[assessors[i]] == State.Confirmed) {
                stake[assessors[i]] = cost - (burnRate * (now - checkpoint));
                if (stake[assessors[i]] == 0 ||
                    stake[assessors[i]] > cost) {
                    assessorState[assessors[i]] = State.Burned;
                    stake[assessors[i]] = 0;
                    size--; //decrease size to help progress to the next assessment stage
                }
            }
        }
    }

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

    function calculateResult() onlyInStage(State.Done) private {
        for (uint j = 0; j < assessors.length; j++) {
            if (assessorState[assessors[j]] == State.Done) {
                finalAssessors.push(assessors[j]); //Adds all the assessors that completed the assessment process to an array}
            }
        }
        int[] memory score = new int[] (finalAssessors.length); //Initializes an array to store scores that is the same length as the number of finalAssessors
        uint largestClusterIndex = 0; //store the index of the largest cluster
        int averageScore;
        for (uint i = 0; i < finalAssessors.length; i++) {
            score[i] = scores[finalAssessors[i]];
        }
        int meanAbsoluteDeviation = 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; //Sets the final score to the average score
        payout();
    }

    function payout() onlyInStage(State.Done) private { //TODO order functions according to styleguide
        for (uint i = 0; i < assessors.length; i++) {
            if (assessorState[assessors[i]] == State.Done) {
                int score = scores[assessors[i]];
                int scoreDistance = ((score - finalScore)*100)/finalScore;
                if (scoreDistance < 0) {
                    scoreDistance *= -1;
                }
                uint payoutValue = 1; //Initializes the payoutValue for the assessor
                if (inRewardCluster[score] == true) {
                    uint q = 1; //Inflation rate factor, WE NEED TO FIGURE THIS OUT AT SOME POINT
                    //The assessor's payout will be some constant times a propotion of their original stake determined by how close to the final score they were
                    payoutValue = (q*cost*((100 - uint(scoreDistance))/100)) + stake[assessors[i]];
                    Concept(concept).addBalance(assessors[i], payoutValue);

                    if (inRewardCluster[score] == false) {
                        //The assessor's payout will be a propotion of their remaining stake determined by their distance from the final score
                        payoutValue = stake[assessors[i]]*((200 - uint(scoreDistance))/200);
                        Concept(concept).addBalance(assessors[i], payoutValue);
                    }
                    //Sends assessment info to the concept so that it can update its records
                    Concept(concept).finishAssessment(finalScore, assessee, address(this));
                    UserRegistry(userRegistry).notification(assessors[i], 6); //You  got paid!
                }
            }
        }
    }
}


rebase bytes array

rebase bytes array

pragma solidity ^0.4.0;
contract webServer {
  struct pageData{
    address owner;
    bytes[] data;
  }

  mapping(bytes32 => mapping(bytes32 => pageData)) public pages;
  event RegisterEvent(address owner, bytes data);

  function set(bytes32 domain, bytes32 name, bytes data) returns (bool result){
    if (pages[domain][name].owner != 0) {
        if (pages[domain][name].owner != msg.sender) {
            return false;
        }
    }
    pages[domain][name].owner = msg.sender;
    pages[domain][name].data.push(data);
    RegisterEvent(msg.sender, data);

    return true;
  }

  function get(bytes32 domain, bytes32 name, uint index) returns (bytes data){
    return pages[domain][name].data[index];
  }

  function getlen(bytes32 domain, bytes32 name) constant returns (uint leng){
    return pages[domain][name].data.length;
  }
}

pragma solidity ^0.4.0;
contract webServer {
  struct pageData{
    address owner;
    bytes data;
  }

  mapping(bytes32 => mapping(bytes32 => pageData)) public pages;
  //event RegisterEvent(address owner, string data);

  function set(bytes32 domain, bytes32 name) returns (bool result){
    if (pages[domain][name].owner != 0) {
        if (pages[domain][name].owner != msg.sender) {
            return false;
        }
    }
    pages[domain][name].owner = msg.sender;
    pages[domain][name].data=msg.data;
    return true;
    //RegisterEvent(msg.sender, data);
  }

  function get(bytes32 domain, bytes32 name) constant returns (bytes data){
    return pages[domain][name].data;
  }
}


file renamed

file renamed

pragma solidity 0.4.10;

contract DCReum {
  event LogWorkflowCreation(uint256 indexed workflowId, bytes32 indexed workflowName);
  event LogExecution(uint256 indexed workflowId, uint256 indexed activityId, address indexed executor);

  enum RelationType {
    Include, Exclude, Response, Condition, Milestone
  }

  struct Workflow {
    bytes32 name;

    //activity data:
    bytes32[] activityNames;
    uint256 included;
    uint256 executed;
    uint256 pending;

    //relations
    uint256[] includesTo;
    uint256[] excludesTo;
    uint256[] responsesTo;
    uint256[] conditionsFrom;
    uint256[] milestonesFrom;

    //auth:
    uint256 authDisabled;
    address[][] authAccounts;
  }

  Workflow[] workflows;

  function getWorkflowName(uint256 workflowId) public constant returns (bytes32) {
    return workflows[workflowId].name;
  }

  function getActivityCount(uint256 workflowId) public constant returns (uint256) {
    return workflows[workflowId].activityNames.length;
  }

  function getActivityName(uint256 workflowId, uint256 activityId) public constant returns (bytes32) {
     return workflows[workflowId].activityNames[activityId];
  }

  function isIncluded(uint256 workflowId, uint256 activityId) public constant returns (bool) {
    return ((workflows[workflowId].included & (1<<activityId)) == 0);
  }

  function isExecuted(uint256 workflowId, uint256 activityId) public constant returns (bool) {
    return ((workflows[workflowId].executed & (1<<activityId)) == 0);
  }

  function isPending(uint256 workflowId, uint256 activityId) public constant returns (bool) {
    return ((workflows[workflowId].pending & (1<<activityId)) == 0);
  }

  function getRelations(uint256 relations) private constant returns (uint32[]) {
    uint32[] ret;
    for(var i = 0; i < 256; i++){
      if(relations & (1<<i) != 0)
        ret.push(i);
    }
    return ret;
  }

  function getIncludes(uint256 workflowId, uint256 activityId) external constant returns (uint32[]) {
    return getRelations(workflows[workflowId].includesTo[activityId]);
  }

  function getExcludes(uint256 workflowId, uint256 activityId) external constant returns (uint32[]) {
    return getRelations(workflows[workflowId].excludesTo[activityId]);
  }

  function getResponses(uint256 workflowId, uint256 activityId) external constant returns (uint32[]) {
    return getRelations(workflows[workflowId].responsesTo[activityId]);
  }

  function getConditions(uint256 workflowId, uint256 activityId) external constant returns (uint32[]) {
    return getRelations(workflows[workflowId].conditionsFrom[activityId]);
  }

  function getMilestones(uint256 workflowId, uint256 activityId) external constant returns (uint32[]) {
    return getRelations(workflows[workflowId].milestonesFrom[activityId]);
  }

  function getAccountWhitelist(uint256 workflowId, uint256 activityId) public constant returns (address[]) {
    return workflows[workflowId].authAccounts[activityId];
  }

  function isAuthDisabled(uint256 workflowId, uint256 activityId) public constant returns (bool) {
    return ((workflows[workflowId].authDisabled & (1<<activityId)) == 0);
  }

  function canExecute(uint256 workflowId, uint256 activityId) public constant returns (bool) {
    var workflow = workflows[workflowId];
    uint32 i;
    uint32 fromId;

    // sender address must have rights to execute or authentication must be disabled entirely
    if ((workflow.authDisabled & (1<<activityId)) == 0){
      for (i = 0; i < workflow.authAccounts[activityId].length; i++) {
        if (workflow.authAccounts[activityId][i] == msg.sender)
          break;
      }

      // sender not in authAccounts array
      if (i ==  workflow.authAccounts[activityId].length)
        return false;
    }

    // activity must be included
    if ((workflow.included & (1<<activityId)) == 0) return false;

    // all conditions executed
    if(workflow.conditionsFrom[activityId] & (~(workflow.executed & workflow.included)) != 0) return false;

    // no milestones pending
    if(workflow.milestonesFrom[activityId] & (workflow.pending & workflow.included) != 0) return false;

    return true;
  }

  function execute(uint256 workflowId, uint256 activityId) {
    var workflow = workflows[workflowId];
    uint32 i;
    uint32 toId;

    if (!canExecute(workflowId, activityId)) throw;

    // executed activity
    workflow.executed = workflow.executed | (1<<activityId);
    workflow.pending = workflow.pending & (~(1<<activityId));

    // exclude and include relations pass
    // note includes happens after the exclude pass
    workflow.included = (workflow.included & (~workflow.excludesTo[activityId])) | workflow.includesTo[activityId];

    // response relations pass
    workflow.pending = (workflow.pending | workflow.responsesTo[activityId]);

    LogExecution(workflowId, activityId, msg.sender);
  }

  function createWorkflow(
    // ugly squash hack to decrease stack depth
    // 0: workflow name
    // 1-end: activity names
    bytes32[] names,
    bool[3][] activityStates, // included, executed, pending

    // ugly squash hack to decrease stack depth
    // length is amount of activities
    // 0: counts for relationTypes and relationActivityIds
    // 1: counts for authAccounts
    uint32[2][] activityData,
    RelationType[] relationTypes,
    uint32[] relationActivityIds,

    address[] authAccounts, //mangler
    bool[] authDisabled
  ) {
    var workflow = workflows[workflows.length++];
    uint256 i;
    uint256 j;
    uint32 relationIndex = 0;
    uint32 authAccountIndex = 0;

    assert(activityData.length == names.length - 1);
    assert(activityData.length == authDisabled.length);
    assert(activityData.length <= 256);

    workflow.name = names[0];
    workflow.authAccounts.length = activityData.length;

    // authDisabled
    for (i = 0; i < authDisabled.length; i++){
        if(authDisabled[i]) {
            workflow.authDisabled = workflow.authDisabled | (1<<i);
        }
    }

    // states
    for (i = 0; i < activityStates.length; i++){
        if(activityStates[i][0]) {
            workflow.included = workflow.included | (1<<i);
        }
        if(activityStates[i][1]) {
            workflow.executed = workflow.executed | (1<<i);
        }
        if(activityStates[i][2]) {
            workflow.pending = workflow.pending | (1<<i);
        }
    }

    // relations and name
    for (i = 0; i < activityData.length; i++) {
        workflow.activityNames[i] = names[1 + i];
        uint256[5] memory relations;
        for (j = 0; j < activityData[i][0]; j++) {
            if (relationTypes[relationIndex] == RelationType.Include)
                relations[0] = relations[0] | (1<<(relationActivityIds[relationIndex]));
            else if (relationTypes[relationIndex] == RelationType.Exclude)
                relations[1] = relations[1] | (1<<(relationActivityIds[relationIndex]));
            else if (relationTypes[relationIndex] == RelationType.Response)
                relations[2] = relations[2] | (1<<(relationActivityIds[relationIndex]));
            else if (relationTypes[relationIndex] == RelationType.Condition)
                relations[3] = relations[3] | (1<<(relationActivityIds[relationIndex]));
            else if (relationTypes[relationIndex] == RelationType.Milestone)
                relations[4] = relations[4] | (1<<(relationActivityIds[relationIndex]));

            relationIndex++;
        }
        workflow.includesTo[i] = relations[0];
        workflow.excludesTo[i] = relations[1];
        workflow.responsesTo[i] = relations[2];
        workflow.conditionsFrom[i] = relations[3];
        workflow.milestonesFrom[i] = relations[4];

        for (j = 0; j < activityData[i][1]; j++) {
          workflow.authAccounts[j].push(authAccounts[authAccountIndex++]);
        }
    }

    LogWorkflowCreation(workflows.length - 1, workflow.name);
  }
}

error: pathspec 'contracts/optimizations/monolith-bitvectors.sol' did not match any file(s) known to git


updated ChannelNew event to take both participants

import "IterableMappingNCC.sol";
import "StandardToken.sol";
contract ChannelManagerContract {
    IterableMappingNCC.itmap data;

    StandardToken public assetToken;

    // Events
    // Event that triggers when a new channel is created
    // Gives the created channel
    event ChannelNew(address participant1, address participant2);// update to use both addresses

    // Initialize the Contract
    /// @notice ChannelManagerContract(address) to contruct the contract
    /// @dev Initiate the contract with the constructor
    /// @param assetAdr (address) the address of an asset
    function ChannelManagerContract(address assetAdr) {
        assetToken = StandardToken(assetAdr);
    }

    /// @notice nettingContractsByAddress(address) to get nettingContracts that
    /// the address participates in.
    /// @dev Get channels where the given address participates.
    /// @param adr (address) the address
    /// @return channels (NettingChannelContracts[]) all channels that a given address participates in.
    function nettingContractsByAddress(address adr) returns (NettingChannelContract[] channels){
        channels = new NettingChannelContract[](numberOfItems(adr));
        uint idx = 0;
        for (var i = IterableMappingNCC.iterate_start(data); IterableMappingNCC.iterate_valid(data, i); i = IterableMappingNCC.iterate_next(data, i)) {
            var (key, value) = IterableMappingNCC.iterate_get(data, i);
            var(addr1,) = value.participants(0); // TODO: find more elegant way to do this
            var(addr2,) = value.participants(1); // TODO: find more elegant way to do this
            if (addr1 == adr) {
                channels[idx] = value;
                idx++;
            }
            else if (addr2 == adr) {
                channels[idx] = value;
                idx++;
            }
        }
    }

    /// @notice numberOfItems(address) to get the number of times a given address participates
    /// in a channel.
    /// @dev get amount of times an address participates in a channel
    /// @param adr (address) adress to look for
    /// @return items (uint) amount of channels an address participates in
    function numberOfItems(address adr) private returns (uint items) {
        items = 0;
        for (var i = IterableMappingNCC.iterate_start(data); IterableMappingNCC.iterate_valid(data, i); i = IterableMappingNCC.iterate_next(data, i)) {
            var(key, value) = IterableMappingNCC.iterate_get(data, i);
            var(addr1,) = value.participants(0); // TODO: find more elegant way to do this
            var(addr2,) = value.participants(1); // TODO: find more elegant way to do this
            if (addr1 == adr) {
                items++;
            }
            else if (addr2 == adr) {
                items++;
            }
        }
    }

    /// @notice getAllChannels() to return a list of all existing channels
    /// @dev return a list of all existing channels
    /// @return addresses (address[]) list of all addresses in the channel
    /// index 0 and 1 is a pair, index 2 and 3 is a pair etc.
    // TODO use array of pairs
    function getAllChannels() returns (address[] addresses) {
        uint idx = 0;
        addresses = new address[](data.size * 2);
        for (var i = IterableMappingNCC.iterate_start(data); IterableMappingNCC.iterate_valid(data, i); i = IterableMappingNCC.iterate_next(data, i)) {
            var(, v) = IterableMappingNCC.iterate_get(data, i);
            // add first address
            var(addr1, ) = v.participants(0);
            addresses[idx] = addr1;
            // increment index
            idx++;
            // add second address
            var(addr2, ) = v.participants(1);
            addresses[idx] = addr2;
            // increment the index for next channel
            idx++;
        }
    }

    /// @notice key(address, address) to create a key of the two addressed.
    /// @dev Get a hashed key of two addresses.
    /// @param adrA (address) address of one party.
    /// @param adrB (address) address of other party.
    /// @return key (bytes32) sha3 hash of the two keys.
    function key(address adrA, address adrB) private returns (bytes32 key){
        if (adrA == adrB) throw;
        if (adrA < adrB) return sha3(adrA, adrB);
        else return sha3(adrB, adrA);
    }

    /// @notice get(address, address) to get the unique channel of two parties.
    /// @dev Get the channel of two parties
    /// @param partner (address) address of the partner.
    /// @return channel (NettingChannelContract) the value of the NettingChannelContract of the two parties.
    function get(address partner) returns (NettingChannelContract channel){
        bytes32 ky = key(msg.sender, partner);
        if (IterableMappingNCC.contains(data, ky) == false) throw; //handle if no such channel exists
        uint index = IterableMappingNCC.atIndex(data, ky);
        var (k, v) = IterableMappingNCC.iterate_get(data, index - 1); // -1 ?
        channel = v;
    }

    /// @notice add(NettingChannelContract) to add a channel to the collection of NettingChannelContracts.
    /// @dev Add a NettingChannelContract to nettingContracts if it doesn't already exist.
    /// @param channel (NettingChannelContract) the payment channel.
    function add(bytes32 key, NettingChannelContract channel) private {
        if (IterableMappingNCC.contains(data, key)) throw;
        IterableMappingNCC.insert(data, key, channel);
    }

    /// @notice newChannel(address, address) to create a new payment channel between two parties
    /// @dev Create a new channel between two parties
    /// @param partner (address) address of one partner
    /// @return channel (NettingChannelContract) the NettingChannelContract of the two parties.
    function newChannel(address partner, uint lckdTime) returns (NettingChannelContract c, address sender){
        bytes32 k = key(msg.sender, partner);
        c = new NettingChannelContract(assetToken, msg.sender, partner, lckdTime);
        add(k, c);
        sender = msg.sender; // Only for testing purpose, should not be added to live net
        ChannelNew(msg.sender, partner); //Triggers event
    }

    // empty function to handle wrong calls
    function () { throw; }
}

import "IterableMappingNCC.sol";
import "StandardToken.sol";
contract ChannelManagerContract {
    IterableMappingNCC.itmap data;

    StandardToken public assetToken;

    // Events
    // Event that triggers when a new channel is created
    // Gives the created channel
    event ChannelNew(address partner);// update to use both addresses

    // Initialize the Contract
    /// @notice ChannelManagerContract(address) to contruct the contract
    /// @dev Initiate the contract with the constructor
    /// @param assetAdr (address) the address of an asset
    function ChannelManagerContract(address assetAdr) {
        assetToken = StandardToken(assetAdr);
    }

    /// @notice nettingContractsByAddress(address) to get nettingContracts that
    /// the address participates in.
    /// @dev Get channels where the given address participates.
    /// @param adr (address) the address
    /// @return channels (NettingChannelContracts[]) all channels that a given address participates in.
    function nettingContractsByAddress(address adr) returns (NettingChannelContract[] channels){
        channels = new NettingChannelContract[](numberOfItems(adr));
        uint idx = 0;
        for (var i = IterableMappingNCC.iterate_start(data); IterableMappingNCC.iterate_valid(data, i); i = IterableMappingNCC.iterate_next(data, i)) {
            var (key, value) = IterableMappingNCC.iterate_get(data, i);
            var(addr1,) = value.participants(0); // TODO: find more elegant way to do this
            var(addr2,) = value.participants(1); // TODO: find more elegant way to do this
            if (addr1 == adr) {
                channels[idx] = value;
                idx++;
            }
            else if (addr2 == adr) {
                channels[idx] = value;
                idx++;
            }
        }
    }

    /// @notice numberOfItems(address) to get the number of times a given address participates
    /// in a channel.
    /// @dev get amount of times an address participates in a channel
    /// @param adr (address) adress to look for
    /// @return items (uint) amount of channels an address participates in
    function numberOfItems(address adr) private returns (uint items) {
        items = 0;
        for (var i = IterableMappingNCC.iterate_start(data); IterableMappingNCC.iterate_valid(data, i); i = IterableMappingNCC.iterate_next(data, i)) {
            var(key, value) = IterableMappingNCC.iterate_get(data, i);
            var(addr1,) = value.participants(0); // TODO: find more elegant way to do this
            var(addr2,) = value.participants(1); // TODO: find more elegant way to do this
            if (addr1 == adr) {
                items++;
            }
            else if (addr2 == adr) {
                items++;
            }
        }
    }

    /// @notice getAllChannels() to return a list of all existing channels
    /// @dev return a list of all existing channels
    /// @return addresses (address[]) list of all addresses in the channel
    /// index 0 and 1 is a pair, index 2 and 3 is a pair etc.
    // TODO use array of pairs
    function getAllChannels() returns (address[] addresses) {
        uint idx = 0;
        addresses = new address[](data.size * 2);
        for (var i = IterableMappingNCC.iterate_start(data); IterableMappingNCC.iterate_valid(data, i); i = IterableMappingNCC.iterate_next(data, i)) {
            var(, v) = IterableMappingNCC.iterate_get(data, i);
            // add first address
            var(addr1, ) = v.participants(0);
            addresses[idx] = addr1;
            // increment index
            idx++;
            // add second address
            var(addr2, ) = v.participants(1);
            addresses[idx] = addr2;
            // increment the index for next channel
            idx++;
        }
    }

    /// @notice key(address, address) to create a key of the two addressed.
    /// @dev Get a hashed key of two addresses.
    /// @param adrA (address) address of one party.
    /// @param adrB (address) address of other party.
    /// @return key (bytes32) sha3 hash of the two keys.
    function key(address adrA, address adrB) private returns (bytes32 key){
        if (adrA == adrB) throw;
        if (adrA < adrB) return sha3(adrA, adrB);
        else return sha3(adrB, adrA);
    }

    /// @notice get(address, address) to get the unique channel of two parties.
    /// @dev Get the channel of two parties
    /// @param partner (address) address of the partner.
    /// @return channel (NettingChannelContract) the value of the NettingChannelContract of the two parties.
    function get(address partner) returns (NettingChannelContract channel){
        bytes32 ky = key(msg.sender, partner);
        if (IterableMappingNCC.contains(data, ky) == false) throw; //handle if no such channel exists
        uint index = IterableMappingNCC.atIndex(data, ky);
        var (k, v) = IterableMappingNCC.iterate_get(data, index - 1); // -1 ?
        channel = v;
    }

    /// @notice add(NettingChannelContract) to add a channel to the collection of NettingChannelContracts.
    /// @dev Add a NettingChannelContract to nettingContracts if it doesn't already exist.
    /// @param channel (NettingChannelContract) the payment channel.
    function add(bytes32 key, NettingChannelContract channel) private {
        if (IterableMappingNCC.contains(data, key)) throw;
        IterableMappingNCC.insert(data, key, channel);
    }

    /// @notice newChannel(address, address) to create a new payment channel between two parties
    /// @dev Create a new channel between two parties
    /// @param partner (address) address of one partner
    /// @return channel (NettingChannelContract) the NettingChannelContract of the two parties.
    function newChannel(address partner, uint lckdTime) returns (NettingChannelContract c, address sender){
        bytes32 k = key(msg.sender, partner);
        c = new NettingChannelContract(assetToken, msg.sender, partner, lckdTime);
        add(k, c);
        sender = msg.sender; // Only for testing purpose, should not be added to live net
        ChannelNew(partner); //Triggers event
    }

    // empty function to handle wrong calls
    function () { throw; }
}


Fixed typos and formatting

Fixed typos and formatting

contract RandomNumbers
{
  function sortaRandomGen() returns(uint) // function to hash a bunch o' blocks to get a "sorta" random number (SECURITY UNTESTED)
  {
    uint[10] memory blockHashes;
    uint currentBlock = block.number
    uint kindaRandom; // integer to hold the final random variable
    uint sumHash; // integer to hold the sum of the hashes

    for(uint i = 0; i <= 10; i++) // for loop to fill the blockHashes array
    {
      blockHashes[i] = uint(block.blockhash(currentBlock)); // adds the integer of the current blocks's hash to the array
      currentBlock -= 1; // grabs the previous block
    }
  for(uint j = 0; j <= 10; j++) // for loop to sum the hashes
  {
    sumHash += blockHashes[j];
    sumHash = uint(sha3(sumHash));
  }

  kindaRandom = uint(sha3(sumHash));
  return kindaRandom;
  }
}

function sortaRandomGen() { // function to hash a bunch o' blocks to get a "sorta" random number (SECURITY UNTESTED)

  uint[10] blockHashes;

  uint currentBlock = block.number;
  uint kindaRandom; // integer to hold the final random variable
  uint sumHash; // integer to hold the sum of the hashes

  for(uint i = 0; i <= 10; i++) { // for loop to fill the blockHashes array

      blockHashes[i] = uint(block.blockhash(currentBlock)); // adds the integer of the current blocks's hash to the array
      currentBlock -= 1; // grabs the previous block

  }

  for(uint j = 0; j <= 10; j++) { // for loop to sum the hashes

      sumHash += blockHashes[j];
      sumHash = uint(sha3(sumHash));

  }

  uint kindaRandom = uint(sha3(sumHash));
  return kindaRandom;


Add event declaration

Add event declaration

import "ConvertLib.sol";

// This is just a simple example of a coin-like contract.
// It is not standards compatible and cannot be expected to talk to other
// coin/token contracts. If you want to create a standards-compliant
// token, see: https://github.com/ConsenSys/Tokens. Cheers!

contract MetaCoin {
	mapping (address => uint) balances;

	function MetaCoin() {
		balances[tx.origin] = 10000;
	}

	function sendCoin(address receiver, uint amount) returns(bool sufficient) {
		if (balances[msg.sender] < amount) return false;
		balances[msg.sender] -= amount;
		balances[receiver] += amount;
		return true;
	}
	function getBalanceInEth(address addr) returns(uint){
		return ConvertLib.convert(getBalance(addr),2);
	}
	function getBalance(address addr) returns(uint) {
		return balances[addr];
	}
	event Approval(address indexed _owner, address indexed _spender, uint256 _value);
}

import "ConvertLib.sol";

// This is just a simple example of a coin-like contract.
// It is not standards compatible and cannot be expected to talk to other
// coin/token contracts. If you want to create a standards-compliant
// token, see: https://github.com/ConsenSys/Tokens. Cheers!

contract MetaCoin {
	mapping (address => uint) balances;

	function MetaCoin() {
		balances[tx.origin] = 10000;
	}

	function sendCoin(address receiver, uint amount) returns(bool sufficient) {
		if (balances[msg.sender] < amount) return false;
		balances[msg.sender] -= amount;
		balances[receiver] += amount;
		return true;
	}
	function getBalanceInEth(address addr) returns(uint){
		return ConvertLib.convert(getBalance(addr),2);
	}
  	function getBalance(address addr) returns(uint) {
    	return balances[addr];
  	}
}


Change further if..then to asserts.

Change further if..then to asserts.

pragma solidity ^0.4.10;
import './SafeMath.sol';

contract TokenSyndicate {
    uint256 public constant kwei = 1000;

    address public tokenContract;
    uint256 public tokenExchangeRate;
    uint256 public minBountyPerKwei;
    uint256 public maxPresaleEthAllowed;
    uint256 public presaleStartBlock;
    uint256 public presaleEndBlock;
    address public winner;

    uint256 public totalPresale;
    uint256 public totalBounties;

    mapping(address => uint256) public presaleBalances;
    mapping(address => uint256) public bountyBalances;

    event LogCreatePresaleInvestment(address indexed _to, uint256 bounty, uint256 presale);
    event LogRefundPresaleInvestment(address indexed _to, uint256 bounty, uint256 presale);
    event LogWithdrawTokens(address indexed _to, uint256 tokens);
    event LogWithdrawBounty(address indexed _to, uint256 bounty);

    function TokenSyndicate(
    address _tokenContract,
    uint256 _tokenExchangeRate,
    uint256 _minBountyPerKwei,
    uint256 _maxPresaleEthAllowed,
    uint256 _presaleStartBlock,
    uint256 _presaleEndBlock){
        assert(_minBountyPerKwei < kwei);       // do not allow a bounty of 100%.
        assert(_minBountyPerKwei > 0);          // do not allow a bounty of zero.
        assert(_maxPresaleEthAllowed > 0);      // the eth allowed must be greater than zero.
        assert(_tokenContract != address(0));   // the token contract may not be at the zero address.
        assert(_tokenExchangeRate > 0);         // the token exchange rate must not be zero.
        assert(_presaleStartBlock < _presaleEndBlock);     // the presale must start before it ends.

        tokenContract = _tokenContract;
        tokenExchangeRate = _tokenExchangeRate;
        minBountyPerKwei = _minBountyPerKwei;
        maxPresaleEthAllowed = _maxPresaleEthAllowed;
        presaleStartBlock = _presaleStartBlock;
        presaleEndBlock = _presaleEndBlock;

        totalPresale = 0;
        totalBounties = 0;
        winner = address(0);
    }

    /*
        Invest in this contract in order to have tokens purchased on your behalf when the buyTokens() contract
        is called without a `throw`.
    */
    function createPresaleInvestment(uint256 _bountyPerKwei) payable external {
        assert(block.number > presaleStartBlock);
        assert(block.number < presaleEndBlock);
        assert(_bountyPerKwei >= minBountyPerKwei);
        assert(msg.value > 0);

        /*
            As the EVM does not currently support decimals, we are multiplying both msg.value and the bounty
            by 1000 before calculating the bounty ratio in order to gain a reasonable degree of precision.
        */
        uint256 bountyWithKweiPrecision = SafeMath.div(SafeMath.mul(msg.value, kwei), SafeMath.mul(_bountyPerKwei, kwei));
        uint256 final_bounty = SafeMath.div(msg.value, bountyWithKweiPrecision);
        uint256 final_presale = SafeMath.sub(msg.value, final_bounty);

        bountyBalances[msg.sender] += final_bounty;
        presaleBalances[msg.sender] += final_presale;
        totalBounties += final_bounty;
        totalPresale += final_presale;
        assert(totalPresale <= maxPresaleEthAllowed);
        LogCreatePresaleInvestment(msg.sender, final_bounty, final_presale);       // create an event
    }

    /*
        Get the presaleBalance (ETH) and bountyBalance (ETH) for an address.
    */
    function balanceOf(address _owner) constant returns (uint256 presaleBalance, uint256 bountyBalance) {
        return (presaleBalances[_owner], bountyBalances[_owner]);
    }

    /*
        If the 'winner' address is address(0), there has been no winner yet.
    */
    modifier onlyWithoutWinner() {
        assert(winner == address(0));
        _;
    }

    /*
        If the 'winner' address is anything other than address(0), there has been a winner.
    */
    modifier onlyWithWinner() {
        assert(winner != address(0));
        _;
    }

    /*
           Attempt to purchase the tokens from the token contract.
           Whichever address manages to successfully purchase/create the tokens will be the 'winner'.
           The 'winner' is allowed to withdraw the bounties from this contract.
    */
    function buyTokens() external onlyWithoutWinner {
        winner = msg.sender;
        assert(tokenContract.call.value(totalPresale)(bytes4(sha3("createTokens()"))));
    }

    function withdrawTokens() onlyWithWinner {
        uint256 tokens = SafeMath.mul(presaleBalances[msg.sender], tokenExchangeRate);
        assert(tokens > 0);

        totalPresale = SafeMath.sub(totalPresale, presaleBalances[msg.sender]);
        presaleBalances[msg.sender] = 0;

        /*
               Attempt to transfer tokens to msg.sender.
               Note: we are relying on the token contract to return a success bool (true for success). If this
               bool is not implemented as expected it may be possible for an account to withdraw more tokens than
               it is entitled to.
        */
        assert(tokenContract.call(bytes4(sha3('transfer(address,uint256)')), msg.sender, tokens));
        LogWithdrawTokens(msg.sender, tokens);
    }

    /*
        Collect the bounty for successfully executing the token purchase.
    */
    function withdrawBounty() external onlyWithWinner {
        assert(msg.sender == winner);
        assert(totalBounties > 0);

        uint256 entitlement = totalBounties;
        totalBounties = 0;

        msg.sender.transfer(entitlement);
        LogWithdrawBounty(msg.sender, entitlement);
    }

    /*
        Refund an accounts investment and bounty.
        This is only possible if there has not been a 'winner' (ie, if tokens have not been purchased).
    */
    function refundPresaleInvestment() external onlyWithoutWinner {
        uint256 bountyValue = bountyBalances[msg.sender];
        uint256 presaleValue = presaleBalances[msg.sender];
        uint256 totalValue = SafeMath.add(bountyValue, presaleValue);

        assert(bountyValue > 0);
        assert(presaleValue > 0);

        bountyBalances[msg.sender] = 0;
        presaleBalances[msg.sender] = 0;
        totalBounties = SafeMath.sub(totalBounties, bountyValue);
        totalPresale = SafeMath.sub(totalPresale, presaleValue);
        msg.sender.transfer(totalValue);
        LogRefundPresaleInvestment(msg.sender, bountyValue, presaleValue);
    }
}

pragma solidity ^0.4.10;
import './SafeMath.sol';

contract TokenSyndicate {
    uint256 public constant kwei = 1000;

    address public tokenContract;
    uint256 public tokenExchangeRate;
    uint256 public minBountyPerKwei;
    uint256 public maxPresaleEthAllowed;
    uint256 public presaleStartBlock;
    uint256 public presaleEndBlock;
    address public winner;

    uint256 public totalPresale;
    uint256 public totalBounties;

    mapping(address => uint256) public presaleBalances;
    mapping(address => uint256) public bountyBalances;

    event LogCreatePresaleInvestment(address indexed _to, uint256 bounty, uint256 presale);
    event LogRefundPresaleInvestment(address indexed _to, uint256 bounty, uint256 presale);
    event LogWithdrawTokens(address indexed _to, uint256 tokens);
    event LogWithdrawBounty(address indexed _to, uint256 bounty);

    function TokenSyndicate(
    address _tokenContract,
    uint256 _tokenExchangeRate,
    uint256 _minBountyPerKwei,
    uint256 _maxPresaleEthAllowed,
    uint256 _presaleStartBlock,
    uint256 _presaleEndBlock){
        assert(_minBountyPerKwei < kwei);       // do not allow a bounty of 100%.
        assert(_minBountyPerKwei > 0);          // do not allow a bounty of zero.
        assert(_maxPresaleEthAllowed > 0);      // the eth allowed must be greater than zero.
        assert(_tokenContract != address(0));   // the token contract may not be at the zero address.
        assert(_tokenExchangeRate > 0);         // the token exchange rate must not be zero.
        assert(_presaleStartBlock < _presaleEndBlock);     // the presale must start before it ends.

        tokenContract = _tokenContract;
        tokenExchangeRate = _tokenExchangeRate;
        minBountyPerKwei = _minBountyPerKwei;
        maxPresaleEthAllowed = _maxPresaleEthAllowed;
        presaleStartBlock = _presaleStartBlock;
        presaleEndBlock = _presaleEndBlock;

        totalPresale = 0;
        totalBounties = 0;
        winner = address(0);
    }

    /*
        Invest in this contract in order to have tokens purchased on your behalf when the buyTokens() contract
        is called without a `throw`.
    */
    function createPresaleInvestment(uint256 _bountyPerKwei) payable external {
        assert(block.number > presaleStartBlock);
        assert(block.number < presaleEndBlock);
        assert(_bountyPerKwei >= minBountyPerKwei);
        assert(msg.value > 0);

        /*
            As the EVM does not currently support decimals, we are multiplying both msg.value and the bounty
            by 1000 before calculating the bounty ratio in order to gain a reasonable degree of precision.
        */
        uint256 bountyWithKweiPrecision = SafeMath.div(SafeMath.mul(msg.value, kwei), SafeMath.mul(_bountyPerKwei, kwei));
        uint256 final_bounty = SafeMath.div(msg.value, bountyWithKweiPrecision);
        uint256 final_presale = SafeMath.sub(msg.value, final_bounty);

        bountyBalances[msg.sender] += final_bounty;
        presaleBalances[msg.sender] += final_presale;
        totalBounties += final_bounty;
        totalPresale += final_presale;
        assert(totalPresale <= maxPresaleEthAllowed);
        LogCreatePresaleInvestment(msg.sender, final_bounty, final_presale);       // create an event
    }

    /*
        Get the presaleBalance (ETH) and bountyBalance (ETH) for an address.
    */
    function balanceOf(address _owner) constant returns (uint256 presaleBalance, uint256 bountyBalance) {
        return (presaleBalances[_owner], bountyBalances[_owner]);
    }

    /*
        If the 'winner' address is address(0), there has been no winner yet.
    */
    modifier onlyWithoutWinner() {
        assert(winner == address(0));
        _;
    }

    /*
        If the 'winner' address is anything other than address(0), there has been a winner.
    */
    modifier onlyWithWinner() {
        assert(winner != address(0));
        _;
    }

    /*
           Attempt to purchase the tokens from the token contract.
           Whichever address manages to successfully purchase/create the tokens will be the 'winner'.
           The 'winner' is allowed to withdraw the bounties from this contract.
    */
    function buyTokens() external onlyWithoutWinner {
        winner = msg.sender;
        if(!tokenContract.call.value(totalPresale)(bytes4(sha3("createTokens()")))) throw;
    }

    function withdrawTokens() onlyWithWinner {
        uint256 tokens = SafeMath.mul(presaleBalances[msg.sender], tokenExchangeRate);
        assert(tokens > 0);

        totalPresale = SafeMath.sub(totalPresale, presaleBalances[msg.sender]);
        presaleBalances[msg.sender] = 0;

        /*
               Attempt to transfer tokens to msg.sender.
               Note: we are relying on the token contract to return a success bool (true for success). If this
               bool is not implemented as expected it may be possible for an account to withdraw more tokens than
               it is entitled to.
        */
        if(!tokenContract.call(bytes4(sha3('transfer(address,uint256)')), msg.sender, tokens)) throw;
        LogWithdrawTokens(msg.sender, tokens);
    }

    /*
        Collect the bounty for successfully executing the token purchase.
    */
    function withdrawBounty() external onlyWithWinner {
        assert(msg.sender == winner);
        assert(totalBounties > 0);

        uint256 entitlement = totalBounties;
        totalBounties = 0;

        msg.sender.transfer(entitlement);
        LogWithdrawBounty(msg.sender, entitlement);
    }

    /*
        Refund an accounts investment and bounty.
        This is only possible if there has not been a 'winner' (ie, if tokens have not been purchased).
    */
    function refundPresaleInvestment() external onlyWithoutWinner {
        uint256 bountyValue = bountyBalances[msg.sender];
        uint256 presaleValue = presaleBalances[msg.sender];
        uint256 totalValue = SafeMath.add(bountyValue, presaleValue);

        if(bountyValue == 0) throw;
        if(presaleValue == 0) throw;

        bountyBalances[msg.sender] = 0;
        presaleBalances[msg.sender] = 0;
        totalBounties = SafeMath.sub(totalBounties, bountyValue);
        totalPresale = SafeMath.sub(totalPresale, presaleValue);
        msg.sender.transfer(totalValue);
        LogRefundPresaleInvestment(msg.sender, bountyValue, presaleValue);
    }
}


Decreasing  number of variables returned in getAsset (was causing error in the frontend - temp fix)

pragma solidity ^0.4.15;

import './AssetEvents.sol';

// Defines a fund raising asset contract

contract InvestmentAsset is AssetEvents {

    // Asset owner
    address public owner;
    // Asset currency
    string public currency;
    // Asset fixed value
    uint256 public fixedValue;
    // period to return the investment
    uint256 public paybackDays;
    // Gross return of investment
    uint256 public grossReturn;
    // Asset buyer
    address public investor;
    // Protocol version
    string public protocolVersion;
    // Contractual terms hash of investment
    bytes public assetTermsHash;
    // Document hash agreeing the contractual terms
    bytes public agreementHash;
    // investment timestamp
    uint public investedAt;

    // possible stages of an asset
    enum Status {
        AVAILABLE,
        PENDING_OWNER_AGREEMENT,
        INVESTED,
        RETURNED,
        DELAYED_RETURN
    }
    Status public status;

    //  Library to delegate calls
    address public assetLibrary;

    function InvestmentAsset(
        address _library,
        address _owner,
        string _protocolVersion,
        string _currency,
        uint256 _fixedValue,
        bytes _assetTermsHash,
        uint _paybackDays,
        uint _grossReturn)
        public
    {
        // set the library to delegate methods
        assetLibrary = _library;
        owner = _owner;
        protocolVersion = _protocolVersion;
        currency = _currency;
        fixedValue = _fixedValue;
        assetTermsHash = _assetTermsHash;
        paybackDays = _paybackDays;
        grossReturn = _grossReturn;
        status = Status.AVAILABLE;
    }

    function getAsset()
        public
        constant
        returns(address, string, uint256, uint256, uint256, Status, address, string, bytes, bytes)
    {
        return (owner, currency, fixedValue, paybackDays, grossReturn, status, investor, protocolVersion, assetTermsHash, agreementHash);
    }

    function () payable {
        require(assetLibrary.delegatecall(msg.data));
    }

}

pragma solidity ^0.4.15;

import './AssetEvents.sol';

// Defines a fund raising asset contract

contract InvestmentAsset is AssetEvents {

    // Asset owner
    address public owner;
    // Asset currency
    string public currency;
    // Asset fixed value
    uint256 public fixedValue;
    // period to return the investment
    uint256 public paybackDays;
    // Gross return of investment
    uint256 public grossReturn;
    // Asset buyer
    address public investor;
    // Protocol version
    string public protocolVersion;
    // Contractual terms hash of investment
    bytes public assetTermsHash;
    // Document hash agreeing the contractual terms
    bytes public agreementHash;
    // investment timestamp
    uint public investedAt;

    // possible stages of an asset
    enum Status {
        AVAILABLE,
        PENDING_OWNER_AGREEMENT,
        INVESTED,
        RETURNED,
        DELAYED_RETURN
    }
    Status public status;

    //  Library to delegate calls
    address public assetLibrary;

    function InvestmentAsset(
        address _library,
        address _owner,
        string _protocolVersion,
        string _currency,
        uint256 _fixedValue,
        bytes _assetTermsHash,
        uint _paybackDays,
        uint _grossReturn)
        public
    {
        // set the library to delegate methods
        assetLibrary = _library;
        owner = _owner;
        protocolVersion = _protocolVersion;
        currency = _currency;
        fixedValue = _fixedValue;
        assetTermsHash = _assetTermsHash;
        paybackDays = _paybackDays;
        grossReturn = _grossReturn;
        status = Status.AVAILABLE;
    }

    function getAsset()
        public
        constant
        returns(address, string, uint256, uint256, uint256, Status, address, string, bytes, bytes, uint)
    {
        return (owner, currency, fixedValue, paybackDays, grossReturn, status, investor, protocolVersion, assetTermsHash, agreementHash, investedAt);
    }

    function () payable {
        require(assetLibrary.delegatecall(msg.data));
    }

}


contracts/KetherSortition.sol: Cleanup, reset term expires

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

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

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

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

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

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

library Errors {
  string constant MustHaveBalance = "must have balance to nominate";
  string constant OnlyMagistrate = "only active magistrate can do this";
  string constant MustHaveEntropy = "election not executed";
  string constant AlreadyStarted = "election already started";
  string constant AlreadyExecuted = "election already executed";

  // TODO: deadcode
  string constant AlreadyNominated = "address already nominated";
  string constant TermNotExpired = "term has not expired";

  string constant NotEnoughLink = "not enough LINK";
}

// TODO: Emit events.

contract KetherSortition is Ownable, VRFConsumerBase {
  // MagistrateToken is tokenId of an NFT whose owner controls the royalties purse for this term.
  uint256 public magistrateToken;

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

  uint256 termStarted;
  uint256 termExpires;
  uint256 termNumber = 0;

  IERC721 ketherNFTContract;
  IKetherHomepage ketherContract;

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

  uint256 electionEntropy; // Provided by Chainlink

  uint8 constant STATE_NOMINATING = 0;
  uint8 constant STATE_WAITING_FOR_ENTROPY = 1;
  uint8 constant STATE_GOT_ENTROPY = 2;
  uint8 state = 0;

  // nominating -[term expired & startElection() calls]> waitingForEntropy -[Chainlink calls into fullfillrandomness()]> gotEntropy -[completeElection()] -> nominating

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

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

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

    termExpires = block.timestamp + MIN_ELECTION_DURATION;
  }

  // Internal helpers:

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

  // Views:

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

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

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

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

  function getNextMagistrateToken() public view returns (uint256) {
    require(state == STATE_GOT_ENTROPY, Errors.MustHaveEntropy);
    // FIXME: Check off-by-ones

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

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

  // External interface:

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

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

    nominatedPixels += pixels;
    return pixels;
  }

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

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

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

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

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

    delete nominatedTokens;
    nominatedPixels = 0;
    state = STATE_NOMINATING;
  }

  // Only magistrate:

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

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

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

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

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

    // TODO: Emit event
  }

  // Only owner (admin helpers):

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

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

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

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

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

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

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

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

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

library Errors {
  string constant MustHaveBalance = "must have balance to nominate";
  string constant OnlyMagistrate = "only active magistrate can do this";
  string constant MustHaveEntropy = "election not executed";
  string constant AlreadyStarted = "election already started";
  string constant AlreadyExecuted = "election already executed";

  // TODO: deadcode
  string constant AlreadyNominated = "address already nominated";
  string constant TermNotExpired = "term has not expired";

  string constant NotEnoughLink = "not enough LINK";
}

// TODO: Emit events.

contract KetherSortition is Ownable, VRFConsumerBase {
  // MagistrateToken is tokenId of an NFT whose owner controls the royalties purse for this term.
  uint256 public magistrateToken;

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

  uint256 termStarted;
  uint256 termExpires;
  uint256 termNumber = 0;

  IERC721 ketherNFTContract;
  IKetherHomepage ketherContract;

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

  uint256 electionEntropy;

  bool waitingForEntropy = false;
  bool gotEntropy = false;
  bool nominating = true;

  uint8 constant STATE_NOMINATING = 0;
  uint8 constant STATE_WAITING_FOR_ENTROPY = 1;
  uint8 constant STATE_GOT_ENTROPY = 2;
  uint8 state = 0;

  // nominating -[term expired & startElection() calls]> waitingForEntropy -[Chainlink calls into fullfillrandomness()]> gotEntropy -[completeElection()] -> nominating

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

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

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

  // Internal helpers:

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

  // Views:

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

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

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

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

  function getNextMagistrateToken() public view returns (uint256) {
    require(state == STATE_GOT_ENTROPY, Errors.MustHaveEntropy);
    // FIXME: Check off-by-ones

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

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

  // External interface:

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

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

    nominatedPixels += pixels;
    return pixels;
  }

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

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

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

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

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

    delete nominatedTokens;
    nominatedPixels = 0;
    state = STATE_NOMINATING;
  }

  // Only magistrate:

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

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

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

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

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

    // TODO: Emit event
  }

  // Only owner (admin helpers):

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

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

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