EIP: 792
Title: Arbitration Standard
Status: Draft
Type: Informational
Category: ERC
Author: Clément Lesaege <clement@kleros.io>
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 an Arbitrable contract allows Arbitrable 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 the Arbitrator 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 value 0 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 the Arbitrator contract just has to return an arbitrary high value in appealCost 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 allows Arbitrable contracts to choose to give higher fee than required, for example if those fee 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 which ruling would be given if there is no appeal and make their appeal decisions accordingly.
Combined with disputeStatus, 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
Presentation on how to make your own implementation:
Abstract
The following describes a standard of
ArbitrableandArbitratorcontracts. 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
Arbitrablecontract developers not to have to know the internal process of theArbitratorcontracts. Neither doArbitratorcontract developers withArbitrableones.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
Arbitratorcontract.It must calls the functions
createDisputeandappealof theArbitratorcontract 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 uniquearbitratorwhich can't be changed, thearbitratorpart can be omitted internally.This contract must implement enforcements of
ruling. Forruling, the value0is reserved to indicate that no ruling has been given.Methods
rule
To be called by the
Arbitratorcontract.Enforces the ruling
_rulingfor dispute(msg.sender,_dispute).Arbitrators should only call
rulewhen all appeals are exhausted.It must reverts in case of failure.
It must fire the
Rulingevent.NOTE: The
Arbitratorcontract should not assume thatrulewill be successfully executed. A malicious (or buggy)Arbitrablecontract could makerulerevert.Events
Ruling
Must trigger when a final ruling is given.
Arbitrator
This contract makes rulings. It must call the
rulefunction when a decision is final.Methods
NOTE: The variable
_extraDatacan contains information to require a custom arbitration (resp. appeal) behaviour of the contract. The format of this variable is determined by theArbitratorcontract creator. In case_extraDatais void or invalid, functions should act according to a default arbitration (resp. appeal) behaviour.NOTE: The variable
_extraDataSHOULD be formatted the same way for both dispute creation and appeal.NOTE: Different
_extraDatavalues can be used by a sameArbitrablecontract, even during the same dispute. ThereforeArbitratorcontracts MUST NOT assume_extraDatato be constant across disputes and appeals.NOTE: Arbitration (resp. appeal)
feecan change, thereforeArbitrablecontracts should call this function each time it is relevant and not assume thefeeare the same as in the last call.NOTE: If the
Arbitrablecontract 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
feein wei required to create a dispute.appealCost
Returns the cost of appeal
feein wei required to appeal the dispute(arbitrator,_disputeID).createDispute
Create a dispute.
It should be called by the
Arbitrablecontract. It must pay at leastarbitrationCost(bytes _extraData)weis.The parameter
_choicesindicates the maximum value_rulingcan take. So for a binary ruling,_choicesshould be2(0to refuse to give a ruling,1for giving the first ruling and2for the second).This method must fire the
DisputeCreationevent.The
Arbitratorcontract should assign a uniquedisputeIDidentifier to the dispute and return it.appeal
Appeal the dispute
(arbitrator,_disputeID).It should be called by the
Arbitrablecontract. It must pay at leastappealCost(uint _disputeID, bytes _extraData)weis.This method must fire the
AppealDecisionevent.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).currentRuling
Return the
rulingwhich will be given if there is no appeal or which has been given.disputeStatus
Return the
statusof the ruling.with
NOTE: The value
solveddoes not necessarily means that the functionrulewas called. It means that the ruling is final and that it won't change.Events
DisputeCreation
Must trigger when a dispute is created.
AppealDecision
Must trigger when the current ruling is appealed.
AppealPossible
Must trigger when appealing a dispute becomes possible.
Rationale
Arbitratorof anArbitrablecontract allowsArbitrablecontracts to have multiple arbitrators and to change them.Arbitrablecontract to pay the fee (opposed to requiring users to directly interact with theArbitratorcontract) 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.ruling, reserving the value0for absence of ruling allows arbitrators to refuse to rule.extraDataallows 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.appealis possible, as theArbitratorcontract just has to return an arbitrary high value inappealCostto indicate that appeals are not possible.Arbitrablecontract 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 allowsArbitrablecontracts to choose to give higherfeethan required, for example if thosefeeare used as an incentive for arbitrators, in order to provide incentives higher than the minimum.disputeStatusallows contract and users to know if a ruling has been given and if it is final.currentRulingallows contracts and users to know whichrulingwould be given if there is no appeal and make their appeal decisions accordingly.Combined with
disputeStatus, it allows other contracts to take actions depending of the result of a dispute. This can be used to enforce contingency fee payouts.Implementations
Example implementations are available at
Presentation on how to make your own implementation: