ethereum / EIPs

The Ethereum Improvement Proposal repository
https://eips.ethereum.org/
Creative Commons Zero v1.0 Universal
12.94k stars 5.31k forks source link

ERC 792: Arbitration Standard #792

Closed clesaege closed 2 years ago

clesaege commented 6 years ago
  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

Implementations

Example implementations are available at

Presentation on how to make your own implementation:

Samyoul commented 6 years ago

Good work, I really like the look of this. I am very interested in this standard as I am also currently developing platform functionality for arbitration of contracts : https://github.com/TiiQu-Network/TiiQu-Network/wiki/White-Paper#crowd-sourced-arbitrage

wanderingstan commented 6 years ago

Seconding the good work. We are developing a marketplace at www.originprotocol.com and arbitration will be important. I'll share this with our team.

clesaege commented 6 years ago

About

Before any ruling is available, it should return the value 0.

I was wondering that the 0 could both mean "No ruling yet" or "Refused to give a ruling", distinction which in some cases may be relevant. What do you think about using uint(-1) for "No ruling yet" to separate those?

clesaege commented 6 years ago

Another solution would be to add a disputeStatus function returning an enum {awaiting, appealable, final}. I like better the second solution.

SerpentChris commented 6 years ago

I really don't like the _extra_data bytes argument. Languages are typed to make code easier to analyze, and this feature forces developers to obscure type information. This could make bugs harder to catch. One way to fix this would be to remove _extra_data and force Arbitrator contracts to store relevant custom data using the disputeID, and to have their own functions for providing details about each stage of dispute resolution.

clesaege commented 6 years ago

@SerpentChris Well the thing is that when we create an Arbitrable contract, we don't know what other parameters the Arbitrator may need. In my usecase: https://github.com/kleros/kleros/blob/master/contracts/KlerosPOC.sol#L396 , this _extraData is used to define the amount of jurors which will be drawn. In further versions it could also contains the ID of a specialized subcourt. And I guess other Arbitrator will have other parameters we can't forecast.

If you let Arbitrator have their own non standardized functions which should be called by the Arbitrator contract. You remove the benefit of a standard, because you would need to know to which Arbitrator contract you will have to interact with in order to write the Arbitrable one.

You can see that other standards took the same approach, for example ERC777: https://github.com/ethereum/EIPs/issues/777 .

clesaege commented 6 years ago

@SerpentChris I looked more into it and we may be able to have better typing when https://github.com/ethereum/solidity/issues/1707 will be implemented. This way the Arbitrator contract functions could use types and the Arbitrable contract use a bytes which would be formatted using the encode method offchain. Note that this would not break backward compatibility with the current proposal.

clesaege commented 6 years ago

I added the disputeStatus to the standard.

mbeylin commented 6 years ago

Wanted to add some more concrete thoughts on this EIP after our call @clesaege

function arbitrationCost(bytes _extraData) constant returns(uint fees) What would the suggested functionality be if people decide to pay higher fees than the minimum (so as to better incentivize arbiters?

function appealCost(uint _disputeID, bytes _extraData) constant returns(uint fees) I believe this is not needed, as appeals should not be a necessary element of all disputes.

function createDispute(bytes _extraData) payable returns(uint disputeID) Is it necessary to return the new dispute ID here? This would only be useful if a contract was making that create dispute call. For Delphi, the way we have implemented this is function openClaim(address _claimant, uint _amount, uint _fee, string _data) (where the string serves the same purpose as the data), the _amount is the value of the claim, and the _fee is the value of the fee the claimant desires to pay (greater than the min fee).

function appeal(uint _disputeID, bytes _extraData) payable As mentioned above, I don't believe this should be a part of the standard, since in no way is an appeals process a necessary element of a dispute.

function disputeStatus(uint _disputeID) constant returns (DisputeStatus status) I feel that this function is not needed, in the absence of an appeals process in the standard, a dispute is either ruled or un-ruled, which could easily be checked by the currentRuling(uint _disputeID) function.

In addition to the DisputeCreation(uint indexed _disputeID, Arbitrable _arbitrable) event, I would suggest adding a DisputeRuled(uint indexed _disputeID) event. It is also unclear to me why the Dispute Creation event would include a reference to the Arbitrable contract, since that is the contract which is emitting the event in the first place (right?).

In addition to this, I want to formally advocate for a settlements process that is on-chain, allowing people to settle disputes for a lower amount without having to pay arbiter fees. However, I would be open to settlement functionality not being included in the standard since I understand you (Kleros) don't include that functionality in your mechanism as of right now.

mbeylin commented 6 years ago

I also want to formally share my opinion that I believe it is premature for us to create an ERC for this when we have minimal evidence of the validity of our assumptions. Standards historically have evolved out of market successes (or based on user data about previous versions of a product), however the lack of decentralized dispute resolution mechanism in the market precludes us from making any assertions about what should be in the standard without including some of our own assumptions. I believe we should align on what a general standard for this would look like, and begin employing it, well before we pursue a finalization of this EIP (similarly to how ERC20 was used well before it was finalized).

clesaege commented 6 years ago

function arbitrationCost(bytes _extraData) constant returns(uint fees) What would the suggested functionality be if people decide to pay higher fees than the minimum (so as to better incentivize arbiters?

The standard is not about functionalities, it's about interoperability. The Arbitrator contracts can decide what to do with the extra fees. I guess in most cases, it will be paying more the arbitrators.


function appealCost(uint _disputeID, bytes _extraData) constant returns(uint fees) I believe this is not needed, as appeals should not be a necessary element of all disputes. function appeal(uint _disputeID, bytes _extraData) payable As mentioned above, I don't believe this should be a part of the standard, since in no way is an appeals process a necessary element of a dispute.

With the exception of the centralized arbitrators and Delphi proposals, all dispute resolution proposal I'm aware of (Kleros, Juris, Jury.Online, Aragon, TiiQu) includes an appeal system. If a contract does not allow appeals, it just has to return a high value to forbid it. But when the overwhelming majority of dispute resolution systems off-chain (state court system, ADR which even when they don't include an intra-ADR appeal system, can then be "appealed" by state courts), and on-chain proposals. It seems that the appeal system must belong to the standard. For dispute resolution systems which don't have appeal possibility the extra implementation cost is minimal (a single function which indicates that appeals are not possible). I think we have 3 possible choice:


function createDispute(bytes _extraData) payable returns(uint disputeID) Is it necessary to return the new dispute ID here?

Yes, for cases where an Arbitrable contract has multiple disputes in the same Arbitrator contract, there must be an identifier to know which on to refer to.


In addition to the DisputeCreation(uint indexed _disputeID, Arbitrable _arbitrable) event, I would suggest adding a DisputeRuled(uint indexed _disputeID) event. It is also unclear to me why the Dispute Creation event would include a reference to the Arbitrable contract, since that is the contract which is emitting the event in the first place (right?).

No, the DisputeCreation event is emitted by the Arbitrator contract. This allows to know from the logs which dispute is related to which Arbitrable contracts.


In addition to this, I want to formally advocate for a settlements process that is on-chain, allowing people to settle disputes for a lower amount without having to pay arbiter fees. However, I would be open to settlement functionality not being included in the standard since I understand you (Kleros) don't include that functionality in your mechanism as of right now.

An on-chain settlement process is not included in the standard as this standard is about standardization of interactions between Arbitrator and Arbitrable contracts. Pre-arbitration settlement is a part of a mediation process and an Arbitrator contract not need to be involved. It is perfectly possible to make contracts with a settlement mechanism implementing this standard (for example https://github.com/kleros/kleros-interaction/blob/master/contracts/standard/arbitration/Rental.sol ). For now we haven't identified a need of settlement standardization due to it (in the usecases we have in mind) being well handled by the Arbitrable contract alone. If they were to be need of standardization (I can imagine, some contract making insurance payment depending of results of settlement and mediators paid on result, i.e only when settlement occurs and the dispute is not raised to arbitration), we would be please to collaborate on it.


I also want to formally share my opinion that I believe it is premature for us to create an ERC for this when we have minimal evidence of the validity of our assumptions. Standards historically have evolved out of market successes (or based on user data about previous versions of a product), however the lack of decentralized dispute resolution mechanism in the market precludes us from making any assertions about what should be in the standard without including some of our own assumptions. I believe we should align on what a general standard for this would look like, and begin employing it, well before we pursue a finalization of this EIP (similarly to how ERC20 was used well before it was finalized).

When speaking with projects needing dispute resolution, the contrary opinion has emerged. There a lot of teams building products which need dispute resolution and a handful of teams working on it. The projects which need dispute resolution generally don't want to have to integrate with each dispute resolution provider, especially knowing that those projects are early stage (the whole industry is) and most of them will have failed within a few years. Integration with a standard, instead of a particular project, allows them to let their users choose their dispute resolution system instead of locking them on a particular one. In the absence of standard of interoperability, monopolies could emerge as dapps developers would have to take a specific action to support a dispute resolution mechanism and they would obviously only do it for systems having significant uses. This would provides significant first-mover advantage and barriers of entry. The only assumption being made is that a significant portion of dispute resolution mechanism will include an appeal possibility. Assumption being supported by thousands of years of off-chain disputes resolution process allowing appeals. This does not prevent the standard from working with disputes resolution systems which do not have the possibility of appeals while not including it would prevent the use of dispute resolution systems with an appeal possibility. The possibility for projects to interact with (up to my knowledge) dispute resolution mechanisms which includes appeals, far outweigh the extra unique (you only need to deploy each contract once, as you can use libraries) gas cost of arround 0.01$.

mbeylin commented 6 years ago

Have both BasicArbitrator/BasicArbitrable and AppealableArbitrator/AppealableArbitrable standards.

In my opinion this would be best, similar to how there was a HumanStandardToken which added increased functionality to the StandardToken functionality.

Yes, for cases where an Arbitrable contract has multiple disputes in the same Arbitrator contract, there must be an identifier to know which on to refers to.

Correct, but this information is entirely useless unless it is being returned to another contract for storage since it's impossible for the returned value to be passed to the sender of the original transaction (if the claim is opened by a user). This information should be emitted in an event. I would also like for the claim amount and fee information to be passed as parameters to this function as well (remember when I asked about what happens if a fee is greater than the arbitrationCost? It's because functions like this one now need to know how much you're paying as a fee)

No, the DisputeCreation event is emitted by the Arbitrator contract.

Could you please explain this to me? If a contract is arbitrable, it means it is a contract requiring arbitration, i.e. requiring the opening of claims against it. For our staking mechanism, these arbitrable contracts are the stakes which can have claims opened against them.

When speaking with projects needing dispute resolution, the contrary opinion has emerged. There a lot of teams building products which need dispute resolution and a handful of teams working on it. The projects which need dispute resolution generally don't want to have to integrate with each dispute resolution provider, especially knowing that those projects are early stage (the whole industry is) and most of them will have failed within a few years. Integration with a standard, instead of a particular project, allows them to let their users choose their dispute resolution system instead of locking them on a particular one.

This viewpoint is admirable, and I am largely behind it, however I worry that trying to formalize this standard too early as an officially accepted EIP (instead of it simply serving as a reference for dispute resolution providers and recipients), we'll be screwing ourselves over in the future by requiring new standards to be backwards compatible. Having competitors and collaborators come together on a standard is an important part of the Ethereum developer community, however it requires a light touch, where developers are open to having their ideas questioned and overturned when the market (their users) provides them feedback that their assumptions are wrong.

In terms of including the appeals process in the standard as an extra function (which may revert for implementations without appeals), I believe this is a fine solution for the short term as we test out our implementations and figure out where they break.

It is non-trivial for all disputes to be implemented using the same contract standard, with there generally being various approaches to the dispute resolution problem which don't necessarily mirror the adjudication methods we see in the real world right now. In an effort to encourage this exploration of new and unique methods, we should try to be fluid in our development of this standard, and open to seeing it challenged and amended as we discover what works in practise.

clesaege commented 6 years ago

Correct, but this information is entirely useless unless it is being returned to another contract for storage since it's impossible for the returned value to be passed to the sender of the original transaction (if the claim is opened by a user).

This information is always being returned to another contract. It is returned to the Arbitrable contract per

It should be called by the Arbitrable contract. It must pay at least arbitrationCost(bytes _extraData) weis.

External accounts don't create dispute. Arbitrable contracts do.


This information should be emitted in an event.

This is the case per

This method must fire the DisputeCreation event.


I would also like for the claim amount and fee information to be passed as parameters to this function as well

This is a general dispute resolution standard, claims not need to be monetary. A claim can for example be about blacklisting something (malicious ENS address, irrelevant item, spam) (see this contract for example https://github.com/kleros/kleros-interaction/blob/master/contracts/standard/permission/ArbitrableBlacklist.sol ). Thus the claimed amount cannot be part of the standard. The fee is passed by being send from the Arbitrable contract to the Arbitrator one. It is accessible using msg.value and there obviously no need to repeat that in a parameter.


No, the DisputeCreation event is emitted by the Arbitrator contract.

Could you please explain this to me? If a contract is arbitrable, it means it is a contract requiring arbitration, i.e. requiring the opening of claims against it. For our staking mechanism, these arbitrable contracts are the stakes which can have claims opened against them.

This standard is only about interaction between Arbitrator and Arbitrable contract. External accounts interactions with the Arbitrable contract are out of scope. You can initiate a dispute at the Arbitrable level as you wish, the DisputeCreation is only emitted when this dispute is raised to the Arbitrator contract (for example if you require both parties to deposit the fees, consider parties not deposit the fee to automatically lose, if only one party deposits the fee, no dispute should be raised to the Arbitrator, thus no DisputeCreation event to be emitted).


This viewpoint is admirable, and I am largely behind it, however I worry that trying to formalize this standard too early as an officially accepted EIP (instead of it simply serving as a reference for dispute resolution providers and recipients), we'll be screwing ourselves over in the future by requiring new standards to be backwards compatible.

That's why this ERC has been put in the issue section before making a pull request per the EIP Work Flow described by EIP1 https://github.com/ethereum/EIPs/blob/master/EIPS/eip-1.md :

In particular, the Issues section of this repository is an excellent place to discuss your proposal with the community and start creating more formalized language around your EIP.


In terms of including the appeals process in the standard as an extra function (which may revert for implementations without appeals), I believe this is a fine solution for the short term as we test out our implementations and figure out where they break.

The possibility off appeals cannot break anything. If you don't need it, don't allow appeals. At worse you lost 0.01$ when deploying your contract (only once if using a library). At best you avoided duplicating your Arbitrable contract development code.


It is non-trivial for all disputes to be implemented using the same contract standard, with there generally being various approaches to the dispute resolution problem which don't necessarily mirror the adjudication methods we see in the real world right now.

When there is no interaction between dapps (for example in the case of Augur where they both deal with dispute resolution and enforcement), there is no need to follow a standard. Removing appeals would have the opposite effect of discouraging the exploration of new methods by locking dapps developers to dispute resolution systems where appeals are not possible.


In an effort to encourage this exploration of new and unique methods, we should try to be fluid in our development of this standard, and open to seeing it challenged and amended as we discover what works in practise.

For sure, but in the other way around (not preventing usages but allowing some). If someone were to show a dispute resolution method which could not fit in the standard, I would support modifying it (as long as it would only incurs limited extra gas cost and code complexity) in order to allow this new dispute resolution method. Up to my knowledge, all dispute resolution systems which were proposed so far fits in the standard. If you have a reasonable usecases not fitting, feel free point toward it. The goal of this standard is to provide the minimum number of standardized functions required for interactions between all reasonably imaginable Arbitrator and Arbitrable contracts.

mbeylin commented 6 years ago

It seems we have again found another strong difference in opinion.

For Delphi, claims are opened by people, against particular stakes. Claims ARE for monetary amounts (units of tokens, for what else could be administered on-chain otherwise?) Are you proposing that certain byte code would execute based on these claims? Is that what you intend to store in the bytes array, and not a content hash?

My desire here isn't to simply "remove appeals". We are approaching arbitration in very different manners and assuming that either approach is right from the outset is incorrect. I will apologize that I've had a bit of trouble understanding this architecture you've designed (the flow of actions between the arbitrable contract and the arbitrator contract).

Here is a list of reasons why this standard doesn't currently conform to the dispute resolution mechanism we've outlined with our arbitration mechanism:

Like I said above, there are many differences in our designs, and that should be encouraged, in order to test the assumptions underlying each of them. Trying to create one standard for all possible usecases of arbitration will be very difficult, owing to the variety of instances in life where arbitration is currently used (and the many new ones which are being ideated such as the blacklisting of accounts, or other new on-chain actions).

clesaege commented 6 years ago

for what else could be administered on-chain otherwise?

Items in lists, Oracle answers, Cryptokitties...


Are you proposing that certain byte code would execute based on these claims?

I'm proposing a system which allows the Arbitrable contracts to decide what should be done when a particular ruling is made. If you want to make and Arbitrable contract which execute a byte code of the claimer when the Arbitrator contract rules in its favor, it's perfectly possible within the standard.


Is that what you intend to store in the bytes array, and not a content hash?

No, the bytes contains specific information for the Arbitrator, this allows the arbitration process of one Arbitrator to be specific depending of the _extraData he receives. Thus an arbitration process depends of the (Arbitrator,_extraData) couple. In my example usecase, the _extraData contains the amount of jurors required and default to a particular value if no _extraData is given.


We are approaching arbitration in very different manners and assuming that either approach is right from the outset is incorrect.

That is not the case. I'm approaching arbitration from a general manner to allow every possible usecases (including yours) while you approach arbitration from a particular approach. Your approach (do you have code to link to so I can verify?) seems to be perfectly compatible with the standard.


our interface requires sending a claim amount, fee amount, and is generalized for people to be able to open claims on behalf of others. The current claim creation interface does not allow for this.

The standard interface perfectly allows this. You have to implement this in the Arbitrable contract. The interaction between external accounts and the Arbitrable contracts are out of scope of this standard. Thus nothing prevents what you do.


why are arbitrator fees fixed, and not simply allowed to move freely?

Having arbitration fees not fixed is perfectly possible within the standard. If you want the Arbitrator contract not to require a particular fee, you can make arbitrationCost to return 0. Since the Arbitrable contract must send at least the value returned by arbitrationCost, it will be able to freely decide which value to send.


why are claims opened for an arbiter, and not just in the arbitrable contract (which is the one who must know about the claims, to determine when they may be paid out) . All of the functions pertaining to a particular dispute (its current status) should be implemented in the Arbitrable contract.

You are speaking about claims, the standard does not deal with claims (this does not mean claims are impossible, just that the Arbitrable contract can implement them as the developer wishes). The Arbitrable contract can (and in a lot of cases will) keep note of information about a particular dispute. This part is not about interactions between Arbitrable and Arbitrator contracts, thus out of scope of this standard.


An arbitrable contract should be decoupled from the arbitrator, which should be no more than an address which is allowed to make rulings on particular claims

That the particular point of this standard, decoupling Arbitrable and Arbitrator contracts. However, arbitrators contracts, if more complex than an external account, need to make some particular actions when disputes are brought to them. Thus, they need to know when a dispute arise and if the fees are properly paid. If you want to restrict arbitrator to external accounts, you obviously don't need an kind of standardization.


Like I said above, there are many differences in our designs , and that should be encouraged, in order to test the assumptions underlying each of them.

No, there is not design difference, as the standardization of interactions between Arbitrable and Arbitrator contracts should not care about the design of those. You are making a particular dispute resolution system, I'm making a standard to allow interoperability of those (I'm also making a dispute resolution system, but that not about what this standard is for and I don't try to push the specifics of the dispute resolution system I'm working on to standardization). You are comparing a set (a standard which allow dispute resolution systems) and one element (a particular dispute resolution system). Saying that there is a design difference between a set and one of its element does not make sens.

This abstraction allows Arbitrable contract developers not to have to know the internal process of the Arbitrator contracts.

There is standard framework for interoperability which is perfectly compatible with your design (from what I understood, but again, for me to verify that I'd need to see your code).


Trying to create one standard for all possible usecases of arbitration will be very difficult, owing to the variety of instances in life where arbitration is currently used (and the many new ones which are being ideated such as the blacklisting of accounts, or other new on-chain actions).

Again, feel free to give me a usecase which will not fit in. But note that the standard is about interactions between Arbitrator and Arbitrable contracts and not about the internal specifics of those, nor about their interactions with external accounts.

mbeylin commented 6 years ago

Here is a link to the stake contract, which will be the "arbitrable" contract in the end. This work is still very much WIP and undocumented, but I think you'll quickly see that our implementation of arbitration is not the same as yours. (or maybe it is, and I've simply misunderstood)

https://github.com/Bounties-Network/Delphi/blob/develop/contracts/DelphiStake.sol

clesaege commented 6 years ago

our implementation of arbitration is not the same as yours

Our respective implementations do not matter for standardization. Only the interaction needs to be standardized, not the implementation. I think that a lot of your previous comments are based on the wrong premise that the standard was about implementation.


(or maybe it is, and I've simply misunderstood) https://github.com/Bounties-Network/Delphi/blob/develop/contracts/DelphiStake.sol

I effectively think you misunderstood as your implementation can be slightly modified to fit in the standard. To do so, you need to call createDispute of the Arbitrator contract after it's sure that a dispute would arise, i.e. in settlementFailed https://github.com/Bounties-Network/Delphi/blob/develop/contracts/DelphiStake.sol#L328 You also need to transfer the fee when calling createDispute and not when the ruling is given (but note that the Arbitrator can pay the human arbitrators only when the ruling in given, so in practice, it does not change what the contract is doing from an external observer point of view). Transferring the fee after a ruling is made would lead potential of DDOS of the Arbitrator by creating disputes he has to rule while the Arbitrable contract would never pay the fees. I however see a point where it would not fit. This is that the fees are paid in tokens, not ETH. For Arbitrator and Arbitrable contracts to be inter-operable, they must obviously accept the same currency. If you think it's worthy, you could work on standardizing payment of fees in tokens.

mbeylin commented 6 years ago

You also need to transfer the fee when calling createDispute and not when the ruling is given (but note that the Arbitrator can pay the human arbitrators only when the ruling in given, so in practice, it does not change what the contract is doing from an external observer point of view).

Why are arbiters being paid in advance when we can trustlessly pay them when they rule?

Transferring the fee after a ruling is made would lead potential of DDOS of the Arbitrator by creating disputes he has to rule while the Arbitrable contract would never pay the fees.

If arbiters simply sort their bounties by the value of their fees instead of by their time of creation (or some weighted combination), the spammy bounties will be the lowest value disputes, and can therefore trivially be ignored. Otherwise if spammy claims have a meaningful supply of fees attached, they can choose to rule on them as they please.

clesaege commented 6 years ago

Why are arbiters being paid in advance when we can trustlessly pay them when they rule?

It's not arbiters which are paid in advance, it's the Arbitrator contract. The Arbitrator contract can pay the humans arbitrators when they rule (see for example https://github.com/kleros/kleros-interaction/blob/master/contracts/standard/arbitration/CentralizedArbitrator.sol). Paying only after ruling would require the Arbitrator contract to vet all Arbitrable to verify that they will pay. Otherwise, Arbitrable contract could start disputes consuming resources and never pay. The Arbitrable contracts users choose their Arbitrator contract, so they can choose non-malicious ones. So it's better to ask the Arbitrable contract to pay before engaging the procedure.


If arbiters simply sort their bounties by the value of their fees instead of by their time of creation (or some weighted combination), the spammy bounties will be the lowest value disputes, and can therefore trivially be ignored. Otherwise if spammy claims have a meaningful supply of fees attached, they can choose to rule on them as they please.

Because

mbeylin commented 6 years ago

Paying only after ruling would require the Arbitrator contract to vet all Arbitrable to verify that they will pay

This is why the arbitrable contracts shouldn't be coupled to the arbitrators, who can choose to rule on claims they desire to (and trust) and ignore ones they don't.

The Arbitrable contracts users choose their Arbitrator contract

Why do you assume that the arbitrator must be another contract and can't simply be an individual?

They would need to verify that the Arbitrable contract is effectively going to pay them after they made a ruling.

This is trivially done on the front end by comparing byte code / the master copy which proxies point to.

This will trigger a dispute resolution process which can be resource consuming.

Again, it only triggers that process if arbiters want it to.

As you can see, a number of design differences are beginning to show themselves, and these are fine. However, trying to declare that one design should be STANDARD without any PROOF would be a terrible decision.

clesaege commented 6 years ago

This is why the arbitrable contracts shouldn't be coupled to the arbitrators, who can choose to rule on claims they desire to (and trust) and ignore ones they don't.

That's the precise goal of this standard, providing a standard interface for coupling Arbitrator contracts and Arbitrable contracts. By paying in the createDispute and appeal the Arbitrator can be sure that the arbitration fee is paid before engaging a dispute resolution procedure (in my usecase drawing jurors which will lock some of their tokens, in some other cases, creating a prediction market, in some cases, doing nothing in particular). By potentially consuming resources, it's important that the contract can be assured that it will be paid. We had a choice between requiring Arbitrable contracts to be vetted or Arbitrator one. We choose the Arbitrator because:


Why do you assume that the arbitrator must be another contract and can't simply be an individual?

Another individual can be trivially put as a contract (cf: https://github.com/kleros/kleros-interaction/blob/master/contracts/standard/arbitration/CentralizedArbitrator.sol and we can do even better by using only a unique contract for centralized arbitrators which specifies the address of the centralized arbitrator in _extraData). While a smart contract based dispute resolution system need to be called for the dispute resolution process to be started.


This is trivially done on the front end by comparing byte code / the master copy which proxies point to.

They would need a list of all accepted Arbitrable contract. Would one not paying be included in the list (by fooling the reviewers), the DDOS would happen. A front-end control would not be sufficient as when the Arbitrator contract is called, actions can be done (locking tokens of jurors, creating markets, etc).


Again, it only triggers that process if arbiters want it to.

Dispute resolution systems do not necessarily have people acting as watchdogs of what a dispute could be.


As you can see, a number of design differences are beginning to show themselves, and these are fine. However, trying to declare that one design should be STANDARD without any PROOF would be a terrible decision.

Mark, this is a standard to allow interoperability between Arbitrator and Arbitrable contract. I think you made it clear you were against standardization and that you see "design difference" (even if the only part of your system which would not fit in the standard is the payment in token on which I invite you to also standardize it) while the standard is not about design but interoperability. When we want to let two particular types of components to interact interchangeably which each others, standardization is required. Without standardization, interoperability is not possible. If you are not interested by standardization of interoperability, which by your previous posts seems to be the case, I don't really know what you are doing in this discussion except being rude (shouting, because that is what the use of capitals means in writing), opposing everything and trying to promote your project (you mentioned your project 4 time while I just mentioned mine along a list of others competitors once). The issue section of ERC is not a place to talk about project specifics and standardization should be project independent. If you think you have some constructive input which can be used toward the goal of the ERC and express them in a polite manner feel free to do so. Otherwise I think you can have a better use of your time than trying to prevent people working for interoperability.

mbeylin commented 6 years ago

That's the precise goal of this standard, providing a standard interface for coupling Arbitrator contracts and Arbitrable contracts.

Then this should not be promoted as an "arbitration standard", when it only covers specific cases of arbitration.

I think you made it clear you were against standardization and that you see "design difference" (even if the only part of your system which would not fit in the standard is the payment in token on which I invite you to also standardize it) while the standard is not about design but interoperability.

I am absolutely not against standardization, I have spent the last year pushing for standardization among bounty implementations on Ethereum, which is why I can tell you first hand that standards should evolve and not be enforced in a heavy handed manner. I resent any implication that my hesitation here is because I don't want a standard to exist, since my goal is very much the opposite. But standards must be administered in a prudent manner.

When we want to let two particular types components to interact interchangeably which each others, standardization is required.

This is true, but a standard for arbitration doesn't need to know anything about who is adjudicating the claims (similarly to how the ERC20 contract doesn't know anything about which contract or individual is transacting with tokens).

If you would like to have a standard for Arbitrable contracts, then it should not be coupled to any Arbiter contract. A second standard for Arbiters may be developed independently, and the Arbiters can make sure they are compatible with the Arbitrable contract, but there's no reason for the bidirectional coupling.

Without standardization, interoperability is not possible.

This is only half true, it's entirely possible to pursue interoperability in the short term by working with select groups on connecting Kleros to their dispute resolution needs (and competitors can do so similarly, either following the same interface or a different one). Then, once we have a better understanding of user needs, we can develop a standard. Trying to develop a standard for your product before you have any users is opposite to every product development best practise that exists in the world, and entirely ignores the needs of your future users as they arise.

If you think you have some constructive input which can be used toward the goal of the ERC and express them in a polite manner feel free to do so.

I have tried repeatedly to explain to you why the standard you are developing differs from the way we have built and architected arbitrable contracts (stakes).

Otherwise I think you can have a better use of your time than trying to prevent people working for interoperability to do.

I am not intending to prevent you from rushing into interoperability, I am attempting to prevent an ERC from being formally proposed which not only doesn't agree with other implementations for Arbitration on Ethereum, but is based on no user data about what actual needs will be when launched into production. As I said above, interoperability can be pursued with partners without proposing an ERC; we've done this fruitfully with standard bounties for over a year, and as it turns out, our initial implementation was not complete, and as we gained users, we learned why it was lacking. If we had proposed a standard from the outset, there would be significant complexity from having to support multiple versions simultaneously (and in perpetuity).

As I stated from the outset, we have significant differences in our implementations, and either one of us calling our ideas for Arbitration "complete" would be foolish. I wish you the best of luck with exploring an architecture of tight coupling between arbitrable and arbiter contracts, while we desire to decouple these components as much as possible. Neither of us has hard evidence about why our design pattern is best, so we should wait and collect that evidence before pushing an ERC forward.

mbeylin commented 6 years ago

And for the record, my mention of "my product 4 times" in no way is meant to promote it (who am I promoting it to? other developers who browse EIPs? Those are unlikely going to make up the bulk of an arbitration user base).

I mentioned our product because we have implemented a version of Arbitration that differs very strongly from yours. Not only does your design require high coupling between projects (dApp smart contracts) and arbitrators, it assumes that one single interface for arbitration can be used in all cases where dispute resolution is required.

I apologize that my comments to you seem rude, I've tried to express my disagreement with your view on multiple occasions, and instead of attempting to understand my point of view, you ignore it. We spent 45 minutes on a call during which you repeatedly tried to explain to me about the importance of an "appeals" process, instead of looking at our design differences from a broader perspective. I really don't intend to stunt your growth or hinder your efforts towards interoperability, but there are real-life, long term consequences of building and pushing EIPs forward. For a component as critical to trust transactions as arbitration, we should make sure we get it right.

Also for the record, my use of bold text and upper case letters is meant to serve to emphasize certain points, not to "shout" at you.

clesaege commented 6 years ago

We spent 45 minutes on a call during which you repeatedly tried to explain to me about the importance of an "appeals" process, instead of looking at our design differences from a broader perspective.

Mark, since you are misreporting our interactions, I would not interact with you anymore. The issue section of an ERC is not a place for personal attacks. Your point of view has been understood. Good luck on your ventures. Further off topic comments will be reported to an EIP editor.

mbeylin commented 6 years ago

The issue section of an ERC is not a place for personal attacks.

Was your above comment not littered with personal attacks on my character?

If you decide you are interested in actually collaborating on a standard for Arbitration on Ethereum (and not simply formalizing your teams approach into a standard that others must conform to), I would be happy to help.

stefek99 commented 6 years ago

Two strong opinions, we need an arbitration standard for that...

🤣

clesaege commented 6 years ago

By the way, for those who want to participate in the initial discussions and write-up of the evidence standard feel free to list your usecases and comments there: https://docs.google.com/document/d/1QaCSTZoTjd63q7pt4wne6Mj62p8Ru8xOrxYE5Skyd3c/edit?usp=sharing

clesaege commented 6 years ago

While speaking with developers of origin @wanderingstan , came the proposal to extend this standard to allow payments to be made in token. It would involve adding a function to return which token is accepted (or 0x0 is the Arbitrator accept ETH) by an arbitrator and the possibility of Arbitrator contracts to use transferFrom in createDispute and appeal instead of checking the amount of wei sent.

In case the Arbitrable contract and the Arbitrator one do not want to deal with the same kind of tokens, an Arbitrator Currency Middleware could be used to make on the fly conversion.

mbeylin commented 6 years ago

@clesaege now that some time has passed, I want to enquire again whether you'd be interested in generalizing this EIP/ breaking it up into two separate EIPs: one for arbitrable contracts and one for arbitrator contracts, whereby the arbitrable contracts never make calls to the arbitrator contract (only storing the arbitrator to validate when they make decisions). This would allow both of our approaches to potentially rely on the same standard (with some overlap), rather than pursuing these different approaches entirely independently.

clesaege commented 6 years ago

@mbeylin I stated in the previous posts, what you do can perfectly be done with this standard and there is no different approaches, your approach is included in this standard (except the payment in tokens that my previous post proposed to add).

We can however discuss about moving the createDispute and appeal to the level of the Arbitrable contract.

The advantage of this proposal I see are:

The disadvantage:

Overall, this proposal seem to fit only the case where an external account is the arbitrator but not the cases where the arbitrator is a more complex smart contract.

mbeylin commented 6 years ago

@clesaege by putting the createDispute function into the arbitrable contract, aren't there significant benefits around:

It's also unclear to me why the fee is paid to arbiters when a dispute is created- wouldn't it make more sense for the fees to be sent to the arbiter at the time when they properly rule on the claim?

It's also unclear to me why moving createDispute into the arbitrable contract would require the arbitrator to know anything about who is capable of creating the dispute or what happens to funds in the interim (this logic may live in the arbitrable contract).

Contracts may enforce the notion of only one dispute being opened at a time, rather than allowing competing disputes (again its unclear to me why this logic is at all related to the arbiters themselves).

It would require an interaction with the Arbitrator contract all the time, even there is no dispute.

Could you explain this a bit more? I'm not sure I follow.

Interaction complexity and quantity would increase, the parties in the dispute would need to interact with the Arbitrator contract in addition to the Arbitrable ones. For example in a simple payment dispute, they would need to create a dispute in the Arbitrable contract (to make sure that the payment is delayed up to the result of the arbitrators) and in the Arbitrator one this lead to more gas spending and higher code complexity (thus risk of bugs).

Again you allude to the need for users to interact with the arbitrator contract in-protocol, but again it's not clear why.

Arbitrable contracts would loose the freedom to determine the fees.

This is categorically false: if arbitrable contracts are creating disputes with a given fee, and communicate this dispute to arbiters out-of-protocol, then arbiters may freely decide to rule on claims which provides a sufficient fee to satisfy them, and ignore those which don't. This allows the prices for dispute resolution to move much more freely than in your current implementation (where the price must for some reason be set in the contact). The problem of pricing is compounded when you start to think about fees paid in a myriad of tokens: how many units of a given token that will be sufficient to incentivize arbiters may change over time, and allowing arbiters to ignore claims which are insufficient is a great solution. Since the initiators of claims are always incentivized to get their claims resolved as quickly as possible, we know they'll always seek pricing information on current arbiter fees (out of protocol), and pay the necessary fees.

This fee structure begins to resemble the way transaction markets work on Ethereum: the protocol doesn't reject transactions which are below a fee which is explicitly set by miners, they simply wait in a pool of txns until the volume is such that they get picked up.

clesaege commented 6 years ago

@clesaege by putting the createDispute function into the arbitrable contract, aren't there significant benefits around:

  • limiting who may create disputes for a given type of smart contract
  • freezing assets/state in the contract pending a ruling

I think you mean requiring parties in a dispute to interact with the Arbitrable contract instead of the Arbitrator one. And that exactly what the standard requires. Parties in a dispute interact with Arbitrable contracts and never with the Arbitrator one. So when they start the process to create a dispute, the Arbitrator contract could freeze fund. The standard has the behaviour you want.

It's also unclear to me why the fee is paid to arbiters when a dispute is created- wouldn't it make more sense for the fees to be sent to the arbiter at the time when they properly rule on the claim?

The fee is not paid directly to the arbiters when a dispute is created, it is paid to the Arbitrator contract which can then pay the individuals doing the arbitration work when it's done. See https://github.com/kleros/kleros-interaction/blob/master/contracts/standard/arbitration/CentralizedArbitrator.sol and https://github.com/kleros/kleros/blob/master/contracts/Kleros.sol as examples. So again the standard has the behaviour you want.

It's also unclear to me why moving createDispute into the arbitrable contract would require the arbitrator to know anything about who is capable of creating the dispute or what happens to funds in the interim (this logic may live in the arbitrable contract).

Because the Arbitrator would need to know who can can create a dispute. While in the current proposal, this logic is given to the Arbitrable contract. If the parties where to interact directly with the Arbitrator, the Arbitrable contract would not be aware that a dispute is raised and could not freeze assets (unless there is other interactions).

Contracts may enforce the notion of only one dispute being opened at a time, rather than allowing competing disputes (again its unclear to me why this logic is at all related to the arbiters themselves).

Yeah, they can do so with the current proposal: since creating disputes must go through the Arbitrable contract, it can restrict dispute creation to only one per X. If it was possible to create them directly through the Arbitrator one, it could not restrict the amount of disputes (or would need to restrict it to one per Arbitrable contract which would cause issues when an Arbitrable contract can handle multiple disputes).

Again you allude to the need for users to interact with the arbitrator contract in-protocol, but again it's not clear why.

No I don't, my previous post was just a though experiment of what would happen if we were to move the createDispute to the Arbitrable contract. It is not what I propose. So again, the proposal seem to be conform to you wishes.

Arbitrable contracts would loose the freedom to determine the fees.

This is categorically false: if arbitrable contracts are creating disputes with a given fee, and communicate this dispute to arbiters out-of-protocol, then arbiters may freely decide to rule on claims which provides a sufficient fee to satisfy them, and ignore those which don't.

Sorry for the confusion, I mean determine who pays the fee. In the current proposal Arbitrator determines the amount of the fees. So it still behave as you wish.

This allows the prices for dispute resolution to move much more freely than in your current implementation (where the price must for some reason be set in the contact).

No, the Arbitrator contract determines a minimum, it's possible to pay more and it is possible for arbitrators to change the amount required. It then allow you to do what you just explained.

Overall everything can behave as you declared you wish it to behave (except paying in token, thus my previous post proposing to add it).

mbeylin commented 6 years ago

The fee is not paid directly to the arbiters when a dispute is created, it is paid to the Arbitrator contract which can then pay the individuals doing the arbitration work when it's done.

But why bother putting the funds in the arbitrator contract in the first place ahead of time, why not just pay out when the decision is submitted? Why is this extra trust being placed on the arbitrator contract (to not allow funds to be taken without ever submitting a ruling) instead of just programming the arbitrable contract to remove this problem altogether?

I think the key in my mind, as a developer who would rely on this standard for only the arbitrable contract (and not the arbitrator contract), is that the contract should not be required to make any assumptions about the address which acts as an arbiter- whether it be an individual or a group. Right now the two contracts are tightly coupled: the arbitrable contract must be calling the arbitrator to discover minimum fees and to notify them (for instance). Do you think it would be possible for us to relax these assumptions to support this use case?

clesaege commented 6 years ago

But why bother putting the funds in the arbitrator contract in the first place ahead of time, why not just pay out when the decision is submitted?

Because otherwise, malicious parties could start an expensive process without paying.

But why bother putting the funds in the arbitrator contract in the first place ahead of time, why not just pay out when the decision is submitted?

Because the parties trust the Arbitrator contract as they would not have chosen it otherwise. Note that requiring to have a ruling would not provide anymore protection as malicious arbitrator could just rule randomly.

I think the key in my mind, as a developer who would rely on this standard for only the arbitrable contract

This standard is for interoperability between Arbitrable and Arbitrator contracts, if you don't have any Arbitrator contract, you don't need to use this standard.

Do you think it would be possible for us to relax these assumptions to support this use case?

No, the purpose of this standard is to have this coupling. We discussed previously the effects removing this coupling would have and your previous post showed that you wanted property only possible with this coupling.

@mbeylin Your posts show that you are not interested nor needing what this standard is doing. That's completely fine and we do not try to force you to do anything. I think it would be better to start some other discussion (on the Ethereum forum for instance) in order to keep the comments there for people working to improve this standard. And come back to the previous discussion topic.

clesaege commented 6 years ago

Coming back to improvement proposals, what do you think of adding the possibility to pay in tokens?

clesaege commented 6 years ago

You can review the evidence standard proposal https://docs.google.com/document/d/1AsGt_Am2rbZwCd6FULfl4ssMIlo_WZVhjo8V7ZFztmo/ . If there is no issues found we'll submit it as an ERC.

TimDaub commented 5 years ago

Great standard. A minor thing:

function rule(uint _dispute, uint _ruling)

Why is uint _dispute not called uint _disputeID?

clesaege commented 5 years ago

Thanks @TimDaub for the remark, I just fixed this (note that it does not lead to any backward compatibility issues as variable names are not used when creating the function signature).

greenlucid commented 4 years ago

I propose adding the following to IArbitrable:

function changeArbitrator(address _newArbitrator) external;

This would change the Arbitrator the Arbitrable calls to a new one. I am a bit conflicted with this, as it might be limiting to Arbitrables that do not wish to add this function, but it's too common of an use case to simply ignore. Arbitrables lacking this function will be forced to die or migrate to a new contract if:

In practice, it would be accompanied by an onlyGovernor modifier. What do you think? Is this limiting?

cbruguera commented 3 years ago

@clesaege Has there been any updates to this proposal with the option to pay fees in tokens? I was checking the Kleros implementation but I think fees are paid in ETH. I was wondering if the standard as it's been currently proposed can easily allow the pay-in-tokens possibility or it would need some changes. I think this is important if aiming to become an interoperable standard.

cbruguera commented 3 years ago

I propose adding the following to IArbitrable:

function changeArbitrator(address _newArbitrator) external;

This would change the Arbitrator the Arbitrable calls to a new one. I am a bit conflicted with this, as it might be limiting to Arbitrables that do not wish to add this function, but it's too common of an use case to simply ignore. Arbitrables lacking this function will be forced to die or migrate to a new contract if:

* Arbitrator is compromised

* Arbitrator is deprecated and jurors migrate to a new one

* Arbitrable decides Arbitrator no longer can cover its needs

* Better Arbitrators are available (cheaper, faster, or bigger quality) and Arbitrable wants to swap

In practice, it would be accompanied by an onlyGovernor modifier. What do you think? Is this limiting?

I think your idea assumes that an Arbitrable contract only has one Arbitrator, which (as the proposal makes clear) is not necessarily the case. Arbitrable contracts could have a list of multiple arbitrarors and their own complex logic for choosing or changing those according to the case. What needs to be standardized is the interface of function calls between Arbitrable and Arbitrator, which this proposal seems to cover IMO.

cbruguera commented 3 years ago

@clesaege In case you check this, I'm dealing with the question of how does an Arbitrator provide additional data specific to a ruling?... For example, Arbiter is deciding on a dispute over staked tokens, therefore should be able to execute rule for slashing a specific amount. The current ruling parameter only offers discrete options, and there's no "extraData" proposed for the rule function... Any ideas?

github-actions[bot] commented 2 years ago

There has been no activity on this issue for two months. It will be closed in a week if no further activity occurs. If you would like to move this EIP forward, please respond to any outstanding feedback or add a comment indicating that you have addressed all required feedback and are ready for a review.

github-actions[bot] commented 2 years ago

This issue was closed due to inactivity. If you are still pursuing it, feel free to reopen it and respond to any feedback or request a review in a comment.