feat: allow specifying a timeout for arbitrators and escalating a dispute to the fallback arbitrator once the timeout passes. (#672)
This commit is contained in:
parent
9be0c1b189
commit
97a966b9f7
|
@ -3,6 +3,7 @@ pragma solidity >=0.5.0 <0.6.0;
|
|||
|
||||
import "./ArbitrationLicense.sol";
|
||||
|
||||
|
||||
/**
|
||||
* Arbitrable
|
||||
* @dev Utils for management of disputes
|
||||
|
@ -19,6 +20,8 @@ contract Arbitrable {
|
|||
|
||||
address public fallbackArbitrator;
|
||||
|
||||
uint public arbitrationTimeout;
|
||||
|
||||
struct ArbitrationCase {
|
||||
bool open;
|
||||
address openBy;
|
||||
|
@ -28,17 +31,19 @@ contract Arbitrable {
|
|||
ArbitrationMotive motive;
|
||||
}
|
||||
|
||||
event ArbitratorChanged(address arbitrator);
|
||||
event ArbitratorChanged(uint escrowId, address sender, address ogArbitrator, address newArbitrator);
|
||||
event ArbitrationCanceled(uint escrowId);
|
||||
event ArbitrationRequired(uint escrowId, uint timeout);
|
||||
event ArbitrationResolved(uint escrowId, ArbitrationResult result, address arbitrator);
|
||||
|
||||
/**
|
||||
* @param _arbitratorLicenses Address of the Arbitrator Licenses contract
|
||||
* @param _fallbackArbitrator Address of the fallback arbitrator in case the original arbitrator does not work on a dispute
|
||||
*/
|
||||
constructor(address _arbitratorLicenses, address _fallbackArbitrator) public {
|
||||
arbitratorLicenses = ArbitrationLicense(_arbitratorLicenses);
|
||||
fallbackArbitrator = _fallbackArbitrator;
|
||||
arbitrationTimeout = 5 days;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -105,7 +110,7 @@ contract Arbitrable {
|
|||
|
||||
require(arbitratorAddress != address(0), "Arbitrator is required");
|
||||
|
||||
uint timeout = block.timestamp + 5 days;
|
||||
uint timeout = block.timestamp + arbitrationTimeout;
|
||||
|
||||
arbitrationCases[_escrowId] = ArbitrationCase({
|
||||
open: true,
|
||||
|
@ -119,6 +124,18 @@ contract Arbitrable {
|
|||
emit ArbitrationRequired(_escrowId, timeout);
|
||||
}
|
||||
|
||||
/**
|
||||
* @notice Allow participants to escalate dispute to fallback arbitrator after timeout
|
||||
* @param _escrowId Id of the Escrow that is being disputed
|
||||
*/
|
||||
function escalateDispute(uint _escrowId) external {
|
||||
require(arbitrationCases[_escrowId].open && arbitrationCases[_escrowId].result == ArbitrationResult.UNSOLVED, "Case must be open and unsolved");
|
||||
require(block.timestamp > arbitrationCases[_escrowId].arbitratorTimeout, "Arbitration is still active");
|
||||
|
||||
emit ArbitratorChanged(_escrowId, msg.sender, arbitrationCases[_escrowId].arbitrator, fallbackArbitrator);
|
||||
arbitrationCases[_escrowId].arbitrator = fallbackArbitrator;
|
||||
}
|
||||
|
||||
/**
|
||||
* @notice Set arbitration result in favour of the buyer or seller and transfer funds accordingly
|
||||
* @param _escrowId Id of the escrow
|
||||
|
@ -128,11 +145,15 @@ contract Arbitrable {
|
|||
require(arbitrationCases[_escrowId].open && arbitrationCases[_escrowId].result == ArbitrationResult.UNSOLVED,
|
||||
"Case must be open and unsolved");
|
||||
require(_result != ArbitrationResult.UNSOLVED, "Arbitration does not have result");
|
||||
require(arbitratorLicenses.isLicenseOwner(msg.sender), "Only arbitrators can invoke this function");
|
||||
|
||||
if (block.timestamp > arbitrationCases[_escrowId].arbitratorTimeout) {
|
||||
require(arbitrationCases[_escrowId].arbitrator == msg.sender || msg.sender == fallbackArbitrator, "Invalid escrow arbitrator");
|
||||
if (msg.sender == fallbackArbitrator) {
|
||||
require(block.timestamp > arbitrationCases[_escrowId].arbitratorTimeout, "Arbitration is still active");
|
||||
if (arbitrationCases[_escrowId].arbitrator != msg.sender) {
|
||||
emit ArbitratorChanged(_escrowId, arbitrationCases[_escrowId].arbitrator, msg.sender);
|
||||
arbitrationCases[_escrowId].arbitrator = msg.sender;
|
||||
}
|
||||
} else {
|
||||
require(arbitratorLicenses.isLicenseOwner(msg.sender), "Only arbitrators can invoke this function");
|
||||
require(arbitrationCases[_escrowId].arbitrator == msg.sender, "Invalid escrow arbitrator");
|
||||
}
|
||||
|
||||
|
@ -141,7 +162,7 @@ contract Arbitrable {
|
|||
|
||||
emit ArbitrationResolved(_escrowId, _result, msg.sender);
|
||||
|
||||
if(_result == ArbitrationResult.BUYER){
|
||||
if (_result == ArbitrationResult.BUYER) {
|
||||
_solveDispute(_escrowId, true, msg.sender);
|
||||
} else {
|
||||
_solveDispute(_escrowId, false, msg.sender);
|
||||
|
|
|
@ -94,9 +94,23 @@ contract Escrow is IEscrow, Pausable, MessageSigned, Fees, Arbitrable, Proxiable
|
|||
feeDestination = _feeDestination;
|
||||
feeMilliPercent = _feeMilliPercent;
|
||||
paused = false;
|
||||
arbitrationTimeout = 5 days;
|
||||
|
||||
_setOwner(msg.sender);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Update arbitration timeout. Can only be called by owner
|
||||
* @param _newTimeout new timeout in seconds
|
||||
*/
|
||||
function updateArbitrationTimeout(uint _newTimeout) public onlyOwner {
|
||||
arbitrationTimeout = _newTimeout;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Update proxy implementation. Can only be called by owner
|
||||
* @param _newCode New contract implementation address
|
||||
*/
|
||||
function updateCode(address newCode) public onlyOwner {
|
||||
updateCodeAddress(newCode);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue