diff --git a/client/approver.js b/client/approver.js index e032b97..6e63d57 100644 --- a/client/approver.js +++ b/client/approver.js @@ -49,7 +49,7 @@ const checkRights = () => { let approverHTML = document.getElementById("approverHTML"); inherichain.methods .approverStatus(accounts[0]) - .call({from: accounts[0]}) + .call({ from: accounts[0] }) .then((values) => { if (!values) { window.alert("You don't have the rights of approver."); @@ -76,7 +76,7 @@ const initWalletAddress = () => { inherichain = initContract(address); inherichain.methods .heir() - .call({from: accounts[0]}) + .call({ from: accounts[0] }) .then((values) => { // Storing the data in localstorage (cache) localStorage.setItem("inherichainWalletAddress", address); @@ -123,7 +123,7 @@ const initApp = () => { } inherichain.methods .approveHeir(value) - .send({from: accounts[0]}) + .send({ from: accounts[0] }) .then(() => { approverAcceptanceStatus.innerHTML = "Success!"; }) @@ -139,7 +139,7 @@ const initApp = () => { e.preventDefault(); inherichain.methods .initiateCharity() - .send({from: accounts[0]}) + .send({ from: accounts[0] }) .then(() => { initiateCharityStatus.innerHTML = "Success!"; }) diff --git a/client/backupOwner.js b/client/backupOwner.js index 8f1c69c..1eeca51 100644 --- a/client/backupOwner.js +++ b/client/backupOwner.js @@ -49,7 +49,7 @@ const checkRights = () => { let backupOwnerHTML = document.getElementById("backupOwnerHTML"); inherichain.methods .backupOwner() - .call({from: accounts[0]}) + .call({ from: accounts[0] }) .then((values) => { if (values != accounts[0]) { window.alert("You don't have the rights of backup owner."); @@ -75,7 +75,7 @@ const initWalletAddress = () => { inherichain = initContract(address); inherichain.methods .heir() - .call({from: accounts[0]}) + .call({ from: accounts[0] }) .then((values) => { // Storing the data in localstorage (cache) localStorage.setItem("inherichainWalletAddress", address); @@ -112,7 +112,7 @@ const initApp = () => { const address = e.target.elements[0].value; inherichain.methods .updateOwner(address) - .send({from: accounts[0]}) + .send({ from: accounts[0] }) .then(() => { backupOwnerUpdateOwnerStatus.innerHTML = "Success!"; }) diff --git a/client/charity.js b/client/charity.js index 21bae40..26abb88 100644 --- a/client/charity.js +++ b/client/charity.js @@ -49,7 +49,7 @@ const checkRights = () => { let charityHTML = document.getElementById("charityHTML"); inherichain.methods .charity() - .call({from: accounts[0]}) + .call({ from: accounts[0] }) .then((values) => { if (values != accounts[0]) { window.alert("You don't have the rights of charity."); @@ -75,7 +75,7 @@ const initWalletAddress = () => { inherichain = initContract(address); inherichain.methods .heir() - .call({from: accounts[0]}) + .call({ from: accounts[0] }) .then((values) => { // Storing the data in localstorage (cache) localStorage.setItem("inherichainWalletAddress", address); @@ -124,7 +124,7 @@ const initApp = () => { approverDeadline, charityDeadline ) - .send({from: accounts[0]}) + .send({ from: accounts[0] }) .then(() => { accessWalletCharityStatus.innerHTML = `Success!`; }) diff --git a/client/heir.js b/client/heir.js index c75d1d2..9ad65bf 100644 --- a/client/heir.js +++ b/client/heir.js @@ -49,7 +49,7 @@ const checkRights = () => { let heirHTML = document.getElementById("heirHTML"); inherichain.methods .heir() - .call({from: accounts[0]}) + .call({ from: accounts[0] }) .then((values) => { if (values != accounts[0]) { window.alert("You don't have the rights of heir."); @@ -75,7 +75,7 @@ const initWalletAddress = () => { inherichain = initContract(address); inherichain.methods .heir() - .call({from: accounts[0]}) + .call({ from: accounts[0] }) .then((values) => { // Storing the data in localstorage (cache) localStorage.setItem("inherichainWalletAddress", address); @@ -125,7 +125,7 @@ const initApp = () => { e.preventDefault(); inherichain.methods .claimOwnership() - .send({from: accounts[0]}) + .send({ from: accounts[0] }) .then(() => { heirClaimOwnershipStatus.innerHTML = "Success!"; }) @@ -156,7 +156,7 @@ const initApp = () => { approverDeadline, charityDeadline ) - .send({from: accounts[0]}) + .send({ from: accounts[0] }) .then(() => { accessWalletApproverStatus.innerHTML = `Success!`; }) @@ -187,7 +187,7 @@ const initApp = () => { approverDeadline, charityDeadline ) - .send({from: accounts[0]}) + .send({ from: accounts[0] }) .then(() => { accessWalletDeadlineStatus.innerHTML = `Success!`; }) diff --git a/client/interact.js b/client/interact.js index 2f2aa4a..389304e 100644 --- a/client/interact.js +++ b/client/interact.js @@ -79,7 +79,7 @@ const initWalletAddress = () => { inherichain = initContract(address); inherichain.methods .heir() - .call({from: accounts[0]}) + .call({ from: accounts[0] }) .then((values) => { // Storing the data in localstorage (cache) localStorage.setItem("inherichainWalletAddress", address); @@ -136,7 +136,7 @@ const getData = () => { inherichain.methods .owner() - .call({from: accounts[0]}) + .call({ from: accounts[0] }) .then((values) => { currentOwner.innerHTML = values; }) @@ -147,7 +147,7 @@ const getData = () => { inherichain.methods .backupOwner() - .call({from: accounts[0]}) + .call({ from: accounts[0] }) .then((values) => { currentBackupOwner.innerHTML = values; }) @@ -159,7 +159,7 @@ const getData = () => { inherichain.methods .heir() - .call({from: accounts[0]}) + .call({ from: accounts[0] }) .then((values) => { currentHeir.innerHTML = values; }) @@ -170,7 +170,7 @@ const getData = () => { inherichain.methods .charity() - .call({from: accounts[0]}) + .call({ from: accounts[0] }) .then((values) => { currentCharity.innerHTML = values; }) @@ -181,7 +181,7 @@ const getData = () => { inherichain.methods .approversLength() - .call({from: accounts[0]}) + .call({ from: accounts[0] }) .then((values) => { approversLength = values; approvers.innerHTML = @@ -189,7 +189,7 @@ const getData = () => { for (let index = 0; index < approversLength; index++) { inherichain.methods .approvers(index) - .call({from: accounts[0]}) + .call({ from: accounts[0] }) .then((values) => { let temp = index + 1; approvers.innerHTML += @@ -212,7 +212,7 @@ const getData = () => { inherichain.methods .heirDeadline() - .call({from: accounts[0]}) + .call({ from: accounts[0] }) .then((values) => { deadline.innerHTML = convertSectoDay(values); }) @@ -223,7 +223,7 @@ const getData = () => { inherichain.methods .heirApprovedDeadline() - .call({from: accounts[0]}) + .call({ from: accounts[0] }) .then((values) => { approverDeadline.innerHTML = convertSectoDay(values); }) @@ -234,7 +234,7 @@ const getData = () => { inherichain.methods .charityDeadline() - .call({from: accounts[0]}) + .call({ from: accounts[0] }) .then((values) => { charityDeadline.innerHTML = convertSectoDay(values); }) @@ -245,7 +245,7 @@ const getData = () => { inherichain.methods .status() - .call({from: accounts[0]}) + .call({ from: accounts[0] }) .then((values) => { contractStatus.innerHTML = status[values]; }) @@ -256,7 +256,7 @@ const getData = () => { inherichain.methods .claimTime() - .call({from: accounts[0]}) + .call({ from: accounts[0] }) .then((values) => { claimTime.innerHTML = values; }) @@ -267,7 +267,7 @@ const getData = () => { inherichain.methods .voteCount() - .call({from: accounts[0]}) + .call({ from: accounts[0] }) .then((values) => { voteCount.innerHTML = values; }) diff --git a/client/owner.js b/client/owner.js index 060cedc..2bb0b56 100644 --- a/client/owner.js +++ b/client/owner.js @@ -43,7 +43,7 @@ const checkRights = () => { let ownerHTML = document.getElementById("ownerHTML"); inherichain.methods .owner() - .call({from: accounts[0]}) + .call({ from: accounts[0] }) .then((values) => { if (values != accounts[0]) { window.alert("You don't have the rights of owner."); @@ -69,7 +69,7 @@ const initWalletAddress = () => { inherichain = initContract(address); inherichain.methods .heir() - .call({from: accounts[0]}) + .call({ from: accounts[0] }) .then((values) => { // Storing the data in localstorage (cache) localStorage.setItem("inherichainWalletAddress", address); @@ -182,7 +182,7 @@ const initApp = () => { const address = e.target.elements[0].value; inherichain.methods .updateBackupOwner(address) - .send({from: accounts[0]}) + .send({ from: accounts[0] }) .then(() => { ownerUpdateBackupOwnerStatus.innerHTML = "Success!"; }) @@ -199,7 +199,7 @@ const initApp = () => { const address = e.target.elements[0].value; inherichain.methods .updateHeir(address) - .send({from: accounts[0]}) + .send({ from: accounts[0] }) .then(() => { ownerUpdateHeirStatus.innerHTML = "Success!"; }) @@ -216,7 +216,7 @@ const initApp = () => { const address = e.target.elements[0].value; inherichain.methods .updateCharity(address) - .send({from: accounts[0]}) + .send({ from: accounts[0] }) .then(() => { ownerUpdateCharityStatus.innerHTML = "Success!"; }) @@ -233,7 +233,7 @@ const initApp = () => { const address = e.target.elements[0].value; inherichain.methods .addApprover(address) - .send({from: accounts[0]}) + .send({ from: accounts[0] }) .then(() => { ownerAddApproverStatus.innerHTML = "Success!"; }) @@ -250,7 +250,7 @@ const initApp = () => { const address = e.target.elements[0].value; inherichain.methods .deleteApprover(address) - .send({from: accounts[0]}) + .send({ from: accounts[0] }) .then(() => { ownerDeleteApproverStatus.innerHTML = "Success!"; }) @@ -269,7 +269,7 @@ const initApp = () => { const charityDeadline = e.target.elements[2].value; inherichain.methods .updateDeadline(deadline, approverDeadline, charityDeadline) - .send({from: accounts[0]}) + .send({ from: accounts[0] }) .then(() => { ownerUpdateDeadlineStatus.innerHTML = "Success!"; }) @@ -287,7 +287,7 @@ const initApp = () => { const address = e.target.elements[1].value; inherichain.methods .transferETH(address, amount) - .send({from: accounts[0]}) + .send({ from: accounts[0] }) .then(() => { ownerTransferSomeETHStatus.innerHTML = "Success!"; }) @@ -304,7 +304,7 @@ const initApp = () => { const amount = web3.utils.toWei(e.target.elements[0].value); inherichain.methods .withdrawSomeETH(amount) - .send({from: accounts[0]}) + .send({ from: accounts[0] }) .then(() => { ownerWithdrawSomeETHStatus.innerHTML = "Success!"; }) @@ -320,7 +320,7 @@ const initApp = () => { e.preventDefault(); inherichain.methods .withdrawAllETH() - .send({from: accounts[0]}) + .send({ from: accounts[0] }) .then(() => { ownerWithdrawAllETHStatus.innerHTML = "Success!"; }) @@ -360,7 +360,7 @@ const initApp = () => { const bytecode = e.target.elements[1].value; inherichain.methods .deployContract(amount, bytecode) - .send({from: accounts[0], value: web3.utils.toWei(amount)}) + .send({ from: accounts[0], value: web3.utils.toWei(amount) }) .then(() => { ownerDeployContractStatus.innerHTML = "Success!"; }) diff --git a/contracts/Inherichain.sol b/contracts/Inherichain.sol index c311589..204ccdc 100644 --- a/contracts/Inherichain.sol +++ b/contracts/Inherichain.sol @@ -1,36 +1,60 @@ // SPDX-License-Identifier: UNLICENSED pragma solidity 0.7.0; +import "@kleros/erc-792/contracts/IArbitrator.sol"; +import "@kleros/erc-792/contracts/IArbitrable.sol"; +import "@kleros/erc-792/contracts/erc-1497/IEvidence.sol"; + /// @title A wallet which has inheritance built in on the Ethereum Blockchain. /// @author Shebin John /// @notice Use this contract as a hot wallet without any worry about passing it on to the next generation. /// @dev This is an alpha version, it is not yet audited, use with caution. -contract Inherichain { +contract Inherichain is IArbitrable, IEvidence { /* Contract Variables */ uint256 public voteCount; // This counts the yes votes for a heir claim. uint256 public claimTime; // The time when the claim was started. Default is zero. Set at the time of claim call. uint256 public charityTime; // The time when the charity was initiated. Set at the time of initiation. + uint256 public disputeTime; // The time when the dispute was initiated. Set at the time of initiation. + uint256 public arbitrationFee; // The ETH required for arbitration, in wei. // Below deadline can be changed at the time of contract creation. // Deadline also works for owner to reclaim if the heir colluded with approvers. uint256 public heirDeadline = 30 days; // Wait time for the heir without approvers approval. Default is 30 days. uint256 public heirApprovedDeadline = 7 days; // Wait time for the heir with approvers approval. Default is 7 days. uint256 public charityDeadline = 45 days; // Wait time for the charity with approver initiation. Default is 45 days. + uint256 public arbitrationFeeDepositTime = 7 days; + uint256 constant metaevidenceID = 0; // Unique identifier of meta-evidence. + uint256 constant evidenceGroupID = 0; // Unique identifier of the evidence group the evidence belongs to. address public owner; // The owner of this contract wallet. address public backupOwner; // The backup owner, same as owner of this wallet, but with a different address. - address public heir; // The heir of this contract. + address payable public heir; // The heir of this contract. address public charity; // The charity decided by the owner. address public charityInitiator; // The approver who initiated the charity. + address payable public disputeInitiator; // The approver who initiated the dispute. + IArbitrator public arbitrator; // Different types of Contract State. - enum Status {Initial, HeirClaimed, ApproverApproved, InitiatedCharity} + enum Status { + Initial, + HeirClaimed, + ClaimDisputed, + DisputeResultPending, + ApproverApproved, + ArbitratorApproved, + ArbitratorRejected, + InitiatedCharity + } Status public status; // The current status of the contract. + enum ClaimRulingOptions {RefusedToArbitrate, OwnerWins, HeirWins} + uint256 constant numberOfClaimRulingOptions = 2; // Notice that option 0 is reserved for RefusedToArbitrate. + mapping(address => bool) public approverStatus; // Whether the approver is valid or not. mapping(address => bool) public voted; // Whether the approver has voted or not. address[] public approvers; // Array of approver addresses. + bytes public arbitratorExtraData; // Extra data to set up the arbitration. /* Events */ @@ -39,19 +63,23 @@ contract Inherichain { /// @param _backupOwner The backup owner of this contract. /// @param _heir The heir of this contract. /// @param _charity The charity address preferred by Owner. + /// @param _arbitrator The arbitrator address for this contract wallet. /// @param _approverCount The no. of approvers added to the contract. /// @param _heirDeadline The wait time for heir to claim without approval from approvers. /// @param _heirApprovedDeadline The wait time for heir to claim with approval from approvers. /// @param _charityDeadline The wait time for charity to claim with initiation from approvers. + /// @param _arbitratorExtraData Extra data for the arbitrator. event contractCreated( address indexed _owner, address indexed _backupOwner, address indexed _heir, address _charity, + IArbitrator _arbitrator, uint256 _approverCount, uint256 _heirDeadline, uint256 _heirApprovedDeadline, - uint256 _charityDeadline + uint256 _charityDeadline, + bytes _arbitratorExtraData ); /// @dev This event is used to notify that the backup owner has been updated. @@ -72,6 +100,22 @@ contract Inherichain { /// @param _changer The one who made the change. It can be either owner or approver. event charityUpdated(address indexed _charity, address indexed _changer); + /// @dev The event is used to notify that the arbitrator has been updated. + /// @param _arbitrator The new arbitrator address. + /// @param _owner The owner who made this change. + event arbitratorUpdated( + IArbitrator indexed _arbitrator, + address indexed _owner + ); + + /// @dev The event is used to notify that the arbitrator has been updated. + /// @param _arbitrationFeeDepositTime The new arbitrator fee deposit time. + /// @param _owner The owner who made this change. + event arbitratorFeeDepositTimeUpdated( + uint256 indexed _arbitrationFeeDepositTime, + address indexed _owner + ); + /// @dev The event is used to notify a change in the deadline. /// @param _heirDeadline The wait time for heir to claim without approval from approvers. /// @param _heirApprovedDeadline The wait time for heir to claim with approval from approvers. @@ -131,6 +175,16 @@ contract Inherichain { uint256 _charityDeadline ); + /// @dev This event is used to notify the claim dispute has been started by arbitrator. + /// @param _funder The person who funded the Heir Dispute Arbitration Fee. + /// @param _arbitrator The Arbitrator. + /// @param _disputeID The ID created for this dispute. + event claimDisputeCreated( + address indexed _funder, + IArbitrator indexed _arbitrator, + uint256 indexed _disputeID + ); + /// @dev This event is used to notify the decision by the approver. /// @param _approver The address of the approver. /// @param _status The decision of the approver. @@ -140,6 +194,14 @@ contract Inherichain { /// @param _approveCount The no. of votes received by the heir for approval. event heirApproved(uint256 indexed _approveCount); + /// @dev The event is used to notify the heir claim is disputed. + /// @param _approver The one who initiated the process. + event heirDisputed(address indexed _approver); + + /// @dev The event is used to notify the initial status is reclaimed. + /// @param _initiator The one who initiated the process. + event initialStatusReclaimed(address indexed _initiator); + /// @dev The event is used to notify that charity process has been initiated. /// @param _approver The one who initiated the process. event charityInitiated(address indexed _approver); @@ -222,6 +284,9 @@ contract Inherichain { /// @param _backupOwner The backup owner of this contract. /// @param _heir The heir of this contract. /// @param _charity The charity address preferred by Owner. + /// @param _arbitrator The arbitrator address for this contract wallet. + /// @param _arbitratorExtraData Extra data for the arbitrator. + /// @param _metaevidence A link to the meta-evidence JSON. /// @param _approvers The approver address array added to the contract. /// @param _deadline The wait time for heir to claim without approval from approvers. /// @param _approverDeadline The wait time for heir to claim with approval from approvers. @@ -229,8 +294,11 @@ contract Inherichain { constructor( address _owner, address _backupOwner, - address _heir, + address payable _heir, address _charity, + IArbitrator _arbitrator, + bytes memory _arbitratorExtraData, + string memory _metaevidence, address[] memory _approvers, uint256 _deadline, uint256 _approverDeadline, @@ -266,6 +334,10 @@ contract Inherichain { charity = _charity; } + arbitrator = _arbitrator; + + arbitratorExtraData = _arbitratorExtraData; + for (uint256 user = 0; user < _approvers.length; user++) { // To add approver only once. require( @@ -288,15 +360,19 @@ contract Inherichain { charityDeadline = _charityDeadline; } + emit MetaEvidence(metaevidenceID, _metaevidence); + emit contractCreated( owner, _backupOwner, _heir, _charity, + _arbitrator, _approvers.length, heirDeadline, heirApprovedDeadline, - charityDeadline + charityDeadline, + _arbitratorExtraData ); } @@ -323,7 +399,7 @@ contract Inherichain { /// @notice Can be used to update the heir. /// @dev Can also be used if the heir tried to access contract before the owner demise along with approvers. /// @param _newHeir The address of the new heir. - function updateHeir(address _newHeir) + function updateHeir(address payable _newHeir) public onlyOwner checkAddress(_newHeir) @@ -362,6 +438,40 @@ contract Inherichain { emit charityUpdated(_charity, msg.sender); } + /// @notice Can be used to update the Arbitrator Address by the Owner. + /// @dev The arbitrator should follow ERC 792 and ERC 1497 standard. + /// @param _arbitrator The address of the Arbitrator. + function updateArbitrator(IArbitrator _arbitrator) + public + onlyOwner + checkAddress(address(_arbitrator)) + { + require( + status == Status.Initial, + "Can only update arbitrator in Initial State." + ); + arbitrator = _arbitrator; + emit arbitratorUpdated(_arbitrator, msg.sender); + } + + /// @notice Can be used to update the Arbitrator Fee Deposit Time. + /// @dev This is the time the heir have to deposit ETH for arbitration fee. + /// @param _arbitrationFeeDepositTime The time provided for deposit. + function updateArbitrationFeeDepositTime(uint256 _arbitrationFeeDepositTime) + public + onlyOwner + { + require( + status == Status.Initial, + "Can only update arbitrator in Initial State." + ); + arbitrationFeeDepositTime = _arbitrationFeeDepositTime; + emit arbitratorFeeDepositTimeUpdated( + _arbitrationFeeDepositTime, + msg.sender + ); + } + /// @notice Can be used to update the deadlines. /// @dev If only one deadline has to be updated, passing the other zero is enough. /// @param _deadline The deadline without approval. @@ -543,8 +653,21 @@ contract Inherichain { _claimOwnership(); } + /// @notice Can be used to reclaim the contract ownership after a rejected dispute from Arbitrator. + /// @dev Might be used when Owner in health crisis, and approver disputed and won. + function reclaimOwnership() public onlyHeir { + require(status == Status.ArbitratorRejected, "Claim already started."); + _claimOwnership(); + } + /// @notice This is an internal function which takes care of the heir claim process. function _claimOwnership() internal { + // The below is used when the owner is not able to prove he is alive due to some health issue or so. + // And the approver disputes the claim from heir. This ensures the heir can claim once in a while. + require( + claimTime < block.timestamp, + "Wait period after an arbitrator rejection or without dispute fee deposit is not over." + ); status = Status.HeirClaimed; claimTime = block.timestamp; if (charityTime != 0) { @@ -564,7 +687,7 @@ contract Inherichain { /// @param _charityDeadline The wait time for charity to claim with initiation from approvers. function accessOwnershipFromApprover( address _backupOwner, - address _heir, + address payable _heir, address[] memory _approvers, uint256 _deadline, uint256 _approverDeadline, @@ -588,6 +711,41 @@ contract Inherichain { ); } + /// @notice Can be used by heir after arbitrator approval. + /// @dev This function can only be called once arbitrator approval is attained. + /// @param _backupOwner The new backup owner of this contract. + /// @param _heir The new heir of this contract. + /// @param _approvers The new approver address array added to the contract. + /// @param _deadline The new wait time for heir to claim without approval from approvers. + /// @param _approverDeadline The new wait time for heir to claim with approval from approvers. + /// @param _charityDeadline The wait time for charity to claim with initiation from approvers. + function accessOwnershipFromArbitrator( + address _backupOwner, + address payable _heir, + address[] memory _approvers, + uint256 _deadline, + uint256 _approverDeadline, + uint256 _charityDeadline + ) public onlyHeir { + require( + status == Status.ArbitratorApproved, + "Arbitrator Approval Required." + ); + // This is just a precautionary wait time, removing it won't affect the security. + require( + block.timestamp - claimTime > heirApprovedDeadline, + "Deadline has not passed." + ); + _accessOwnership( + _backupOwner, + _heir, + _approvers, + _deadline, + _approverDeadline, + _charityDeadline + ); + } + /// @notice Can be used by heir after deadline has been passed. /// @dev This function can be called with or without the approver approvals after the deadline. /// @param _backupOwner The new backup owner of this contract. @@ -598,7 +756,7 @@ contract Inherichain { /// @param _charityDeadline The wait time for charity to claim with initiation from approvers. function accessOwnershipAfterDeadline( address _backupOwner, - address _heir, + address payable _heir, address[] memory _approvers, uint256 _deadline, uint256 _approverDeadline, @@ -627,7 +785,7 @@ contract Inherichain { /// @param _charityDeadline The wait time for charity to claim with initiation from approvers. function _accessOwnership( address _backupOwner, - address _heir, + address payable _heir, address[] memory _approvers, uint256 _deadline, uint256 _approverDeadline, @@ -656,6 +814,27 @@ contract Inherichain { ); } + /// @notice Can be used to pay the arbitration fee for Heir, if approver disputed. + /// @dev Can be paid by anyone. + function payArbitrationFeeForHeir() public payable { + require(status == Status.ClaimDisputed, "Claim is not disputed."); + uint256 cost = arbitrator.arbitrationCost(arbitratorExtraData); + require(msg.value >= cost, "Arbitration Fee insufficient."); + if (msg.value < arbitrationFee) { + // This ensures that atleast a minimum arbitration fee is returned to winner. + // (in case the fee changes during dispute) + arbitrationFee = msg.value; + } + // The arbitrator will check if the fee send is adequate and refund the remaining. + uint256 disputeID = + arbitrator.createDispute{value: cost}( + numberOfClaimRulingOptions, + arbitratorExtraData + ); + status = Status.DisputeResultPending; + emit claimDisputeCreated(msg.sender, arbitrator, disputeID); + } + /* Approver Functions */ /// @notice Can be used to approve or reject a claim request by heir. @@ -675,6 +854,42 @@ contract Inherichain { emit heirApproval(msg.sender, _acceptance); } + /// @notice Can be used to dispute a Heir Claim, or dispute incorrect heir acceptance. + /// @dev Call scope limited to Approvers to limit spamming. + function disputeHeir() public payable onlyApprover { + require( + status == Status.HeirClaimed || status == Status.ApproverApproved, + "Claim has not started yet or Claim was approved incorrectly." + ); + uint256 cost = arbitrator.arbitrationCost(arbitratorExtraData); + require(msg.value >= cost, "Arbitration Fee not sufficient."); + // It is the responsibility of the ethereum address to receive the remaining eth back. + msg.sender.send(cost - msg.value); + status = Status.ClaimDisputed; + disputeTime = block.timestamp; + arbitrationFee = cost; + disputeInitiator = msg.sender; + emit heirDisputed(msg.sender); + } + + /// @notice Can be used by anyone to stop the claim process by heir after arbitration fee deposit time ends. + /// @dev Can be used only after approver made a dispute to claim. + function reclaimInitialStatus() public { + require(status == Status.ClaimDisputed, "Claim is not disputed."); + require( + block.timestamp - disputeTime > arbitrationFeeDepositTime, + "The heir Arbitration fee deposit time not over." + ); + claimTime = block.timestamp + heirDeadline; // This ensures the heir can claim once in a while. + // It is the responsibility of the ethereum address to receive the remaining eth back. + disputeInitiator.send(arbitrationFee); + status = Status.Initial; + disputeTime = 0; + arbitrationFee = 0; + disputeInitiator = address(0); + emit initialStatusReclaimed(msg.sender); + } + /// @notice Can be used to initiate the charity process. /// @dev Called when owner and heir are no more. function initiateCharity() public onlyApprover { @@ -701,7 +916,7 @@ contract Inherichain { /// @param _charityDeadline The wait time for charity to claim with initiation from approvers. function accessOwnershipFromCharity( address _backupOwner, - address _heir, + address payable _heir, address[] memory _approvers, uint256 _deadline, uint256 _approverDeadline, @@ -729,6 +944,59 @@ contract Inherichain { ); } + /* Arbitrator */ + + /// @notice Give a ruling for a dispute. Must be called by the arbitrator. + /// @param _disputeID ID of the dispute in the Arbitrator contract. + /// @param _ruling Result of arbitration (including refused to arbitrate). + function rule(uint256 _disputeID, uint256 _ruling) public override { + require( + msg.sender == address(arbitrator), + "Only the arbitrator can execute this." + ); + require( + status == Status.DisputeResultPending, + "There should be a dispute to execute a ruling." + ); + require(_ruling <= numberOfClaimRulingOptions, "Ruling out of bounds!"); + if (_ruling == 1) { + status = Status.ArbitratorApproved; + heir.send(arbitrationFee); + } else if (_ruling == 2) { + status = Status.ArbitratorRejected; + disputeInitiator.send(arbitrationFee); + } else { + status = Status.Initial; + // If wei is an odd number, then it will be added to the owner assets. + uint256 half = arbitrationFee / 2; + heir.send(half); + disputeInitiator.send(half); + } + disputeTime = 0; + arbitrationFee = 0; + disputeInitiator = address(0); + emit Ruling(arbitrator, _disputeID, _ruling); + } + + /* General Functions */ + + /// @notice Can be used to submit any evidence during the Claim Dispute Period. + /// @dev Only owner, heir or approver can call this function. + /// @param _evidence A URI to the evidence JSON file whose name should be its keccak256 hash followed by .json. + function submitEvidence(string memory _evidence) public { + require( + status == Status.ClaimDisputed, + "Contract is not in Disputed state." + ); + require( + msg.sender == heir || + msg.sender == owner || + approverStatus[msg.sender], + "Third parties are not allowed to submit evidence." + ); + emit Evidence(arbitrator, evidenceGroupID, msg.sender, _evidence); + } + /* Read/Getter Functions */ /// @notice To get the length of the approvers array. diff --git a/contracts/Kleros/CentralizedArbitratorWithAppeal.sol b/contracts/Kleros/CentralizedArbitratorWithAppeal.sol new file mode 100644 index 0000000..aa67596 --- /dev/null +++ b/contracts/Kleros/CentralizedArbitratorWithAppeal.sol @@ -0,0 +1,128 @@ +/** + * @authors: [@ferittuncer, @hbarcelos] + * @reviewers: [] + * @auditors: [] + * @bounties: [] + * @deployments: [] + * SPDX-License-Identifier: MIT + */ +pragma solidity >=0.7; + +import "@kleros/erc-792/contracts/IArbitrator.sol"; + +contract CentralizedArbitratorWithAppeal is IArbitrator { + address public owner = msg.sender; + uint256 constant appealWindow = 3 minutes; + uint256 internal arbitrationFee = 1e15; + + struct Dispute { + IArbitrable arbitrated; + uint256 choices; + uint256 ruling; + DisputeStatus status; + uint256 appealPeriodStart; + uint256 appealPeriodEnd; + uint256 appealCount; + } + + Dispute[] public disputes; + + function arbitrationCost(bytes memory _extraData) public override view returns (uint256) { + return arbitrationFee; + } + + function appealCost(uint256 _disputeID, bytes memory _extraData) public override view returns (uint256) { + return arbitrationFee * (2**(disputes[_disputeID].appealCount)); + } + + function setArbitrationCost(uint256 _newCost) public { + arbitrationFee = _newCost; + } + + function createDispute(uint256 _choices, bytes memory _extraData) + public + override + payable + returns (uint256 disputeID) + { + require(msg.value >= arbitrationCost(_extraData), "Not enough ETH to cover arbitration costs."); + + disputes.push( + Dispute({ + arbitrated: IArbitrable(msg.sender), + choices: _choices, + ruling: uint256(-1), + status: DisputeStatus.Waiting, + appealPeriodStart: 0, + appealPeriodEnd: 0, + appealCount: 0 + }) + ); + + emit DisputeCreation(disputeID, IArbitrable(msg.sender)); + + disputeID = disputes.length - 1; + } + + function disputeStatus(uint256 _disputeID) public override view returns (DisputeStatus status) { + Dispute storage dispute = disputes[_disputeID]; + if (disputes[_disputeID].status == DisputeStatus.Appealable && block.timestamp >= dispute.appealPeriodEnd) + return DisputeStatus.Solved; + else return disputes[_disputeID].status; + } + + function currentRuling(uint256 _disputeID) public override view returns (uint256 ruling) { + ruling = disputes[_disputeID].ruling; + } + + function giveRuling(uint256 _disputeID, uint256 _ruling) public { + require(msg.sender == owner, "Only the owner of this contract can execute rule function."); + + Dispute storage dispute = disputes[_disputeID]; + + require(_ruling <= dispute.choices, "Ruling out of bounds!"); + require(dispute.status == DisputeStatus.Waiting, "Dispute is not awaiting arbitration."); + + dispute.ruling = _ruling; + dispute.status = DisputeStatus.Appealable; + dispute.appealPeriodStart = block.timestamp; + dispute.appealPeriodEnd = dispute.appealPeriodStart + appealWindow; + + emit AppealPossible(_disputeID, dispute.arbitrated); + } + + function executeRuling(uint256 _disputeID) public { + Dispute storage dispute = disputes[_disputeID]; + require(dispute.status == DisputeStatus.Appealable, "The dispute must be appealable."); + require( + block.timestamp > dispute.appealPeriodEnd, + "The dispute must be executed after its appeal period has ended." + ); + + dispute.status = DisputeStatus.Solved; + dispute.arbitrated.rule(_disputeID, dispute.ruling); + } + + function appeal(uint256 _disputeID, bytes memory _extraData) public override payable { + Dispute storage dispute = disputes[_disputeID]; + dispute.appealCount++; + + require(msg.value >= appealCost(_disputeID, _extraData), "Not enough ETH to cover appeal costs."); + + require(dispute.status == DisputeStatus.Appealable, "The dispute must be appealable."); + require( + block.timestamp < dispute.appealPeriodEnd, + "The appeal must occur before the end of the appeal period." + ); + + dispute.status = DisputeStatus.Waiting; + + emit AppealDecision(_disputeID, dispute.arbitrated); + } + + function appealPeriod(uint256 _disputeID) public override view returns (uint256 start, uint256 end) { + Dispute storage dispute = disputes[_disputeID]; + + return (dispute.appealPeriodStart, dispute.appealPeriodEnd); + } +} diff --git a/contracts/Kleros/SimpleCentralizedArbitrator.sol b/contracts/Kleros/SimpleCentralizedArbitrator.sol new file mode 100644 index 0000000..95df424 --- /dev/null +++ b/contracts/Kleros/SimpleCentralizedArbitrator.sol @@ -0,0 +1,84 @@ +/** + * @authors: [@ferittuncer, @hbarcelos] + * @reviewers: [] + * @auditors: [] + * @bounties: [] + * @deployments: [] + * SPDX-License-Identifier: MIT + */ +pragma solidity >=0.7; + +import "@kleros/erc-792/contracts/IArbitrator.sol"; + +contract SimpleCentralizedArbitrator is IArbitrator { + address public owner = msg.sender; + + struct Dispute { + IArbitrable arbitrated; + uint256 choices; + uint256 ruling; + DisputeStatus status; + } + + Dispute[] public disputes; + + function arbitrationCost(bytes memory _extraData) public override pure returns (uint256) { + return 0.1 ether; + } + + function appealCost(uint256 _disputeID, bytes memory _extraData) public override pure returns (uint256) { + return 2**250; // An unaffordable amount which practically avoids appeals. + } + + function createDispute(uint256 _choices, bytes memory _extraData) + public + override + payable + returns (uint256 disputeID) + { + require(msg.value >= arbitrationCost(_extraData), "Not enough ETH to cover arbitration costs."); + + disputes.push( + Dispute({ + arbitrated: IArbitrable(msg.sender), + choices: _choices, + ruling: uint256(-1), + status: DisputeStatus.Waiting + }) + ); + + disputeID = disputes.length - 1; + emit DisputeCreation(disputeID, IArbitrable(msg.sender)); + } + + function disputeStatus(uint256 _disputeID) public override view returns (DisputeStatus status) { + status = disputes[_disputeID].status; + } + + function currentRuling(uint256 _disputeID) public override view returns (uint256 ruling) { + ruling = disputes[_disputeID].ruling; + } + + function rule(uint256 _disputeID, uint256 _ruling) public { + require(msg.sender == owner, "Only the owner of this contract can execute rule function."); + + Dispute storage dispute = disputes[_disputeID]; + + require(_ruling <= dispute.choices, "Ruling out of bounds!"); + require(dispute.status == DisputeStatus.Waiting, "Dispute is not awaiting arbitration."); + + dispute.ruling = _ruling; + dispute.status = DisputeStatus.Solved; + + msg.sender.send(arbitrationCost("")); + dispute.arbitrated.rule(_disputeID, _ruling); + } + + function appeal(uint256 _disputeID, bytes memory _extraData) public override payable { + require(msg.value >= appealCost(_disputeID, _extraData), "Not enough ETH to cover arbitration costs."); + } + + function appealPeriod(uint256 _disputeID) public override pure returns (uint256 start, uint256 end) { + return (0, 0); + } +} diff --git a/docs/Inherichain.md b/docs/Inherichain.md index 9a8212b..ca2e891 100644 --- a/docs/Inherichain.md +++ b/docs/Inherichain.md @@ -43,7 +43,7 @@ Check if the contract have enough balance. -### `constructor(address _owner, address _backupOwner, address _heir, address _charity, address[] _approvers, uint256 _deadline, uint256 _approverDeadline, uint256 _charityDeadline)` (public) +### `constructor(address _owner, address _backupOwner, address payable _heir, address _charity, contract IArbitrator _arbitrator, bytes _arbitratorExtraData, string _metaevidence, address[] _approvers, uint256 _deadline, uint256 _approverDeadline, uint256 _charityDeadline)` (public) @@ -58,7 +58,7 @@ Can be used to update the backup owner. Owner and the new backup owner cannot be the same. -### `updateHeir(address _newHeir)` (public) +### `updateHeir(address payable _newHeir)` (public) Can be used to update the heir. @@ -74,6 +74,22 @@ Can be used to update the Charity Address by the Owner. Also reset a initiated c If the charity address is predetermined by owner, then approver cannot nominate a charity. +### `updateArbitrator(contract IArbitrator _arbitrator)` (public) + +Can be used to update the Arbitrator Address by the Owner. + + +The arbitrator should follow ERC 792 and ERC 1497 standard. + + +### `updateArbitrationFeeDepositTime(uint256 _arbitrationFeeDepositTime)` (public) + +Can be used to update the Arbitrator Fee Deposit Time. + + +This is the time the heir have to deposit ETH for arbitration fee. + + ### `updateDeadline(uint256 _deadline, uint256 _approverDeadline, uint256 _charityDeadline)` (public) Can be used to update the deadlines. @@ -154,13 +170,20 @@ Can be used to claim the contract ownership. This function starts the claim process for heir. +### `reclaimOwnership()` (public) + +Can be used to reclaim the contract ownership after a rejected dispute from Arbitrator. + + +Might be used when Owner in health crisis, and approver disputed and won. + ### `_claimOwnership()` (internal) This is an internal function which takes care of the heir claim process. -### `accessOwnershipFromApprover(address _backupOwner, address _heir, address[] _approvers, uint256 _deadline, uint256 _approverDeadline, uint256 _charityDeadline)` (public) +### `accessOwnershipFromApprover(address _backupOwner, address payable _heir, address[] _approvers, uint256 _deadline, uint256 _approverDeadline, uint256 _charityDeadline)` (public) Can be used by heir after approver approval. @@ -168,7 +191,15 @@ Can be used by heir after approver approval. This function can only be called once majority vote is attained. -### `accessOwnershipAfterDeadline(address _backupOwner, address _heir, address[] _approvers, uint256 _deadline, uint256 _approverDeadline, uint256 _charityDeadline)` (public) +### `accessOwnershipFromArbitrator(address _backupOwner, address payable _heir, address[] _approvers, uint256 _deadline, uint256 _approverDeadline, uint256 _charityDeadline)` (public) + +Can be used by heir after arbitrator approval. + + +This function can only be called once arbitrator approval is attained. + + +### `accessOwnershipAfterDeadline(address _backupOwner, address payable _heir, address[] _approvers, uint256 _deadline, uint256 _approverDeadline, uint256 _charityDeadline)` (public) Can be used by heir after deadline has been passed. @@ -176,13 +207,20 @@ Can be used by heir after deadline has been passed. This function can be called with or without the approver approvals after the deadline. -### `_accessOwnership(address _backupOwner, address _heir, address[] _approvers, uint256 _deadline, uint256 _approverDeadline, uint256 _charityDeadline)` (internal) +### `_accessOwnership(address _backupOwner, address payable _heir, address[] _approvers, uint256 _deadline, uint256 _approverDeadline, uint256 _charityDeadline)` (internal) This is an internal function which takes care of the ownership transfer tasks. +### `payArbitrationFeeForHeir()` (public) + +Can be used to pay the arbitration fee for Heir, if approver disputed. + + +Can be paid by anyone. + ### `approveHeir(bool _acceptance)` (public) Can be used to approve or reject a claim request by heir. @@ -191,6 +229,20 @@ Can be used to approve or reject a claim request by heir. Only callable if claim has started and approver not already voted. +### `disputeHeir()` (public) + +Can be used to dispute a Heir Claim, or dispute incorrect heir acceptance. + + +Call scope limited to Approvers to limit spamming. + +### `reclaimInitialStatus()` (public) + +Can be used by anyone to stop the claim process by heir after arbitration fee deposit time ends. + + +Can be used only after approver made a dispute to claim. + ### `initiateCharity()` (public) Can be used to initiate the charity process. @@ -198,7 +250,7 @@ Can be used to initiate the charity process. Called when owner and heir are no more. -### `accessOwnershipFromCharity(address _backupOwner, address _heir, address[] _approvers, uint256 _deadline, uint256 _approverDeadline, uint256 _charityDeadline)` (public) +### `accessOwnershipFromCharity(address _backupOwner, address payable _heir, address[] _approvers, uint256 _deadline, uint256 _approverDeadline, uint256 _charityDeadline)` (public) Can be used by charity after deadline has been passed. @@ -206,6 +258,21 @@ Can be used by charity after deadline has been passed. This function can only be called after the approver has initiated the charity. +### `rule(uint256 _disputeID, uint256 _ruling)` (public) + +Give a ruling for a dispute. Must be called by the arbitrator. + + + + +### `submitEvidence(string _evidence)` (public) + +Can be used to submit any evidence during the Claim Dispute Period. + + +Only owner, heir or approver can call this function. + + ### `approversLength() → uint256 count` (public) To get the length of the approvers array. @@ -215,7 +282,7 @@ Used for testing and frontend. -### `contractCreated(address _owner, address _backupOwner, address _heir, address _charity, uint256 _approverCount, uint256 _heirDeadline, uint256 _heirApprovedDeadline, uint256 _charityDeadline)` +### `contractCreated(address _owner, address _backupOwner, address _heir, address _charity, contract IArbitrator _arbitrator, uint256 _approverCount, uint256 _heirDeadline, uint256 _heirApprovedDeadline, uint256 _charityDeadline, bytes _arbitratorExtraData)` @@ -243,6 +310,20 @@ The event is used to notify that the heir has been updated and any claim has bee The event is used to notify that the charity has been updated. +### `arbitratorUpdated(contract IArbitrator _arbitrator, address _owner)` + + + +The event is used to notify that the arbitrator has been updated. + + +### `arbitratorFeeDepositTimeUpdated(uint256 _arbitrationFeeDepositTime, address _owner)` + + + +The event is used to notify that the arbitrator has been updated. + + ### `deadlineUpdated(uint256 _heirDeadline, uint256 _heirApprovedDeadline, uint256 _charityDeadline, address _owner)` @@ -286,6 +367,13 @@ This event is emitted when the heir has made a request for access to the contrac This event is used to notify when the heir has received the access to the contract. +### `claimDisputeCreated(address _funder, contract IArbitrator _arbitrator, uint256 _disputeID)` + + + +This event is used to notify the claim dispute has been started by arbitrator. + + ### `heirApproval(address _approver, bool _status)` @@ -300,6 +388,20 @@ This event is used to notify the decision by the approver. This event is used to notify when the approval is successful. +### `heirDisputed(address _approver)` + + + +The event is used to notify the heir claim is disputed. + + +### `initialStatusReclaimed(address _initiator)` + + + +The event is used to notify the initial status is reclaimed. + + ### `charityInitiated(address _approver)` diff --git a/docs/Kleros/CentralizedArbitratorWithAppeal.md b/docs/Kleros/CentralizedArbitratorWithAppeal.md new file mode 100644 index 0000000..0cc2092 --- /dev/null +++ b/docs/Kleros/CentralizedArbitratorWithAppeal.md @@ -0,0 +1,68 @@ +## `CentralizedArbitratorWithAppeal` + + + + + + +### `arbitrationCost(bytes _extraData) → uint256` (public) + + + + + +### `appealCost(uint256 _disputeID, bytes _extraData) → uint256` (public) + + + + + +### `setArbitrationCost(uint256 _newCost)` (public) + + + + + +### `createDispute(uint256 _choices, bytes _extraData) → uint256 disputeID` (public) + + + + + +### `disputeStatus(uint256 _disputeID) → enum IArbitrator.DisputeStatus status` (public) + + + + + +### `currentRuling(uint256 _disputeID) → uint256 ruling` (public) + + + + + +### `giveRuling(uint256 _disputeID, uint256 _ruling)` (public) + + + + + +### `executeRuling(uint256 _disputeID)` (public) + + + + + +### `appeal(uint256 _disputeID, bytes _extraData)` (public) + + + + + +### `appealPeriod(uint256 _disputeID) → uint256 start, uint256 end` (public) + + + + + + diff --git a/docs/Kleros/SimpleCentralizedArbitrator.md b/docs/Kleros/SimpleCentralizedArbitrator.md new file mode 100644 index 0000000..84ddae1 --- /dev/null +++ b/docs/Kleros/SimpleCentralizedArbitrator.md @@ -0,0 +1,56 @@ +## `SimpleCentralizedArbitrator` + + + + + + +### `arbitrationCost(bytes _extraData) → uint256` (public) + + + + + +### `appealCost(uint256 _disputeID, bytes _extraData) → uint256` (public) + + + + + +### `createDispute(uint256 _choices, bytes _extraData) → uint256 disputeID` (public) + + + + + +### `disputeStatus(uint256 _disputeID) → enum IArbitrator.DisputeStatus status` (public) + + + + + +### `currentRuling(uint256 _disputeID) → uint256 ruling` (public) + + + + + +### `rule(uint256 _disputeID, uint256 _ruling)` (public) + + + + + +### `appeal(uint256 _disputeID, bytes _extraData)` (public) + + + + + +### `appealPeriod(uint256 _disputeID) → uint256 start, uint256 end` (public) + + + + + + diff --git a/migrations/2_inherichain.js b/migrations/2_inherichain.js index 578f1c9..5d0b102 100644 --- a/migrations/2_inherichain.js +++ b/migrations/2_inherichain.js @@ -1,4 +1,5 @@ const Inherichain = artifacts.require("Inherichain"); +const SimpleCentralizedArbitrator = artifacts.require("SimpleCentralizedArbitrator"); module.exports = function (deployer, network, accounts) { var owner, @@ -17,15 +18,21 @@ module.exports = function (deployer, network, accounts) { approverTwo, approverThree, ] = accounts; - deployer.deploy( - Inherichain, - owner, - backupOwner, - heir, - charity, - [approverOne, approverTwo, approverThree], - 0, - 0, - 0 - ); + deployer.deploy(SimpleCentralizedArbitrator) + .then(function() { + return deployer.deploy( + Inherichain, + owner, + backupOwner, + heir, + charity, + SimpleCentralizedArbitrator.address, + `0x0`, + "", + [approverOne, approverTwo, approverThree], + 0, + 0, + 0 + ); + }); }; diff --git a/migrations/4_simpleERC20.js b/migrations/4_simpleERC20.js index 3f3bc7d..030ce88 100644 --- a/migrations/4_simpleERC20.js +++ b/migrations/4_simpleERC20.js @@ -3,5 +3,5 @@ const SimpleERC20 = artifacts.require("SimpleERC20"); module.exports = function (deployer, network, accounts) { var owner, backupOwner, heir; [owner, backupOwner, heir] = accounts; - deployer.deploy(SimpleERC20, 10000, {from: heir}); + deployer.deploy(SimpleERC20, 10000, { from: heir }); }; diff --git a/package.json b/package.json index d4ff3c6..1efe998 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "inherichain", - "version": "2.4.4", + "version": "3.0.0", "description": "A wallet which has inheritance built in on the Ethereum Blockchain.", "main": "truffle-config.js", "directories": { @@ -10,6 +10,7 @@ "lint": "solhint 'contracts/**/*.sol'", "prettier": "prettier --write **/*.sol **/*.js", "documentation": "solidity-docgen --solc-module ./node_modules/solc", + "migrate": "truffle compile && truffle migrate --reset", "test": "truffle test --network development", "coverage": "truffle run coverage --file='test/*.test.js' --network coverage", "start": "node server.js", @@ -32,6 +33,7 @@ }, "homepage": "https://github.com/remedcu/Inherichain#readme", "dependencies": { + "@kleros/erc-792": "^7.0.0", "@openzeppelin/test-helpers": "^0.5.7", "ganache-cli": "^6.12.0", "solc": "0.7.0", diff --git a/test/approver.test.js b/test/approver.test.js index b29c664..b8ae33a 100644 --- a/test/approver.test.js +++ b/test/approver.test.js @@ -1,6 +1,7 @@ const Inherichain = artifacts.require("Inherichain"); const Demo = artifacts.require("Demo"); const SimpleERC20 = artifacts.require("SimpleERC20"); +const SimpleCentralizedArbitrator = artifacts.require("SimpleCentralizedArbitrator"); const { time, // Convert different time units to seconds. Available helpers are: seconds, minutes, hours, days, weeks and years. @@ -20,6 +21,7 @@ contract("Inherichain (Approver Functions)", (accounts) => { let inherichain = null; let demo = null; let simpleERC20 = null; + let arbitrator = null; let owner, backupOwner, heir, @@ -33,10 +35,16 @@ contract("Inherichain (Approver Functions)", (accounts) => { newApproverTwo, newApproverThree, outsider; + const arbitratorExtraData = `0x0`; + const metaEvidence = ""; const sInitial = 0; const sHeirClaimed = 1; - const sApproverApproved = 2; - const sInitiatedCharity = 3; + const sClaimDisputed = 2; + const sDisputeResultPending =3; + const sApproverApproved = 4; + const sArbitratorApproved = 5; + const sArbitratorRejected = 6; + const sInitiatedCharity = 7; const deadline = time.duration.days(30).toNumber(); const approverDeadline = time.duration.days(7).toNumber(); const charityDeadline = time.duration.days(45).toNumber(); @@ -73,6 +81,7 @@ contract("Inherichain (Approver Functions)", (accounts) => { // inherichain = await Inherichain.deployed(); demo = await Demo.deployed(); simpleERC20 = await SimpleERC20.deployed(); + arbitrator = await SimpleCentralizedArbitrator.deployed(); }); beforeEach("", async () => { @@ -81,6 +90,9 @@ contract("Inherichain (Approver Functions)", (accounts) => { backupOwner, heir, charity, + arbitrator.address, + arbitratorExtraData, + metaEvidence, [approverOne, approverTwo, approverThree], 0, 0, @@ -89,10 +101,10 @@ contract("Inherichain (Approver Functions)", (accounts) => { }); it("Approving heir by Approver should be possible.", async () => { - await inherichain.claimOwnership({from: heir}); + await inherichain.claimOwnership({ from: heir }); const cOldVoteCount = await inherichain.voteCount(); const cOldApproverOneVote = await inherichain.voted(approverOne); - await inherichain.approveHeir(true, {from: approverOne}); + await inherichain.approveHeir(true, { from: approverOne }); const cNewVoteCount = await inherichain.voteCount(); const cNewApproverOneVote = await inherichain.voted(approverOne); assert.strictEqual( @@ -113,10 +125,10 @@ contract("Inherichain (Approver Functions)", (accounts) => { }); it("Rejecting heir by Approver should be possible.", async () => { - await inherichain.claimOwnership({from: heir}); + await inherichain.claimOwnership({ from: heir }); const cOldVoteCount = await inherichain.voteCount(); const cOldApproverOneVote = await inherichain.voted(approverOne); - await inherichain.approveHeir(false, {from: approverOne}); + await inherichain.approveHeir(false, { from: approverOne }); const cNewVoteCount = await inherichain.voteCount(); const cNewApproverOneVote = await inherichain.voted(approverOne); assert.strictEqual( @@ -137,62 +149,61 @@ contract("Inherichain (Approver Functions)", (accounts) => { }); it("Approving heir by Outsider should not be possible.", async () => { - await inherichain.claimOwnership({from: heir}); + await inherichain.claimOwnership({ from: heir }); await expectRevert( - inherichain.approveHeir(true, {from: outsider}), + inherichain.approveHeir(true, { from: outsider }), "Only an approver can call this function." ); }); it("Rejecting heir by Outsider should not be possible.", async () => { - await inherichain.claimOwnership({from: heir}); + await inherichain.claimOwnership({ from: heir }); await expectRevert( - inherichain.approveHeir(false, {from: outsider}), + inherichain.approveHeir(false, { from: outsider }), "Only an approver can call this function." ); }); it("Approving heir by Approver twice should not be possible.", async () => { - await inherichain.claimOwnership({from: heir}); - await inherichain.approveHeir(true, {from: approverOne}); + await inherichain.claimOwnership({ from: heir }); + await inherichain.approveHeir(true, { from: approverOne }); await expectRevert( - inherichain.approveHeir(true, {from: approverOne}), + inherichain.approveHeir(true, { from: approverOne }), "Already voted." ); }); it("Rejecting heir by Approver twice should not be possible.", async () => { - await inherichain.claimOwnership({from: heir}); - await inherichain.approveHeir(false, {from: approverOne}); + await inherichain.claimOwnership({ from: heir }); + await inherichain.approveHeir(false, { from: approverOne }); await expectRevert( - inherichain.approveHeir(false, {from: approverOne}), + inherichain.approveHeir(false, { from: approverOne }), "Already voted." ); }); it("Without heir claiming ownership, voting by Approver should not be possible.", async () => { await expectRevert( - inherichain.approveHeir(true, {from: approverOne}), + inherichain.approveHeir(true, { from: approverOne }), "Claim has not started yet." ); }); it("With majority approving heir, the majority vote by Approver should emit heirApproved Event.", async () => { - await inherichain.claimOwnership({from: heir}); - await inherichain.approveHeir(true, {from: approverOne}); - const receipt = await inherichain.approveHeir(true, {from: approverTwo}); + await inherichain.claimOwnership({ from: heir }); + await inherichain.approveHeir(true, { from: approverOne }); + const receipt = await inherichain.approveHeir(true, { from: approverTwo }); expectEvent(receipt, "heirApproved", { _approveCount: new BN(2), }); }); it("Approving heir by Approver should emit heirApproval Event.", async () => { - await inherichain.claimOwnership({from: heir}); - const receipt = await inherichain.approveHeir(false, {from: approverOne}); + await inherichain.claimOwnership({ from: heir }); + const receipt = await inherichain.approveHeir(false, { from: approverOne }); expectEvent(receipt, "heirApproval", { _approver: approverOne, _status: false, }); }); - }); diff --git a/test/backupOwner.test.js b/test/backupOwner.test.js index 43645f2..ca29f85 100644 --- a/test/backupOwner.test.js +++ b/test/backupOwner.test.js @@ -1,6 +1,7 @@ const Inherichain = artifacts.require("Inherichain"); const Demo = artifacts.require("Demo"); const SimpleERC20 = artifacts.require("SimpleERC20"); +const SimpleCentralizedArbitrator = artifacts.require("SimpleCentralizedArbitrator"); const { time, // Convert different time units to seconds. Available helpers are: seconds, minutes, hours, days, weeks and years. @@ -20,6 +21,7 @@ contract("Inherichain (Backup Owner Functions)", (accounts) => { let inherichain = null; let demo = null; let simpleERC20 = null; + let arbitrator = null; let owner, backupOwner, heir, @@ -33,10 +35,16 @@ contract("Inherichain (Backup Owner Functions)", (accounts) => { newApproverTwo, newApproverThree, outsider; + const arbitratorExtraData = `0x0`; + const metaEvidence = ""; const sInitial = 0; const sHeirClaimed = 1; - const sApproverApproved = 2; - const sInitiatedCharity = 3; + const sClaimDisputed = 2; + const sDisputeResultPending =3; + const sApproverApproved = 4; + const sArbitratorApproved = 5; + const sArbitratorRejected = 6; + const sInitiatedCharity = 7; const deadline = time.duration.days(30).toNumber(); const approverDeadline = time.duration.days(7).toNumber(); const charityDeadline = time.duration.days(45).toNumber(); @@ -73,6 +81,7 @@ contract("Inherichain (Backup Owner Functions)", (accounts) => { // inherichain = await Inherichain.deployed(); demo = await Demo.deployed(); simpleERC20 = await SimpleERC20.deployed(); + arbitrator = await SimpleCentralizedArbitrator.deployed(); }); beforeEach("", async () => { @@ -81,6 +90,9 @@ contract("Inherichain (Backup Owner Functions)", (accounts) => { backupOwner, heir, charity, + arbitrator.address, + arbitratorExtraData, + metaEvidence, [approverOne, approverTwo, approverThree], 0, 0, @@ -89,7 +101,7 @@ contract("Inherichain (Backup Owner Functions)", (accounts) => { }); it("Updating an Owner by Backup Owner should be possible.", async () => { - await inherichain.updateOwner(newBackupOwner, {from: backupOwner}); + await inherichain.updateOwner(newBackupOwner, { from: backupOwner }); const cNewOwner = await inherichain.owner(); assert.strictEqual( cNewOwner, @@ -115,5 +127,4 @@ contract("Inherichain (Backup Owner Functions)", (accounts) => { _changer: backupOwner, }); }); - }); diff --git a/test/charity.test.js b/test/charity.test.js index 8c8362b..3890973 100644 --- a/test/charity.test.js +++ b/test/charity.test.js @@ -1,6 +1,7 @@ const Inherichain = artifacts.require("Inherichain"); const Demo = artifacts.require("Demo"); const SimpleERC20 = artifacts.require("SimpleERC20"); +const SimpleCentralizedArbitrator = artifacts.require("SimpleCentralizedArbitrator"); const { time, // Convert different time units to seconds. Available helpers are: seconds, minutes, hours, days, weeks and years. @@ -20,6 +21,7 @@ contract("Inherichain (Charity Functions)", (accounts) => { let inherichain = null; let demo = null; let simpleERC20 = null; + let arbitrator = null; let owner, backupOwner, heir, @@ -33,10 +35,16 @@ contract("Inherichain (Charity Functions)", (accounts) => { newApproverTwo, newApproverThree, outsider; + const arbitratorExtraData = `0x0`; + const metaEvidence = ""; const sInitial = 0; const sHeirClaimed = 1; - const sApproverApproved = 2; - const sInitiatedCharity = 3; + const sClaimDisputed = 2; + const sDisputeResultPending =3; + const sApproverApproved = 4; + const sArbitratorApproved = 5; + const sArbitratorRejected = 6; + const sInitiatedCharity = 7; const deadline = time.duration.days(30).toNumber(); const approverDeadline = time.duration.days(7).toNumber(); const charityDeadline = time.duration.days(45).toNumber(); @@ -73,6 +81,7 @@ contract("Inherichain (Charity Functions)", (accounts) => { // inherichain = await Inherichain.deployed(); demo = await Demo.deployed(); simpleERC20 = await SimpleERC20.deployed(); + arbitrator = await SimpleCentralizedArbitrator.deployed(); }); beforeEach("", async () => { @@ -81,6 +90,9 @@ contract("Inherichain (Charity Functions)", (accounts) => { backupOwner, heir, charity, + arbitrator.address, + arbitratorExtraData, + metaEvidence, [approverOne, approverTwo, approverThree], 0, 0, diff --git a/test/heir.test.js b/test/heir.test.js index ec01d17..212e026 100644 --- a/test/heir.test.js +++ b/test/heir.test.js @@ -1,6 +1,7 @@ const Inherichain = artifacts.require("Inherichain"); const Demo = artifacts.require("Demo"); const SimpleERC20 = artifacts.require("SimpleERC20"); +const SimpleCentralizedArbitrator = artifacts.require("SimpleCentralizedArbitrator"); const { time, // Convert different time units to seconds. Available helpers are: seconds, minutes, hours, days, weeks and years. @@ -20,6 +21,7 @@ contract("Inherichain (Heir Functions)", (accounts) => { let inherichain = null; let demo = null; let simpleERC20 = null; + let arbitrator = null; let owner, backupOwner, heir, @@ -33,10 +35,16 @@ contract("Inherichain (Heir Functions)", (accounts) => { newApproverTwo, newApproverThree, outsider; + const arbitratorExtraData = `0x0`; + const metaEvidence = ""; const sInitial = 0; const sHeirClaimed = 1; - const sApproverApproved = 2; - const sInitiatedCharity = 3; + const sClaimDisputed = 2; + const sDisputeResultPending =3; + const sApproverApproved = 4; + const sArbitratorApproved = 5; + const sArbitratorRejected = 6; + const sInitiatedCharity = 7; const deadline = time.duration.days(30).toNumber(); const approverDeadline = time.duration.days(7).toNumber(); const charityDeadline = time.duration.days(45).toNumber(); @@ -73,6 +81,7 @@ contract("Inherichain (Heir Functions)", (accounts) => { // inherichain = await Inherichain.deployed(); demo = await Demo.deployed(); simpleERC20 = await SimpleERC20.deployed(); + arbitrator = await SimpleCentralizedArbitrator.deployed(); }); beforeEach("", async () => { @@ -81,6 +90,9 @@ contract("Inherichain (Heir Functions)", (accounts) => { backupOwner, heir, charity, + arbitrator.address, + arbitratorExtraData, + metaEvidence, [approverOne, approverTwo, approverThree], 0, 0, @@ -91,7 +103,7 @@ contract("Inherichain (Heir Functions)", (accounts) => { it("Claim ownership by Heir should be possible.", async () => { const cOldStatus = await inherichain.status(); const cOldClaimTime = await inherichain.claimTime(); - await inherichain.claimOwnership({from: heir}); + await inherichain.claimOwnership({ from: heir }); const cNewStatus = await inherichain.status(); const cNewClaimTime = await inherichain.claimTime(); assert.strictEqual( @@ -118,21 +130,21 @@ contract("Inherichain (Heir Functions)", (accounts) => { it("Claim ownership by Outsider should not be possible.", async () => { await expectRevert( - inherichain.claimOwnership({from: outsider}), + inherichain.claimOwnership({ from: outsider }), "Only heir can call this function." ); }); it("Claim ownership by Heir twice should not be possible.", async () => { - await inherichain.claimOwnership({from: heir}); + await inherichain.claimOwnership({ from: heir }); await expectRevert( - inherichain.claimOwnership({from: heir}), + inherichain.claimOwnership({ from: heir }), "Claim already started." ); }); it("Claim ownership by Heir should emit the ownershipClaimed Event.", async () => { - const receipt = await inherichain.claimOwnership({from: heir}); + const receipt = await inherichain.claimOwnership({ from: heir }); expectEvent(receipt, "ownershipClaimed", { _heir: heir, // _claimTime: , @@ -140,9 +152,9 @@ contract("Inherichain (Heir Functions)", (accounts) => { }); it("Accessing ownership with approver votes by heir should be possible.", async () => { - await inherichain.claimOwnership({from: heir}); - await inherichain.approveHeir(true, {from: approverOne}); - await inherichain.approveHeir(true, {from: approverTwo}); + await inherichain.claimOwnership({ from: heir }); + await inherichain.approveHeir(true, { from: approverOne }); + await inherichain.approveHeir(true, { from: approverTwo }); await time.increase(approverDeadline + 1); await inherichain.accessOwnershipFromApprover( newBackupOwner, @@ -151,7 +163,7 @@ contract("Inherichain (Heir Functions)", (accounts) => { newDeadline, newApproverDeadline, newCharityDeadline, - {from: heir} + { from: heir } ); const cNewStatus = await inherichain.status(); const cNewOwner = await inherichain.owner(); @@ -230,7 +242,7 @@ contract("Inherichain (Heir Functions)", (accounts) => { }); it("Accessing ownership without approver votes by heir should not be possible.", async () => { - await inherichain.claimOwnership({from: heir}); + await inherichain.claimOwnership({ from: heir }); await expectRevert( inherichain.accessOwnershipFromApprover( newBackupOwner, @@ -239,16 +251,16 @@ contract("Inherichain (Heir Functions)", (accounts) => { newDeadline, newApproverDeadline, newCharityDeadline, - {from: heir} + { from: heir } ), "Majority vote required to access ownership." ); }); it("Accessing ownership with approver votes by outsider should not be possible.", async () => { - await inherichain.claimOwnership({from: heir}); - await inherichain.approveHeir(true, {from: approverOne}); - await inherichain.approveHeir(true, {from: approverTwo}); + await inherichain.claimOwnership({ from: heir }); + await inherichain.approveHeir(true, { from: approverOne }); + await inherichain.approveHeir(true, { from: approverTwo }); await expectRevert( inherichain.accessOwnershipFromApprover( newBackupOwner, @@ -257,14 +269,14 @@ contract("Inherichain (Heir Functions)", (accounts) => { newDeadline, newApproverDeadline, newCharityDeadline, - {from: outsider} + { from: outsider } ), "Only heir can call this function." ); }); it("Accessing ownership without approver votes by outsider should not be possible.", async () => { - await inherichain.claimOwnership({from: heir}); + await inherichain.claimOwnership({ from: heir }); await expectRevert( inherichain.accessOwnershipFromApprover( newBackupOwner, @@ -273,16 +285,16 @@ contract("Inherichain (Heir Functions)", (accounts) => { newDeadline, newApproverDeadline, newCharityDeadline, - {from: outsider} + { from: outsider } ), "Only heir can call this function." ); }); it("Accessing ownership from approver votes before approver deadline by heir should not be possible.", async () => { - await inherichain.claimOwnership({from: heir}); - await inherichain.approveHeir(true, {from: approverOne}); - await inherichain.approveHeir(true, {from: approverTwo}); + await inherichain.claimOwnership({ from: heir }); + await inherichain.approveHeir(true, { from: approverOne }); + await inherichain.approveHeir(true, { from: approverTwo }); await expectRevert( inherichain.accessOwnershipFromApprover( newBackupOwner, @@ -291,16 +303,16 @@ contract("Inherichain (Heir Functions)", (accounts) => { newDeadline, newApproverDeadline, newCharityDeadline, - {from: heir} + { from: heir } ), "Deadline has not passed." ); }); it("Accessing ownership from approver votes by heir should emit ownershipAccessed Event.", async () => { - await inherichain.claimOwnership({from: heir}); - await inherichain.approveHeir(true, {from: approverOne}); - await inherichain.approveHeir(true, {from: approverTwo}); + await inherichain.claimOwnership({ from: heir }); + await inherichain.approveHeir(true, { from: approverOne }); + await inherichain.approveHeir(true, { from: approverTwo }); await time.increase(approverDeadline + 1); const receipt = await inherichain.accessOwnershipFromApprover( newBackupOwner, @@ -309,7 +321,7 @@ contract("Inherichain (Heir Functions)", (accounts) => { newDeadline, newApproverDeadline, newCharityDeadline, - {from: heir} + { from: heir } ); expectEvent(receipt, "ownershipAccessed", { _newOwner: heir, @@ -322,7 +334,7 @@ contract("Inherichain (Heir Functions)", (accounts) => { }); it("Accessing ownership after deadline by heir should be possible.", async () => { - await inherichain.claimOwnership({from: heir}); + await inherichain.claimOwnership({ from: heir }); await time.increase(deadline + 1); await inherichain.accessOwnershipAfterDeadline( newBackupOwner, @@ -331,7 +343,7 @@ contract("Inherichain (Heir Functions)", (accounts) => { newDeadline, newApproverDeadline, newCharityDeadline, - {from: heir} + { from: heir } ); const cNewStatus = await inherichain.status(); const cNewOwner = await inherichain.owner(); @@ -410,7 +422,7 @@ contract("Inherichain (Heir Functions)", (accounts) => { }); it("Accessing ownership before deadline by heir should not be possible.", async () => { - await inherichain.claimOwnership({from: heir}); + await inherichain.claimOwnership({ from: heir }); await expectRevert( inherichain.accessOwnershipAfterDeadline( newBackupOwner, @@ -419,14 +431,14 @@ contract("Inherichain (Heir Functions)", (accounts) => { newDeadline, newApproverDeadline, newCharityDeadline, - {from: heir} + { from: heir } ), "Deadline has not passed." ); }); it("Accessing ownership after deadline by outsider should not be possible.", async () => { - await inherichain.claimOwnership({from: heir}); + await inherichain.claimOwnership({ from: heir }); await time.increase(deadline + 1); await expectRevert( inherichain.accessOwnershipAfterDeadline( @@ -436,14 +448,14 @@ contract("Inherichain (Heir Functions)", (accounts) => { newDeadline, newApproverDeadline, newCharityDeadline, - {from: outsider} + { from: outsider } ), "Only heir can call this function." ); }); it("Accessing ownership before deadline by outsider should not be possible.", async () => { - await inherichain.claimOwnership({from: heir}); + await inherichain.claimOwnership({ from: heir }); await time.increase(deadline + 1); await expectRevert( inherichain.accessOwnershipAfterDeadline( @@ -453,14 +465,14 @@ contract("Inherichain (Heir Functions)", (accounts) => { newDeadline, newApproverDeadline, newCharityDeadline, - {from: outsider} + { from: outsider } ), "Only heir can call this function." ); }); it("Accessing ownership after deadline by heir should emit ownershipAccessed Event.", async () => { - await inherichain.claimOwnership({from: heir}); + await inherichain.claimOwnership({ from: heir }); await time.increase(deadline + 1); const receipt = await inherichain.accessOwnershipAfterDeadline( newBackupOwner, @@ -469,7 +481,7 @@ contract("Inherichain (Heir Functions)", (accounts) => { newDeadline, newApproverDeadline, newCharityDeadline, - {from: heir} + { from: heir } ); expectEvent(receipt, "ownershipAccessed", { _newOwner: heir, @@ -480,5 +492,4 @@ contract("Inherichain (Heir Functions)", (accounts) => { _heirApprovedDeadline: new BN(newApproverDeadline), }); }); - }); diff --git a/test/inherichain.test.js b/test/inherichain.test.js index 4f35be2..ac15e31 100644 --- a/test/inherichain.test.js +++ b/test/inherichain.test.js @@ -1,6 +1,7 @@ const Inherichain = artifacts.require("Inherichain"); const Demo = artifacts.require("Demo"); const SimpleERC20 = artifacts.require("SimpleERC20"); +const SimpleCentralizedArbitrator = artifacts.require("SimpleCentralizedArbitrator"); const { time, // Convert different time units to seconds. Available helpers are: seconds, minutes, hours, days, weeks and years. @@ -20,6 +21,7 @@ contract("Inherichain (Basic Functions)", (accounts) => { let inherichain = null; let demo = null; let simpleERC20 = null; + let arbitrator = null; let owner, backupOwner, heir, @@ -33,10 +35,16 @@ contract("Inherichain (Basic Functions)", (accounts) => { newApproverTwo, newApproverThree, outsider; + const arbitratorExtraData = `0x0`; + const metaEvidence = ""; const sInitial = 0; const sHeirClaimed = 1; - const sApproverApproved = 2; - const sInitiatedCharity = 3; + const sClaimDisputed = 2; + const sDisputeResultPending =3; + const sApproverApproved = 4; + const sArbitratorApproved = 5; + const sArbitratorRejected = 6; + const sInitiatedCharity = 7; const deadline = time.duration.days(30).toNumber(); const approverDeadline = time.duration.days(7).toNumber(); const charityDeadline = time.duration.days(45).toNumber(); @@ -73,6 +81,7 @@ contract("Inherichain (Basic Functions)", (accounts) => { // inherichain = await Inherichain.deployed(); demo = await Demo.deployed(); simpleERC20 = await SimpleERC20.deployed(); + arbitrator = await SimpleCentralizedArbitrator.deployed(); }); beforeEach("", async () => { @@ -81,6 +90,9 @@ contract("Inherichain (Basic Functions)", (accounts) => { backupOwner, heir, charity, + arbitrator.address, + arbitratorExtraData, + metaEvidence, [approverOne, approverTwo, approverThree], 0, 0, @@ -145,6 +157,9 @@ contract("Inherichain (Basic Functions)", (accounts) => { constants.ZERO_ADDRESS, heir, constants.ZERO_ADDRESS, + arbitrator.address, + arbitratorExtraData, + metaEvidence, [approverOne, approverTwo, approverThree], newDeadline, newApproverDeadline, @@ -219,6 +234,9 @@ contract("Inherichain (Basic Functions)", (accounts) => { owner, heir, charity, + arbitrator.address, + arbitratorExtraData, + metaEvidence, [approverOne, approverTwo, approverThree], newDeadline, newApproverDeadline, @@ -235,6 +253,9 @@ contract("Inherichain (Basic Functions)", (accounts) => { backupOwner, owner, charity, + arbitrator.address, + arbitratorExtraData, + metaEvidence, [approverOne, approverTwo, approverThree], newDeadline, newApproverDeadline, @@ -251,6 +272,9 @@ contract("Inherichain (Basic Functions)", (accounts) => { backupOwner, backupOwner, charity, + arbitrator.address, + arbitratorExtraData, + metaEvidence, [approverOne, approverTwo, approverThree], newDeadline, newApproverDeadline, @@ -267,6 +291,9 @@ contract("Inherichain (Basic Functions)", (accounts) => { backupOwner, constants.ZERO_ADDRESS, charity, + arbitrator.address, + arbitratorExtraData, + metaEvidence, [approverOne, approverTwo, approverThree], newDeadline, newApproverDeadline, @@ -283,6 +310,9 @@ contract("Inherichain (Basic Functions)", (accounts) => { backupOwner, heir, charity, + arbitrator.address, + arbitratorExtraData, + metaEvidence, [approverOne, approverOne], newDeadline, newApproverDeadline, @@ -371,7 +401,7 @@ contract("Inherichain (Basic Functions)", (accounts) => { it("Should be able to deposit an ERC20 Token by Outsider.", async () => { const valueToDeposit = randomValue(); - await simpleERC20.transfer(outsider, valueToDeposit, {from: heir}); + await simpleERC20.transfer(outsider, valueToDeposit, { from: heir }); await simpleERC20.transfer(inherichain.address, valueToDeposit, { from: outsider, }); diff --git a/test/owner.test.js b/test/owner.test.js index 0301fba..66f301d 100644 --- a/test/owner.test.js +++ b/test/owner.test.js @@ -1,6 +1,7 @@ const Inherichain = artifacts.require("Inherichain"); const Demo = artifacts.require("Demo"); const SimpleERC20 = artifacts.require("SimpleERC20"); +const SimpleCentralizedArbitrator = artifacts.require("SimpleCentralizedArbitrator"); const { time, // Convert different time units to seconds. Available helpers are: seconds, minutes, hours, days, weeks and years. @@ -20,6 +21,7 @@ contract("Inherichain (Owner Functions)", (accounts) => { let inherichain = null; let demo = null; let simpleERC20 = null; + let arbitrator = null; let owner, backupOwner, heir, @@ -33,10 +35,16 @@ contract("Inherichain (Owner Functions)", (accounts) => { newApproverTwo, newApproverThree, outsider; + const arbitratorExtraData = `0x0`; + const metaEvidence = ""; const sInitial = 0; const sHeirClaimed = 1; - const sApproverApproved = 2; - const sInitiatedCharity = 3; + const sClaimDisputed = 2; + const sDisputeResultPending =3; + const sApproverApproved = 4; + const sArbitratorApproved = 5; + const sArbitratorRejected = 6; + const sInitiatedCharity = 7; const deadline = time.duration.days(30).toNumber(); const approverDeadline = time.duration.days(7).toNumber(); const charityDeadline = time.duration.days(45).toNumber(); @@ -73,6 +81,7 @@ contract("Inherichain (Owner Functions)", (accounts) => { // inherichain = await Inherichain.deployed(); demo = await Demo.deployed(); simpleERC20 = await SimpleERC20.deployed(); + arbitrator = await SimpleCentralizedArbitrator.deployed(); }); beforeEach("", async () => { @@ -81,6 +90,9 @@ contract("Inherichain (Owner Functions)", (accounts) => { backupOwner, heir, charity, + arbitrator.address, + arbitratorExtraData, + metaEvidence, [approverOne, approverTwo, approverThree], 0, 0, @@ -106,7 +118,7 @@ contract("Inherichain (Owner Functions)", (accounts) => { it("Updating Backup Owner by outsider should not be possible.", async () => { await expectRevert( - inherichain.updateBackupOwner(newBackupOwner, {from: outsider}), + inherichain.updateBackupOwner(newBackupOwner, { from: outsider }), "Only owner can call this function." ); }); @@ -147,7 +159,7 @@ contract("Inherichain (Owner Functions)", (accounts) => { it("Updating Heir by outsider should not be possible.", async () => { await expectRevert( - inherichain.updateHeir(newHeir, {from: outsider}), + inherichain.updateHeir(newHeir, { from: outsider }), "Only owner can call this function." ); }); @@ -177,11 +189,11 @@ contract("Inherichain (Owner Functions)", (accounts) => { const cInitialStatus = await inherichain.status(); const cInitialClaimTime = await inherichain.claimTime(); const cInitialVoteCount = await inherichain.voteCount(); - await inherichain.claimOwnership({from: heir}); + await inherichain.claimOwnership({ from: heir }); const cAfterClaimStatus = await inherichain.status(); const cOldClaimTime = await inherichain.claimTime(); - await inherichain.approveHeir(true, {from: approverOne}); - await inherichain.approveHeir(true, {from: approverTwo}); + await inherichain.approveHeir(true, { from: approverOne }); + await inherichain.approveHeir(true, { from: approverTwo }); const cAfterApprovalStatus = await inherichain.status(); const cOldVoteCount = await inherichain.voteCount(); await inherichain.updateHeir(newHeir); @@ -393,7 +405,7 @@ contract("Inherichain (Owner Functions)", (accounts) => { it("Adding an approver by outsider should not be possible.", async () => { await expectRevert( - inherichain.addApprover(newApproverOne, {from: outsider}), + inherichain.addApprover(newApproverOne, { from: outsider }), "Only owner can call this function." ); }); @@ -447,7 +459,7 @@ contract("Inherichain (Owner Functions)", (accounts) => { it("Deleting an approver by outsider should not be possible.", async () => { await expectRevert( - inherichain.deleteApprover(newApproverOne, {from: outsider}), + inherichain.deleteApprover(newApproverOne, { from: outsider }), "Only owner can call this function." ); }); @@ -618,7 +630,7 @@ contract("Inherichain (Owner Functions)", (accounts) => { it("Contract deployment by Outsider should not be possible.", async () => { await expectRevert( - inherichain.deployContract(0, demoBytecode, {from: outsider}), + inherichain.deployContract(0, demoBytecode, { from: outsider }), "Only owner can call this function." ); }); @@ -696,14 +708,14 @@ contract("Inherichain (Owner Functions)", (accounts) => { it("Should not be able to withdraw all ether by Outsider.", async () => { await expectRevert( - inherichain.withdrawAllETH({from: outsider}), + inherichain.withdrawAllETH({ from: outsider }), "Only owner can call this function." ); }); it("Should not be able to withdraw partial ether by Outsider.", async () => { await expectRevert( - inherichain.withdrawSomeETH(transferValue, {from: outsider}), + inherichain.withdrawSomeETH(transferValue, { from: outsider }), "Only owner can call this function." ); }); @@ -740,7 +752,7 @@ contract("Inherichain (Owner Functions)", (accounts) => { it("Should not be able to transfer ether by Outsider.", async () => { await expectRevert( - inherichain.transferETH(backupOwner, transferValue, {from: outsider}), + inherichain.transferETH(backupOwner, transferValue, { from: outsider }), "Only owner can call this function." ); }); @@ -757,7 +769,7 @@ contract("Inherichain (Owner Functions)", (accounts) => { it("Updating an Owner by Outsider should not be possible.", async () => { await expectRevert( - inherichain.updateOwner(newBackupOwner, {from: outsider}), + inherichain.updateOwner(newBackupOwner, { from: outsider }), "Only primary or backup owner can call this function." ); }); @@ -777,5 +789,4 @@ contract("Inherichain (Owner Functions)", (accounts) => { _changer: owner, }); }); - });