Last active
February 18, 2020 21:47
-
-
Save pavoltravnik/6453dbda0468dc79679cf8b52d6ca7dc 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.22 <0.7.0; | |
contract Arbitrust { | |
address[] arbitrators; | |
struct Contract { | |
bool exists; | |
uint limitArbiters; | |
bytes32 hashContract; // should be a hash of electronic document signed in electronic form | |
address[] partiesList; | |
mapping(address => bool) parties; | |
bytes32[] actionsList; | |
mapping(bytes32 => Action) actions; | |
} | |
struct Action { | |
bool exists; | |
bool finished; | |
uint order; | |
address creator; | |
bytes32 hashAction; | |
uint blockNumber; | |
uint voteCount; | |
string[] ipfsHashes; | |
bool[] votes; | |
bool vote; | |
bool voted; | |
address[] poolArbiters; | |
address[] selectedArbiters; | |
} | |
mapping(bytes32 => Contract) contracts; | |
mapping(address => bool) arbitratorsMap; | |
constructor() public { | |
// This will be a static list of arbitrators addresses. | |
arbitrators = [ | |
0x8bc74ff2860270BC3305eFC38F88dce4C15E53A1, | |
0x00e64163B622490a023AdB804D6c1AdF16F65D86, | |
0x2d6ECCf5A635064135579b128E75D68eEC204b16, | |
0x761661c64ab1188ECf4E707DafA4Dc368EFBc8C6, | |
0x63aDbB88c8321F690E86C946af257B8d6076242D | |
]; | |
for (uint i=0; i < arbitrators.length; i++) { | |
arbitratorsMap[arbitrators[i]] = true; | |
} | |
} | |
// ------------------- Create Contract ------------------- | |
// Sample data for debugging: | |
// 0x9b7ecc6eeb83abf9ade10fe38865df4499be3568dcc507ae2ec3b44989cb0093 | |
// ["0xA63ccf846e602bE40147c87dC6880510E3BD73BB","0xA63ccf846e602bE40147c87dC6880510E3BD73BB"] | |
function createContract(bytes32 _hashContract, address[] memory _partiesList, uint _limitArbiters) public { | |
require(_partiesList.length > 1 && _partiesList.length < 5, "Contract have to have at least 2 parties and maximum 4 parties."); | |
require(contracts[_hashContract].exists == false, "Contract already exists."); | |
require(_limitArbiters == 1 || _limitArbiters == 3, "Number of arbiters."); | |
contracts[_hashContract].exists = true; | |
contracts[_hashContract].hashContract = _hashContract; | |
contracts[_hashContract].partiesList = _partiesList; | |
contracts[_hashContract].limitArbiters = _limitArbiters; | |
for (uint i=0; i<_partiesList.length; i++) { | |
contracts[_hashContract].parties[_partiesList[i]] = true; | |
} | |
} | |
// function getContractPartiesListLength(bytes32 _hashContract) public view returns (uint256){ | |
// require(contracts[_hashContract].exists == true, "Contract doesn't exist."); | |
// return contracts[_hashContract].partiesList.length; | |
// } | |
function getArbitratorsLength() public view returns (uint) { | |
return arbitrators.length; | |
} | |
// ------------------- Create Action ------------------- | |
function createAction(bytes32 _hashContract, bytes32 _hashAction) public { | |
require(contracts[_hashContract].exists == true, "Contract doesn't exist."); | |
require(contracts[_hashContract].actions[_hashAction].exists == false, "Action already exists."); | |
require(contracts[_hashContract].parties[msg.sender] = true, "Only party can create Action"); | |
require(isPreviousActionFinished(_hashContract, _hashAction) == true, "Previous action has to be finished."); | |
contracts[_hashContract].actions[_hashAction].exists = true; | |
contracts[_hashContract].actions[_hashAction].creator = msg.sender; | |
contracts[_hashContract].actions[_hashAction].blockNumber = block.number; | |
contracts[_hashContract].actionsList.push(_hashAction); | |
contracts[_hashContract].actions[_hashAction].poolArbiters = arbitrators; | |
} | |
function getBlockNumber(bytes32 _hashContract, bytes32 _hashAction) public view returns (uint){ | |
return contracts[_hashContract].actions[_hashAction].blockNumber; | |
} | |
function getBlokHash(uint _blockNumber) public view returns (bytes32){ | |
return blockhash(_blockNumber); | |
} | |
function getSelectedOrderOfArbiter(bytes32 _hashContract, bytes32 _hashAction, uint _order) public view returns (uint){ | |
require(getBlockNumber(_hashContract,_hashAction) <= block.number, "You have to wait for other blocks"); | |
return ((uint(getBlokHash(getBlockNumber(_hashContract, _hashAction))) + _order) % (getArbitratorsLength() - _order)); | |
} | |
// Shelling point | |
function getSelectedOrderOfArbiterSchelling(bytes32 _hashContract, bytes32 _hashAction, address[] memory _arbitersLeftPool, uint _order) public view returns (uint){ | |
require(getBlockNumber(_hashContract,_hashAction) <= block.number, "You have to wait for other blocks"); | |
return ((uint(getBlokHash(getBlockNumber(_hashContract, _hashAction) + _order ))) % (_arbitersLeftPool.length)); | |
} | |
function xeligibleToVote(bytes32 _hashContract, bytes32 _hashAction) public view returns (uint[] memory){ | |
uint numOfArbiters = contracts[_hashContract].limitArbiters; | |
require(getBlockNumber(_hashContract,_hashAction) <= block.number + numOfArbiters, "You have to wait for other blocks"); | |
address[] memory poolArbitersPool; | |
uint[] memory order = new uint[](numOfArbiters); | |
uint selectedArbiter; | |
poolArbitersPool = arbitrators; | |
for (uint i=0; i< numOfArbiters; i++) { | |
selectedArbiter = getSelectedOrderOfArbiterSchelling(_hashContract, _hashAction, poolArbitersPool, i); | |
delete poolArbitersPool[selectedArbiter]; | |
order[i] = selectedArbiter; | |
} | |
return order; | |
} | |
// function xeligibleToVote(bytes32 _hashContract, bytes32 _hashAction) public view returns (uint[] memory){ | |
// uint numOfArbiters = contracts[_hashContract].limitArbiters; | |
// require(getBlockNumber(_hashContract,_hashAction) <= block.number + numOfArbiters, "You have to wait for other blocks"); | |
// address[] memory poolArbitersSelected = arbitrators; | |
// uint[] memory order; | |
// for (uint i=0; i< numOfArbiters; i++) { | |
// order.push(getSelectedOrderOfArbiterSchelling(_hashContract, _hashAction, poolArbitersSelected)); | |
// delete poolArbitersSelected[i]; | |
// } | |
// } | |
function getActionsLength(bytes32 _hashContract) public view returns(uint){ | |
return contracts[_hashContract].actionsList.length; | |
} | |
function isActionFinished(bytes32 _hashContract, bytes32 _hashAction) public view returns(bool){ | |
return contracts[_hashContract].actions[_hashAction].finished; | |
} | |
function getOrderAction (bytes32 _hashContract, bytes32 _hashAction) public view returns(uint){ | |
return contracts[_hashContract].actions[_hashAction].order; | |
} | |
function isPreviousActionFinished(bytes32 _hashContract, bytes32 _hashAction) public view returns(bool){ | |
// It must be a chain of finished Actions | |
if ( getOrderAction(_hashContract, _hashAction) < 1) { | |
return true; | |
} else { | |
return contracts[_hashContract].actions[contracts[_hashContract].actionsList[(getOrderAction(_hashContract, _hashAction) - 1)]].finished; | |
} | |
} | |
// ------------------- Voting ------------------- | |
function vote(bytes32 _hashContract, bytes32 _hashAction, bool _vote) public returns(bool){ | |
require(isActionFinished(_hashContract, _hashAction) == false, "Current action can not be finished."); | |
require(isPreviousActionFinished(_hashContract, _hashAction) == true, "Previous action has to be finished."); | |
require(msg.sender == arbitrators[getSelectedOrderOfArbiter(_hashContract,_hashAction, 0)], "You have no right to vote."); | |
contracts[_hashContract].actions[_hashAction].vote = _vote; | |
contracts[_hashContract].actions[_hashAction].voted = true; | |
contracts[_hashContract].actions[_hashAction].finished = true; | |
} | |
function getResult(bytes32 _hashContract, bytes32 _hashAction) public view returns(bool){ | |
require(contracts[_hashContract].actions[_hashAction].voted == true, "There is no vote yet."); | |
return contracts[_hashContract].actions[_hashAction].vote; | |
} | |
// ------------------- Delivery of documents ------------------- | |
function sendDocument(bytes32 _hashContract, bytes32 _hashAction, string memory _ipfsHash) public { | |
require(contracts[_hashContract].exists == true, "Contract doesn't exist."); | |
require((contracts[_hashContract].parties[msg.sender] == true || arbitratorsMap[msg.sender] == true), "Only party or arbitrator can submit document."); | |
contracts[_hashContract].actions[_hashAction].ipfsHashes.push(_ipfsHash); | |
} | |
function getDocumentsLength(bytes32 _hashContract, bytes32 _hashAction) public view returns (uint256){ | |
require(contracts[_hashContract].exists == true, "Contract doesn't exist."); | |
return contracts[_hashContract].actions[_hashAction].ipfsHashes.length; | |
} | |
function getDocumentIPFShash(bytes32 _hashContract, bytes32 _hashAction, uint256 _order) public view returns (string memory){ | |
require(contracts[_hashContract].exists == true, "Contract does't exist."); | |
return contracts[_hashContract].actions[_hashAction].ipfsHashes[_order]; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment