Created
August 6, 2018 07:05
-
-
Save elenadimitrova/4967a3509d31e76d89dc72902643a218 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
pragma solidity ^0.4.23; | |
contract ReviewableTaskCollection { | |
function addTask() { | |
} | |
struct Task { | |
bytes32 specificationHash; | |
uint256 dueDate; | |
// Role Ids mapping to user addresses, using role Ids: | |
// 0 - task manager, 1 - task evaluator, 2 - task work | |
mapping (uint8 => address) roles; | |
// Maps task role ids (0,1,2) to payment amount | |
mapping (uint8 => uint256) payouts; | |
} | |
mapping (uint256 => Task) tasks; | |
uint256 taskCount; | |
uint8 constant MANAGER = 0; | |
uint8 constant EVALUATOR = 1; | |
uint8 constant WORKER = 2; | |
// Mapping task id to current "active" nonce for executing task changes | |
mapping (uint256 => uint256) taskChangeNonces; | |
// Mapping function signature to 2 task roles whose approval is needed to execute | |
mapping (bytes4 => uint8[2]) reviewers; | |
modifier self() { | |
require(address(this) == msg.sender); | |
_; | |
} | |
constructor() { | |
setFunctionReviewers(bytes4(keccak256("setTaskBrief(uint256,bytes32)")), MANAGER, WORKER); | |
setFunctionReviewers(bytes4(keccak256("setTaskDueDate(uint256,uint256)")), MANAGER, WORKER); | |
setFunctionReviewers(bytes4(keccak256("setTaskEvaluatorPayout(uint256,uint256)")), MANAGER, EVALUATOR); | |
setFunctionReviewers(bytes4(keccak256("setTaskWorkerPayout(uint256,uint256)")), MANAGER, WORKER); | |
} | |
function setFunctionReviewers(bytes4 _sig, uint8 _firstReviewer, uint8 _secondReviewer) | |
private | |
{ | |
uint8[2] memory _reviewers = [_firstReviewer, _secondReviewer]; | |
reviewers[_sig] = _reviewers; | |
} | |
function setTaskBrief(uint256 _id, bytes32 _specificationHash) public self { | |
tasks[_id].specificationHash = _specificationHash; | |
} | |
function setTaskDueDate(uint256 _id, uint256 _dueDate) public self { | |
tasks[_id].dueDate = _dueDate; | |
} | |
function setTaskEvaluatorPayout(uint256 _id, uint256 _amount) public self { | |
tasks[_id].payouts[EVALUATOR] = _amount; | |
} | |
function setTaskWorkerPayout(uint256 _id, uint256 _amount) public self { | |
tasks[_id].payouts[WORKER] = _amount; | |
} | |
function executeTaskChange(uint8[] _sigV, bytes32[] _sigR, bytes32[] _sigS, uint256 _value, bytes _data) public { | |
require(_sigR.length == 2); | |
bytes4 sig; | |
uint256 taskId; | |
(sig, taskId) = deconstructCall(_data); | |
bytes32 msgHash = keccak256(abi.encodePacked(address(this), address(this), _value, _data, taskChangeNonces[taskId])); | |
address[] memory reviewerAddresses = new address[](2); | |
for (uint i = 0; i < 2; i++) { | |
bytes32 txHash; | |
txHash = keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", msgHash)); | |
reviewerAddresses[i] = ecrecover(txHash, _sigV[i], _sigR[i], _sigS[i]); | |
} | |
require(reviewerAddresses[0] != reviewerAddresses[1]); | |
require( | |
reviewerAddresses[0] == tasks[taskId].roles[reviewers[sig][0]] || | |
reviewerAddresses[0] == tasks[taskId].roles[reviewers[sig][1]] | |
); | |
require( | |
reviewerAddresses[1] == tasks[taskId].roles[reviewers[sig][0]] || | |
reviewerAddresses[1] == tasks[taskId].roles[reviewers[sig][1]] | |
); | |
taskChangeNonces[taskId] += 1; | |
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) | |
} | |
} | |
// 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) { | |
assembly { | |
sig := mload(add(_data, 0x20)) | |
taskId := mload(add(_data, 0x24)) | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment