Skip to content

Instantly share code, notes, and snippets.

@pavoltravnik
Last active February 18, 2020 21:47
Show Gist options
  • Save pavoltravnik/6453dbda0468dc79679cf8b52d6ca7dc to your computer and use it in GitHub Desktop.
Save pavoltravnik/6453dbda0468dc79679cf8b52d6ca7dc to your computer and use it in GitHub Desktop.
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