Description
EIP: 792
Title: Arbitration Standard
Status: Draft
Type: Informational
Category: ERC
Author: Clément Lesaege <[email protected]>
Created: 2017-12-06
Abstract
The following describes a standard of Arbitrable
and Arbitrator
contracts. Every Arbitrable contract can be adjudicated by every Arbitrator contract. Arbitrator contracts give rulings and Arbitrable contracts enforce them.
Motivation
Using two contracts allows separation between the ruling and its enforcement. This abstraction allows Arbitrable
contract developers not to have to know the internal process of the Arbitrator
contracts. Neither do Arbitrator
contract developers with Arbitrable
ones.
It allows dapps to easily switch from one arbitration service to another one. Or to allow their users to choose themselves their arbitration services.
Specification
Arbitrable
This contract enforces decisions given by the Arbitrator
contract.
It must calls the functions createDispute
and appeal
of the Arbitrator
contract and pay the required fee. It is its responsability to determine in which case a dispute occurs and when an appeal is possible.
It must track the disputes by their (arbitrator,disputeID)
unique key. If the contract only has a unique arbitrator
which can't be changed, the arbitrator
part can be omitted internally.
This contract must implement enforcements of ruling
. For ruling
, the value 0
is reserved to indicate that no ruling has been given.
Methods
rule
To be called by the Arbitrator
contract.
Enforces the ruling _ruling
for dispute (msg.sender,_dispute)
.
Arbitrators should only call rule
when all appeals are exhausted.
It must reverts in case of failure.
It must fire the Ruling
event.
function rule(uint _disputeID, uint _ruling)
NOTE: The Arbitrator
contract should not assume that rule
will be successfully executed. A malicious (or buggy) Arbitrable
contract could make rule
revert.
Events
Ruling
Must trigger when a final ruling is given.
event Ruling(Arbitrator indexed _arbitrator, uint indexed _disputeID, uint _ruling)
Arbitrator
This contract makes rulings. It must call the rule
function when a decision is final.
Methods
NOTE: The variable _extraData
can contains information to require a custom arbitration (resp. appeal) behaviour of the contract. The format of this variable is determined by the Arbitrator
contract creator. In case _extraData
is void or invalid, functions should act according to a default arbitration (resp. appeal) behaviour.
NOTE: The variable _extraData
SHOULD be formatted the same way for both dispute creation and appeal.
NOTE: Different _extraData
values can be used by a same Arbitrable
contract, even during the same dispute. Therefore Arbitrator
contracts MUST NOT assume _extraData
to be constant across disputes and appeals.
NOTE: Arbitration (resp. appeal) fee
can change, therefore Arbitrable
contracts should call this function each time it is relevant and not assume the fee
are the same as in the last call.
NOTE: If the Arbitrable
contract does not pay enough fee, the functions should revert. However, if it pays too much fee, the contract should not revert and accept the higher fee.
arbitrationCost
Returns the cost of arbitration fee
in wei required to create a dispute.
function arbitrationCost(bytes _extraData) view returns(uint fee)
appealCost
Returns the cost of appeal fee
in wei required to appeal the dispute (arbitrator,_disputeID)
.
function appealCost(uint _disputeID, bytes _extraData) view returns(uint fee)
createDispute
Create a dispute.
It should be called by the Arbitrable
contract. It must pay at least arbitrationCost(bytes _extraData)
weis.
The parameter _choices
indicates the maximum value _ruling
can take. So for a binary ruling, _choices
should be 2
(0
to refuse to give a ruling, 1
for giving the first ruling and 2
for the second).
This method must fire the DisputeCreation
event.
The Arbitrator
contract should assign a unique disputeID
identifier to the dispute and return it.
function createDispute(uint _choices, bytes _extraData) payable returns(uint disputeID)
appeal
Appeal the dispute (arbitrator,_disputeID)
.
It should be called by the Arbitrable
contract. It must pay at least appealCost(uint _disputeID, bytes _extraData)
weis.
This method must fire the AppealDecision
event.
function appeal(uint _disputeID, bytes _extraData) payable
appealPeriod
Return the [start
,end
] time windown for appealing a ruling if known in advance.
If those time are not known or appeal is not possible, returns (0,0)
.
function appealPeriod(uint _disputeID) public view returns(uint start, uint end)
currentRuling
Return the ruling
which will be given if there is no appeal or which has been given.
function currentRuling(uint _disputeID) view returns (uint ruling)
disputeStatus
Return the status
of the ruling.
function disputeStatus(uint _disputeID) view returns (DisputeStatus status)
with
enum DisputeStatus {Waiting, Appealable, Solved}
NOTE: The value solved
does not necessarily means that the function rule
was called. It means that the ruling is final and that it won't change.
Events
DisputeCreation
Must trigger when a dispute is created.
event DisputeCreation(uint indexed _disputeID, Arbitrable indexed _arbitrable)
AppealDecision
Must trigger when the current ruling is appealed.
event AppealDecision(uint indexed _disputeID, Arbitrable indexed _arbitrable)
AppealPossible
Must trigger when appealing a dispute becomes possible.
event AppealPossible(uint indexed _disputeID, Arbitrable indexed _arbitrable);
Rationale
- An arbitration standard allows interoperability between dapps needing and requiring arbitration.
- Not putting a standard function returning the
Arbitrator
of anArbitrable
contract allowsArbitrable
contracts to have multiple arbitrators and to change them. - Requiring the
Arbitrable
contract to pay the fee (opposed to requiring users to directly interact with theArbitrator
contract) allows it to determine who should pay the fee. It can choose to split them, or require parties to deposit ether to pay fee and reimburse the winners. - For
ruling
, reserving the value0
for absence of ruling allows arbitrators to refuse to rule. - The variable
extraData
allows arbitrary customization of arbitration processes. For example, the amount of jurors which will participate in a ruling and the time allowed. The way a dispute is handled is determined by the(arbitrator,extraData)
pair. - We don't need a method to indicates if
appeal
is possible, as theArbitrator
contract just has to return an arbitrary high value inappealCost
to indicate that appeals are not possible. - Accepting higher fee instead of reverting generally provides more security. If the
Arbitrable
contract has a bug which makes it pay too much, it's better to accept the higher fee, than to prevent disputes and appeals which could stuck the contract forever. It also allowsArbitrable
contracts to choose to give higherfee
than required, for example if thosefee
are used as an incentive for arbitrators, in order to provide incentives higher than the minimum. - The method
disputeStatus
allows contract and users to know if a ruling has been given and if it is final. - The method
currentRuling
allows contracts and users to know whichruling
would be given if there is no appeal and make their appeal decisions accordingly.
Combined withdisputeStatus
, it allows other contracts to take actions depending of the result of a dispute. This can be used to enforce contingency fee payouts. - This ERC is just about rulings and enforcement, handling of evidence is described in ERC1497: Evidence Standard.
- About community consensus, we published this article including the previous version of the proposed standard and talked about the standard during Devcon3. After feedback, we modified the standard to include events and to split it into two standards: one about ruling and enforcement (this one) and one about handling of evidence (to come).
Implementations
Example implementations are available at
- https://github.com/kleros/kleros-interaction/tree/master/contracts/standard/arbitration
- https://github.com/kleros/kleros/blob/master/contracts/KlerosPOC.sol
Presentation on how to make your own implementation: