diff --git a/contracts/Colony.sol b/contracts/Colony.sol index 77d71c9529..0ce3109083 100755 --- a/contracts/Colony.sol +++ b/contracts/Colony.sol @@ -105,8 +105,10 @@ contract Colony is ColonyStorage, PatriciaTreeProofs { } function mintTokensForColonyNetwork(uint _wad) public { - require(msg.sender == colonyNetworkAddress, "colony-access-denied-only-network-allowed"); // Only the colony Network can call this function - require(this == IColonyNetwork(colonyNetworkAddress).getMetaColony(), "colony-access-denied-only-meta-colony-allowed"); // Function only valid on the Meta Colony + // Only the colony Network can call this function + require(msg.sender == colonyNetworkAddress, "colony-access-denied-only-network-allowed"); + // Function only valid on the Meta Colony + require(this == IColonyNetwork(colonyNetworkAddress).getMetaColony(), "colony-access-denied-only-meta-colony-allowed"); token.mint(_wad); token.transfer(colonyNetworkAddress, _wad); } @@ -145,16 +147,6 @@ contract Colony is ColonyStorage, PatriciaTreeProofs { function getDomainCount() public view returns (uint256) { return domainCount; } - function setFunctionReviewers(bytes4 _sig, uint8 _firstReviewer, uint8 _secondReviewer) - private - { - uint8[2] memory _reviewers = [_firstReviewer, _secondReviewer]; - reviewers[_sig] = _reviewers; - } - - function setRoleAssignmentFunction(bytes4 _sig) private { - roleAssignmentSigs[_sig] = true; - } modifier verifyKey(bytes key) { uint256 colonyAddress; @@ -175,7 +167,7 @@ contract Colony is ColonyStorage, PatriciaTreeProofs { function verifyReputationProof(bytes key, bytes value, uint branchMask, bytes32[] siblings) // solium-disable-line security/no-assign-params verifyKey(key) - public returns (bool) + public view returns (bool) { // Get roothash from colonynetwork bytes32 rootHash = IColonyNetwork(colonyNetworkAddress).getReputationRootHash(); @@ -195,6 +187,17 @@ contract Colony is ColonyStorage, PatriciaTreeProofs { e.setResolver(newResolver); } + function setFunctionReviewers(bytes4 _sig, uint8 _firstReviewer, uint8 _secondReviewer) + private + { + uint8[2] memory _reviewers = [_firstReviewer, _secondReviewer]; + reviewers[_sig] = _reviewers; + } + + function setRoleAssignmentFunction(bytes4 _sig) private { + roleAssignmentSigs[_sig] = true; + } + function initialiseDomain(uint256 _skillId) private skillExists(_skillId) { // Create a new pot potCount += 1; diff --git a/contracts/ColonyFunding.sol b/contracts/ColonyFunding.sol index 9afcd48c6b..8c760ef8f8 100755 --- a/contracts/ColonyFunding.sol +++ b/contracts/ColonyFunding.sol @@ -245,7 +245,13 @@ contract ColonyFunding is ColonyStorage, DSMath { function getRewardPayoutInfo(uint256 _payoutId) public view returns (bytes32, uint256, uint256, address, uint256) { RewardPayoutCycle memory rewardPayoutInfo = rewardPayoutCycles[_payoutId]; - return (rewardPayoutInfo.reputationState, rewardPayoutInfo.totalTokens, rewardPayoutInfo.amount, rewardPayoutInfo.tokenAddress, rewardPayoutInfo.blockTimestamp); + return ( + rewardPayoutInfo.reputationState, + rewardPayoutInfo.totalTokens, + rewardPayoutInfo.amount, + rewardPayoutInfo.tokenAddress, + rewardPayoutInfo.blockTimestamp + ); } function updateTaskPayoutsWeCannotMakeAfterPotChange(uint256 _id, address _token, uint _prev) internal { diff --git a/contracts/ColonyNetwork.sol b/contracts/ColonyNetwork.sol index 79f4e9c0c9..a5cc76fef2 100644 --- a/contracts/ColonyNetwork.sol +++ b/contracts/ColonyNetwork.sol @@ -245,6 +245,13 @@ contract ColonyNetwork is ColonyNetworkStorage { uint nParents = skills[_skillId].nParents; // TODO: Is it cheaper to check if _amount is <0, and if not, just set nChildren to 0, because children won't be updated for such an update? uint nChildren = skills[_skillId].nChildren; - IReputationMiningCycle(inactiveReputationMiningCycle).appendReputationUpdateLog(_user, _amount, _skillId, msg.sender, nParents, nChildren); + IReputationMiningCycle(inactiveReputationMiningCycle).appendReputationUpdateLog( + _user, + _amount, + _skillId, + msg.sender, + nParents, + nChildren + ); } } diff --git a/contracts/ColonyNetworkStaking.sol b/contracts/ColonyNetworkStaking.sol index 5b69b6f5c1..c1b7dcda9c 100644 --- a/contracts/ColonyNetworkStaking.sol +++ b/contracts/ColonyNetworkStaking.sol @@ -127,7 +127,8 @@ contract ColonyNetworkStaking is ColonyNetworkStorage, DSMath { IColony(metaColony).mintTokensForColonyNetwork(stakers.length * reward); // This should be the total amount of new tokens we're awarding. - ReputationMiningCycle(inactiveReputationMiningCycle).rewardStakersWithReputation(stakers, metaColony, reward, rootGlobalSkillId + 2); // This gives them reputation in the next update cycle. + // This gives them reputation in the next update cycle. + ReputationMiningCycle(inactiveReputationMiningCycle).rewardStakersWithReputation(stakers, metaColony, reward, rootGlobalSkillId + 2); for (uint256 i = 0; i < stakers.length; i++) { // Also give them some newly minted tokens. diff --git a/contracts/ColonyTask.sol b/contracts/ColonyTask.sol index bbe4c8f6ec..9884e67f5d 100755 --- a/contracts/ColonyTask.sol +++ b/contracts/ColonyTask.sol @@ -19,7 +19,6 @@ pragma solidity ^0.4.23; pragma experimental "v0.5.0"; import "../lib/dappsys/math.sol"; -import "./IColonyNetwork.sol"; import "./ColonyStorage.sol"; import "./IColony.sol"; import "./SafeMath.sol"; @@ -100,7 +99,8 @@ contract ColonyTask is ColonyStorage, DSMath { modifier taskWorkRatingsClosed(uint256 _id) { uint taskCompletionTime = tasks[_id].deliverableTimestamp != 0 ? tasks[_id].deliverableTimestamp : tasks[_id].dueDate; - require(sub(now, taskCompletionTime) > add(RATING_COMMIT_TIMEOUT, RATING_REVEAL_TIMEOUT)); // More than 10 days from work submission have passed + // More than 10 days from work submission have passed + require(sub(now, taskCompletionTime) > add(RATING_COMMIT_TIMEOUT, RATING_REVEAL_TIMEOUT)); _; } @@ -182,11 +182,17 @@ contract ColonyTask is ColonyStorage, DSMath { msgHash ); - require(reviewerAddresses[0] == tasks[taskId].roles[reviewers[sig][0]].user || reviewerAddresses[0] == tasks[taskId].roles[reviewers[sig][1]].user); + require( + reviewerAddresses[0] == tasks[taskId].roles[reviewers[sig][0]].user || + reviewerAddresses[0] == tasks[taskId].roles[reviewers[sig][1]].user + ); if (nSignaturesRequired == 2) { require(reviewerAddresses[0] != reviewerAddresses[1]); - require(reviewerAddresses[1] == tasks[taskId].roles[reviewers[sig][0]].user || reviewerAddresses[1] == tasks[taskId].roles[reviewers[sig][1]].user); + require( + reviewerAddresses[1] == tasks[taskId].roles[reviewers[sig][0]].user || + reviewerAddresses[1] == tasks[taskId].roles[reviewers[sig][1]].user + ); } taskChangeNonces[taskId]++; @@ -248,14 +254,6 @@ contract ColonyTask is ColonyStorage, DSMath { require(executeCall(address(this), _value, _data)); } - // The address.call() syntax is no longer recommended, see: - // https://github.com/ethereum/solidity/issues/2884 - function executeCall(address to, uint256 value, bytes data) internal returns (bool success) { - assembly { - success := call(gas, to, value, add(data, 0x20), mload(data), 0, 0) - } - } - function submitTaskWorkRating(uint256 _id, uint8 _role, bytes32 _ratingSecret) public userCanRateRole(_id, _role) ratingSecretDoesNotExist(_id, _role) @@ -423,7 +421,18 @@ contract ColonyTask is ColonyStorage, DSMath { function getTask(uint256 _id) public view returns (bytes32, bytes32, bool, bool, uint256, uint256, uint256, uint256, uint256, uint256[]) { Task storage t = tasks[_id]; - return (t.specificationHash, t.deliverableHash, t.finalized, t.cancelled, t.dueDate, t.payoutsWeCannotMake, t.potId, t.deliverableTimestamp, t.domainId, t.skills); + return ( + t.specificationHash, + t.deliverableHash, + t.finalized, + t.cancelled, + t.dueDate, + t.payoutsWeCannotMake, + t.potId, + t.deliverableTimestamp, + t.domainId, + t.skills + ); } function getTaskRole(uint256 _id, uint8 _role) public view returns (address, bool, uint8) { @@ -485,6 +494,14 @@ contract ColonyTask is ColonyStorage, DSMath { return reviewerAddresses; } + // The address.call() syntax is no longer recommended, see: + // https://github.com/ethereum/solidity/issues/2884 + function executeCall(address to, uint256 value, bytes data) internal returns (bool success) { + assembly { + success := call(gas, to, value, add(data, 0x20), mload(data), 0, 0) + } + } + // Get the function signature and task id from the transaction bytes data // Note: Relies on the encoded function's first parameter to be the uint256 taskId function deconstructCall(bytes _data) internal pure returns (bytes4 sig, uint256 taskId) { diff --git a/contracts/IColony.sol b/contracts/IColony.sol index 2025a42b27..b3f0570241 100644 --- a/contracts/IColony.sol +++ b/contracts/IColony.sol @@ -218,7 +218,14 @@ contract IColony { /// @param _value The transaction value, i.e. number of wei to be sent when the transaction is executed /// Currently we only accept 0 value transactions but this is kept as a future option /// @param _data The transaction data - function executeTaskChange(uint8[] _sigV, bytes32[] _sigR, bytes32[] _sigS, uint8[] _mode, uint256 _value, bytes _data) public; + function executeTaskChange( + uint8[] _sigV, + bytes32[] _sigR, + bytes32[] _sigS, + uint8[] _mode, + uint256 _value, + bytes _data + ) public; /// @notice Executes a task role update transaction `_data` which is approved and signed by two of addresses /// depending of which function we are calling. Allowed functions are `setTaskManagerRole`, `setTaskEvaluatorRole` and `setTaskWorkerRole`. @@ -230,7 +237,14 @@ contract IColony { /// @param _value The transaction value, i.e. number of wei to be sent when the transaction is executed /// Currently we only accept 0 value transactions but this is kept as a future option /// @param _data The transaction data - function executeTaskRoleAssignment(uint8[] _sigV, bytes32[] _sigR, bytes32[] _sigS, uint8[] _mode, uint256 _value, bytes _data) public; + function executeTaskRoleAssignment( + uint8[] _sigV, + bytes32[] _sigR, + bytes32[] _sigS, + uint8[] _mode, + uint256 _value, + bytes _data + ) public; /// @notice Submit a hashed secret of the rating for work in task `_id` which was performed by user with task role id `_role` /// Allowed within 5 days period starting which whichever is first from either the deliverable being submitted or the dueDate been reached diff --git a/contracts/IReputationMiningCycle.sol b/contracts/IReputationMiningCycle.sol index af0ad80e64..0e58849a41 100644 --- a/contracts/IReputationMiningCycle.sol +++ b/contracts/IReputationMiningCycle.sol @@ -25,7 +25,19 @@ contract IReputationMiningCycle { /// @param round The dispute round to query /// @param index The index in the dispute round to query /// @return The elements of the Submission struct for the submission requested. See ReputationMiningCycle.sol for the full description - function disputeRounds(uint256 round, uint256 index) public view returns (bytes32 proposedNewRootHash, uint256 nNodes, uint256 lastResponseTimestamp, uint256 challengeStepCompleted, bytes32 jrh, bytes32 intermediateReputationHash, uint256 intermediateReputationNNodes, uint256 jrhNnodes, uint256 lowerBound, uint256 upperBound, uint256 providedPreviousReputationUID); + function disputeRounds(uint256 round, uint256 index) public view returns ( + bytes32 proposedNewRootHash, + uint256 nNodes, + uint256 lastResponseTimestamp, + uint256 challengeStepCompleted, + bytes32 jrh, + bytes32 intermediateReputationHash, + uint256 intermediateReputationNNodes, + uint256 jrhNnodes, + uint256 lowerBound, + uint256 upperBound, + uint256 providedPreviousReputationUID + ); /// @notice Get the hash for the corresponding entry. /// @param submitter The address that submitted the hash @@ -126,7 +138,14 @@ contract IReputationMiningCycle { /// @param _colonyAddress The address of the colony the reputation is being affected in /// @param _nParents The number of parent skills the skill defined by the skillId has /// @param _nChildren The number of child skills the skill defined by the skillId has - function appendReputationUpdateLog(address _user, int _amount, uint _skillId, address _colonyAddress, uint _nParents, uint _nChildren) public; + function appendReputationUpdateLog( + address _user, + int _amount, + uint _skillId, + address _colonyAddress, + uint _nParents, + uint _nChildren + ) public; /// @notice Get the length of the ReputationUpdateLog stored on this instance of the ReputationMiningCycle contract /// @return nUpdates diff --git a/contracts/PatriciaTree/PatriciaTreeProofs.sol b/contracts/PatriciaTree/PatriciaTreeProofs.sol index 5c747bed32..f48d98248c 100644 --- a/contracts/PatriciaTree/PatriciaTreeProofs.sol +++ b/contracts/PatriciaTree/PatriciaTreeProofs.sol @@ -5,6 +5,7 @@ pragma experimental "ABIEncoderV2"; import {Data} from "./Data.sol"; import {Bits} from "./Bits.sol"; + /// @title Functions related to checking Patricia Tree proofs /// @notice More info at: https://github.com/chriseth/patricia-trie contract PatriciaTreeProofs { @@ -12,7 +13,10 @@ contract PatriciaTreeProofs { using Data for Data.Edge; using Data for Data.Label; - function getImpliedRoot(bytes key, bytes value, uint branchMask, bytes32[] siblings) public view returns (bytes32) { // solium-disable-line security/no-assign-params + function getImpliedRoot(bytes key, bytes value, uint branchMask, bytes32[] siblings) public // solium-disable-line security/no-assign-params + view + returns (bytes32) + { Data.Label memory k = Data.Label(keccak256(key), 256); Data.Edge memory e; e.node = keccak256(value); diff --git a/contracts/ReputationMiningCycle.sol b/contracts/ReputationMiningCycle.sol index fa63915caa..53f721cd59 100644 --- a/contracts/ReputationMiningCycle.sol +++ b/contracts/ReputationMiningCycle.sol @@ -118,9 +118,12 @@ contract ReputationMiningCycle is PatriciaTreeProofs, DSMath { // Here, the minimum stake is 10**15. require(entryIndex <= IColonyNetwork(colonyNetworkAddress).getStakedBalance(msg.sender) / 10**15); require(entryIndex > 0); - if (reputationHashSubmissions[msg.sender].proposedNewRootHash != 0x0) { // If this user has submitted before during this round... - require(newHash == reputationHashSubmissions[msg.sender].proposedNewRootHash); // ...require that they are submitting the same hash ... - require(nNodes == reputationHashSubmissions[msg.sender].nNodes); // ...require that they are submitting the same number of nodes for that hash ... + // If this user has submitted before during this round... + if (reputationHashSubmissions[msg.sender].proposedNewRootHash != 0x0) { + // ...require that they are submitting the same hash ... + require(newHash == reputationHashSubmissions[msg.sender].proposedNewRootHash); + // ...require that they are submitting the same number of nodes for that hash ... + require(nNodes == reputationHashSubmissions[msg.sender].nNodes); require (submittedEntries[newHash][msg.sender][entryIndex] == false); // ... but not this exact entry } _; @@ -143,15 +146,15 @@ contract ReputationMiningCycle is PatriciaTreeProofs, DSMath { _; } - function getEntryHash(address submitter, uint256 entryIndex, bytes32 newHash) public pure returns (bytes32) { - return keccak256(abi.encodePacked(submitter, entryIndex, newHash)); - } - /// @notice Constructor for this contract. constructor() public { colonyNetworkAddress = msg.sender; } + function getEntryHash(address submitter, uint256 entryIndex, bytes32 newHash) public pure returns (bytes32) { + return keccak256(abi.encodePacked(submitter, entryIndex, newHash)); + } + function resetWindow() public { require(msg.sender == colonyNetworkAddress); reputationMiningWindowOpenTimestamp = now; @@ -216,7 +219,11 @@ contract ReputationMiningCycle is PatriciaTreeProofs, DSMath { { // TODO: Require some amount of time to have passed (i.e. people have had a chance to submit other hashes) Submission storage submission = disputeRounds[roundNumber][0]; - IColonyNetwork(colonyNetworkAddress).setReputationRootHash(submission.proposedNewRootHash, submission.nNodes, submittedHashes[submission.proposedNewRootHash][submission.nNodes]); + IColonyNetwork(colonyNetworkAddress).setReputationRootHash( + submission.proposedNewRootHash, + submission.nNodes, + submittedHashes[submission.proposedNewRootHash][submission.nNodes] + ); selfdestruct(colonyNetworkAddress); } @@ -296,12 +303,22 @@ contract ReputationMiningCycle is PatriciaTreeProofs, DSMath { //TODO: Can we do some deleting to make calling this as cheap as possible for people? } - function respondToBinarySearchForChallenge(uint256 round, uint256 idx, bytes jhIntermediateValue, uint256 branchMask, bytes32[] siblings) public { + function respondToBinarySearchForChallenge( + uint256 round, + uint256 idx, + bytes jhIntermediateValue, + uint256 branchMask, + bytes32[] siblings + ) public + { // TODO: Check this challenge is active. // This require is necessary, but not a sufficient check (need to check we have an opponent, at least). require(disputeRounds[round][idx].lowerBound!=disputeRounds[round][idx].upperBound); - uint256 targetNode = add(disputeRounds[round][idx].lowerBound, sub(disputeRounds[round][idx].upperBound, disputeRounds[round][idx].lowerBound) / 2); + uint256 targetNode = add( + disputeRounds[round][idx].lowerBound, + sub(disputeRounds[round][idx].upperBound, disputeRounds[round][idx].lowerBound) / 2 + ); bytes32 jrh = disputeRounds[round][idx].jrh; bytes memory targetNodeBytes = new bytes(32); @@ -373,9 +390,6 @@ contract ReputationMiningCycle is PatriciaTreeProofs, DSMath { if (u[U_REQUIRE_REPUTATION_CHECK]==1) { checkPreviousReputationInState( u, - _reputationKey, - reputationSiblings, - agreeStateReputationValue, agreeStateSiblings, previousNewReputationKey, previousNewReputationValue, @@ -420,7 +434,15 @@ contract ReputationMiningCycle is PatriciaTreeProofs, DSMath { disputeRounds[round][index].upperBound = disputeRounds[round][index].jrhNnodes; } - function appendReputationUpdateLog(address _user, int _amount, uint256 _skillId, address _colonyAddress, uint256 _nParents, uint256 _nChildren) public { + function appendReputationUpdateLog( + address _user, + int _amount, + uint256 _skillId, + address _colonyAddress, + uint256 _nParents, + uint256 _nChildren + ) public + { require(colonyNetworkAddress == msg.sender); uint reputationUpdateLogLength = reputationUpdateLog.length; uint nPreviousUpdates = 0; @@ -520,7 +542,7 @@ contract ReputationMiningCycle is PatriciaTreeProofs, DSMath { disputeRounds[round][opponentIdx].lastResponseTimestamp = now; } - function checkKey( uint256 round, uint256 idx, uint256 logEntryNumber, bytes memory _reputationKey) internal { + function checkKey(uint256 round, uint256 idx, uint256 logEntryNumber, bytes memory _reputationKey) internal view { // If the state transition we're checking is less than the number of nodes in the currently accepted state, it's a decay transition (TODO: not implemented) // Otherwise, look up the corresponding entry in the reputation log. uint256 updateNumber = disputeRounds[round][idx].lowerBound - 1; @@ -555,7 +577,11 @@ contract ReputationMiningCycle is PatriciaTreeProofs, DSMath { } } - function getExpectedSkillIdAndAddress( ReputationLogEntry storage logEntry, uint256 updateNumber ) internal returns (uint256 expectedSkillId, address expectedAddress) { + function getExpectedSkillIdAndAddress(ReputationLogEntry storage logEntry, uint256 updateNumber) + internal + view + returns (uint256 expectedSkillId, address expectedAddress) + { // Work out the expected userAddress and skillId for this updateNumber in this logEntry. if ((updateNumber - logEntry.nPreviousUpdates + 1) <= logEntry.nUpdates / 2 ) { // Then we're updating a colony-wide total, so we expect an address of 0x0 @@ -588,9 +614,17 @@ contract ReputationMiningCycle is PatriciaTreeProofs, DSMath { } } - function proveBeforeReputationValue(uint256[10] u, bytes _reputationKey, bytes32[] reputationSiblings, bytes agreeStateReputationValue, bytes32[] agreeStateSiblings) internal { + function proveBeforeReputationValue( + uint256[10] u, + bytes _reputationKey, + bytes32[] reputationSiblings, + bytes agreeStateReputationValue, + bytes32[] agreeStateSiblings + ) internal + { bytes32 jrh = disputeRounds[u[U_ROUND]][u[U_IDX]].jrh; - uint256 lastAgreeIdx = disputeRounds[u[U_ROUND]][u[U_IDX]].lowerBound - 1; // We binary searched to the first disagreement, so the last agreement is the one before. + // We binary searched to the first disagreement, so the last agreement is the one before. + uint256 lastAgreeIdx = disputeRounds[u[U_ROUND]][u[U_IDX]].lowerBound - 1; uint256 reputationValue; assembly { reputationValue := mload(add(agreeStateReputationValue, 32)) @@ -624,7 +658,14 @@ contract ReputationMiningCycle is PatriciaTreeProofs, DSMath { // where we don't prove anything with merkle proofs in this whole dance is here. } - function proveAfterReputationValue(uint256[10] u, bytes _reputationKey, bytes32[] reputationSiblings, bytes disagreeStateReputationValue, bytes32[] disagreeStateSiblings) internal { + function proveAfterReputationValue( + uint256[10] u, + bytes _reputationKey, + bytes32[] reputationSiblings, + bytes disagreeStateReputationValue, + bytes32[] disagreeStateSiblings + ) internal view + { bytes32 jrh = disputeRounds[u[U_ROUND]][u[U_IDX]].jrh; uint256 firstDisagreeIdx = disputeRounds[u[U_ROUND]][u[U_IDX]].lowerBound; bytes32 reputationRootHash = getImpliedRoot(_reputationKey, disagreeStateReputationValue, u[U_REPUTATION_BRANCH_MASK], reputationSiblings); @@ -644,11 +685,16 @@ contract ReputationMiningCycle is PatriciaTreeProofs, DSMath { require(jrh==impliedRoot, "colony-invalid-after-reputation-proof"); } - function performReputationCalculation(uint256[10] u, bytes agreeStateReputationValueBytes, bytes disagreeStateReputationValueBytes, bytes previousNewReputationValueBytes) internal { + function performReputationCalculation( + uint256[10] u, + bytes agreeStateReputationValueBytes, + bytes disagreeStateReputationValueBytes, + bytes previousNewReputationValueBytes + ) internal view + { // TODO: Possibility of decay calculation // TODO: Possibility of reputation loss - child reputations do not lose the whole of logEntry.amount, but the same fraction logEntry amount is of the user's reputation in skill given by logEntry.skillId ReputationLogEntry storage logEntry = reputationUpdateLog[u[U_LOG_ENTRY_NUMBER]]; - int256 amount; uint256 agreeStateReputationValue; uint256 disagreeStateReputationValue; uint256 agreeStateReputationUID; @@ -693,18 +739,21 @@ contract ReputationMiningCycle is PatriciaTreeProofs, DSMath { function checkPreviousReputationInState( uint256[10] u, - bytes _reputationKey, - bytes32[] reputationSiblings, - bytes agreeStateReputationValue, bytes32[] agreeStateSiblings, bytes previousNewReputationKey, bytes previousNewReputationValue, - bytes32[] previousNewReputationSiblings) - internal + bytes32[] previousNewReputationSiblings + ) internal view { - uint256 lastAgreeIdx = disputeRounds[u[U_ROUND]][u[U_IDX]].lowerBound - 1; // We binary searched to the first disagreement, so the last agreement is the one before - - bytes32 reputationRootHash = getImpliedRoot(previousNewReputationKey, previousNewReputationValue, u[U_PREVIOUS_NEW_REPUTATION_BRANCH_MASK], previousNewReputationSiblings); + // We binary searched to the first disagreement, so the last agreement is the one before + uint256 lastAgreeIdx = disputeRounds[u[U_ROUND]][u[U_IDX]].lowerBound - 1; + + bytes32 reputationRootHash = getImpliedRoot( + previousNewReputationKey, + previousNewReputationValue, + u[U_PREVIOUS_NEW_REPUTATION_BRANCH_MASK], + previousNewReputationSiblings + ); bytes memory jhLeafValue = new bytes(64); bytes memory lastAgreeIdxBytes = new bytes(32); assembly { @@ -727,7 +776,7 @@ contract ReputationMiningCycle is PatriciaTreeProofs, DSMath { disputeRounds[u[U_ROUND]][u[U_IDX]].provedPreviousReputationUID = previousReputationUID; } - function checkJRHProof1(bytes32 jrh, uint256 branchMask1, bytes32[] siblings1) internal { + function checkJRHProof1(bytes32 jrh, uint256 branchMask1, bytes32[] siblings1) internal view { // Proof 1 needs to prove that they started with the current reputation root hash bytes32 reputationRootHash = IColonyNetwork(colonyNetworkAddress).getReputationRootHash(); uint256 reputationRootHashNNodes = IColonyNetwork(colonyNetworkAddress).getReputationRootHashNNodes();