-
Notifications
You must be signed in to change notification settings - Fork 8
WIP: build boson-kleros integration poc #488
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,12 @@ | ||
| // SPDX-License-Identifier: MIT | ||
| pragma solidity ^0.8; | ||
|
|
||
| interface IEscalatable { | ||
| function escalateDispute( | ||
| uint256 _exchangeId, | ||
| uint256 _buyerPercent, | ||
| uint256 _sellerPercent | ||
| ) external; | ||
|
|
||
| function escalationCost() external returns (uint256 _cost); | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,8 @@ | ||
| // SPDX-License-Identifier: MIT | ||
| pragma solidity ^0.8; | ||
|
|
||
| interface IEscalationResolver { | ||
| function decideDispute(uint256 _exchangeId, uint256 _buyerPercent) external; | ||
|
|
||
| function refuseEscalatedDispute(uint256 _exchangeId) external; | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -115,18 +115,9 @@ interface IBosonDisputeHandler is IBosonDisputeEvents, IBosonFundsLibEvents { | |
| * - Dispute was escalated and escalation period has elapsed | ||
| * | ||
| * @param _exchangeId - the id of the associated exchange | ||
| * @param _buyerPercent - percentage of the pot that goes to the buyer | ||
| * @param _sigR - r part of the signer's signature | ||
| * @param _sigS - s part of the signer's signature | ||
| * @param _sigV - v part of the signer's signature | ||
| * @param _percent - percentage of the pot that goes to the buyer | ||
| */ | ||
| function resolveDispute( | ||
| uint256 _exchangeId, | ||
| uint256 _buyerPercent, | ||
| bytes32 _sigR, | ||
| bytes32 _sigS, | ||
| uint8 _sigV | ||
| ) external; | ||
| function resolveDispute(uint256 _exchangeId, uint256 _percent) external; | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. See objections to this below on the
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Added changes and Rationale to the BPIP |
||
|
|
||
| /** | ||
| * @notice Puts the dispute into the Escalated state. | ||
|
|
@@ -211,14 +202,12 @@ interface IBosonDisputeHandler is IBosonDisputeEvents, IBosonFundsLibEvents { | |
| * @return dispute - the dispute details. See {BosonTypes.Dispute} | ||
| * @return disputeDates - the dispute dates details {BosonTypes.DisputeDates} | ||
| */ | ||
| function getDispute(uint256 _exchangeId) | ||
| function getDispute( | ||
| uint256 _exchangeId | ||
| ) | ||
| external | ||
| view | ||
| returns ( | ||
| bool exists, | ||
| BosonTypes.Dispute memory dispute, | ||
| BosonTypes.DisputeDates memory disputeDates | ||
| ); | ||
| returns (bool exists, BosonTypes.Dispute memory dispute, BosonTypes.DisputeDates memory disputeDates); | ||
|
|
||
| /** | ||
| * @notice Gets the state of a given dispute. | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,62 @@ | ||
| // SPDX-License-Identifier: MIT | ||
| pragma solidity ^0.8; | ||
| // THIS CONTRACT IS IMPLEMENTED FOR INOFRMATION PURPOSES AND SHOULD NOT BE USED IN PRODUCTION | ||
|
|
||
| import { IArbitrator } from "./IArbitrator.sol"; | ||
| import { IArbitrable } from "./IArbitrable.sol"; | ||
| import { IMetaEvidence } from "./IMetaEvidence.sol"; | ||
| import { IEscalatable } from "../interfaces/escalation/IEscalatable.sol"; | ||
| import { IEscalationResolver } from "../interfaces/escalation/IEscalationResolver.sol"; | ||
|
|
||
| contract BosonKlerosConnector is IEscalatable, IArbitrable, IMetaEvidence { | ||
0xartem marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| error InvalidExchangeError(); | ||
|
|
||
| struct BosonCase { | ||
| uint256 exchangeId; | ||
| uint256 buyerPercent; | ||
| uint256 sellerPercent; | ||
| // TODO: evidence data | ||
| } | ||
|
|
||
| IArbitrator arbitrator; | ||
| IEscalationResolver escalationResolver; | ||
|
|
||
| mapping(uint256 => BosonCase) klerosDisputeCases; | ||
|
|
||
| constructor(IArbitrator _arbitrator, IEscalationResolver _escalationResolver) { | ||
| arbitrator = _arbitrator; | ||
| escalationResolver = _escalationResolver; | ||
| } | ||
|
|
||
| function escalateDispute(uint256 _exchangeId, uint256 _buyerPercent, uint256 _sellerPercent) external { | ||
| // 3 is a number of ruling options. For example: 1 - buyer proposal, 2 - seller proposal, 3 - refuse to decide | ||
| uint256 disputeId = arbitrator.createDispute(3, ""); | ||
| klerosDisputeCases[disputeId] = BosonCase(_exchangeId, _buyerPercent, _sellerPercent); | ||
| } | ||
|
|
||
| function escalationCost() external view returns (uint256 _cost) { | ||
| return arbitrator.arbitrationCost(""); | ||
| } | ||
|
|
||
| /** | ||
| * @dev Give a ruling for a dispute. Must be called by the arbitrator. | ||
| * The purpose of this function is to ensure that the address calling it has the right to rule on the contract. | ||
| * @param _disputeID ID of the dispute in the Arbitrator contract. | ||
| * @param _ruling Ruling given by the arbitrator. Note that 0 is reserved for "Not able/wanting to make a decision". | ||
| */ | ||
| function rule(uint256 _disputeID, uint256 _ruling) external { | ||
| BosonCase memory bosonCase = klerosDisputeCases[_disputeID]; | ||
| if (bosonCase.exchangeId == 0) revert InvalidExchangeError(); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is the emission of an Error required by Kleros? Otherwise this would need to be implemented as a revert reason. We discussed implementing formal Error types but we were too far along the development track to do that before deploying V2, so we're kind of stuck with the style. We definitely shouldn't mix and match unless there's an absolute requirement. That's said, it's in a client, which is a boundary contract that could conceivably be given a pass if there's no other option.
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There is no such requirement from Kleros. It can be modified to match Boson coding style. |
||
|
|
||
| // Assume 3 is refusal to decide, 1 - buyer proposal is accepted, 2 - seller proposal is accepted | ||
| if (_ruling == 1) { | ||
| escalationResolver.decideDispute(bosonCase.exchangeId, bosonCase.buyerPercent); | ||
| } else if (_ruling == 2) { | ||
| escalationResolver.decideDispute(bosonCase.exchangeId, 10000 - bosonCase.sellerPercent); | ||
| } else { | ||
| escalationResolver.refuseEscalatedDispute(bosonCase.exchangeId); | ||
| } | ||
|
|
||
| emit Ruling(arbitrator, _disputeID, _ruling); | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,34 @@ | ||
| // SPDX-License-Identifier: MIT | ||
|
|
||
| pragma solidity ^0.8; | ||
|
|
||
| import "./IArbitrator.sol"; | ||
|
|
||
| /** | ||
| * @title IArbitrable | ||
| * Arbitrable interface. Note that this interface follows the ERC-792 standard. | ||
| * When developing arbitrable contracts, we need to: | ||
| * - Define the action taken when a ruling is received by the contract. | ||
| * - Allow dispute creation. For this a function must call arbitrator.createDispute{value: _fee}(_choices,_extraData); | ||
| */ | ||
| interface IArbitrable { | ||
| /** | ||
| * @dev To be raised when a ruling is given. | ||
| * @param _arbitrator The arbitrator giving the ruling. | ||
| * @param _disputeID ID of the dispute in the Arbitrator contract. | ||
| * @param _ruling The ruling which was given. | ||
| */ | ||
| event Ruling( | ||
| IArbitrator indexed _arbitrator, | ||
| uint256 indexed _disputeID, | ||
| uint256 _ruling | ||
| ); | ||
|
|
||
| /** | ||
| * @dev Give a ruling for a dispute. Must be called by the arbitrator. | ||
| * The purpose of this function is to ensure that the address calling it has the right to rule on the contract. | ||
| * @param _disputeID ID of the dispute in the Arbitrator contract. | ||
| * @param _ruling Ruling given by the arbitrator. Note that 0 is reserved for "Not able/wanting to make a decision". | ||
| */ | ||
| function rule(uint256 _disputeID, uint256 _ruling) external; | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,48 @@ | ||
| // SPDX-License-Identifier: MIT | ||
|
|
||
| pragma solidity ^0.8; | ||
|
|
||
| import "./IArbitrable.sol"; | ||
|
|
||
| /** | ||
| * @title Arbitrator | ||
| * Arbitrator interface that implements the new arbitration standard. | ||
| * Unlike the ERC-792 this standard doesn't have anything related to appeals, so each arbitrator can implement an appeal system that suits it the most. | ||
| * When developing arbitrator contracts we need to: | ||
| * - Define the functions for dispute creation (createDispute). Don't forget to store the arbitrated contract and the disputeID (which should be unique, may nbDisputes). | ||
| * - Define the functions for cost display (arbitrationCost). | ||
| * - Allow giving rulings. For this a function must call arbitrable.rule(disputeID, ruling). | ||
| */ | ||
| interface IArbitrator { | ||
| /** | ||
| * @dev To be emitted when a dispute is created. | ||
| * @param _disputeID ID of the dispute. | ||
| * @param _arbitrable The contract which created the dispute. | ||
| */ | ||
| event DisputeCreation( | ||
| uint256 indexed _disputeID, | ||
| IArbitrable indexed _arbitrable | ||
| ); | ||
|
|
||
| /** | ||
| * @dev Create a dispute. Must be called by the arbitrable contract. | ||
| * Must pay at least arbitrationCost(_extraData). | ||
| * @param _choices Amount of choices the arbitrator can make in this dispute. | ||
| * @param _extraData Can be used to give additional info on the dispute to be created. | ||
| * @return disputeID ID of the dispute created. | ||
| */ | ||
| function createDispute(uint256 _choices, bytes calldata _extraData) | ||
| external | ||
| payable | ||
| returns (uint256 disputeID); | ||
|
|
||
| /** | ||
| * @dev Compute the cost of arbitration. It is recommended not to increase it often, as it can be highly time and gas consuming for the arbitrated contracts to cope with fee augmentation. | ||
| * @param _extraData Can be used to give additional info on the dispute to be created. | ||
| * @return cost Required cost of arbitration. | ||
| */ | ||
| function arbitrationCost(bytes calldata _extraData) | ||
| external | ||
| view | ||
| returns (uint256 cost); | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,12 @@ | ||
| // SPDX-License-Identifier: MIT | ||
| pragma solidity ^0.8; | ||
|
|
||
| interface IEscalatable { | ||
| function escalateDispute( | ||
| uint256 _exchangeId, | ||
| uint256 _buyerPercent, | ||
| uint256 _sellerPercent | ||
| ) external; | ||
|
|
||
| function escalationCost() external returns (uint256 _cost); | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,8 @@ | ||
| // SPDX-License-Identifier: MIT | ||
| pragma solidity ^0.8; | ||
|
|
||
| interface IEscalationResolver { | ||
| function decideDispute(uint256 _exchangeId, uint256 _buyerPercent) external; | ||
|
|
||
| function refuseEscalatedDispute(uint256 _exchangeId) external; | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,24 @@ | ||
| // SPDX-License-Identifier: MIT | ||
|
|
||
| pragma solidity ^0.8.0; | ||
|
|
||
| import "./IArbitrator.sol"; | ||
|
|
||
| /** @title IEvidence | ||
| * ERC-1497: Evidence Standard | ||
| */ | ||
| interface IEvidence { | ||
| /** | ||
| * @dev To be raised when evidence is submitted. Should point to the resource (evidences are not to be stored on chain due to gas considerations). | ||
| * @param _arbitrator The arbitrator of the contract. | ||
| * @param _evidenceGroupID Unique identifier of the evidence group the evidence belongs to. | ||
| * @param _party The address of the party submiting the evidence. Note that 0x0 refers to evidence not submitted by any party. | ||
| * @param _evidence IPFS path to evidence, example: '/ipfs/Qmarwkf7C9RuzDEJNnarT3WZ7kem5bk8DZAzx78acJjMFH/evidence.json' | ||
| */ | ||
| event Evidence( | ||
| IArbitrator indexed _arbitrator, | ||
| uint256 indexed _evidenceGroupID, | ||
| address indexed _party, | ||
| string _evidence | ||
| ); | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,32 @@ | ||
| // SPDX-License-Identifier: MIT | ||
|
|
||
| pragma solidity ^0.8.0; | ||
|
|
||
| import "./IArbitrator.sol"; | ||
| import "./IEvidence.sol"; | ||
|
|
||
| /** @title IEvidence | ||
| * ERC-1497: Evidence Standard | ||
| */ | ||
| interface IMetaEvidence is IEvidence { | ||
| /** | ||
| * @dev To be emitted when meta-evidence is submitted. | ||
| * @param _metaEvidenceID Unique identifier of meta-evidence. | ||
| * @param _evidence IPFS path to metaevidence, example: '/ipfs/Qmarwkf7C9RuzDEJNnarT3WZ7kem5bk8DZAzx78acJjMFH/metaevidence.json' | ||
| */ | ||
| event MetaEvidence(uint256 indexed _metaEvidenceID, string _evidence); | ||
|
|
||
| /** | ||
| * @dev To be emitted when a dispute is created to link the correct meta-evidence to the disputeID. | ||
| * @param _arbitrator The arbitrator of the contract. | ||
| * @param _disputeID ID of the dispute in the Arbitrator contract. | ||
| * @param _metaEvidenceID Unique identifier of meta-evidence. | ||
| * @param _evidenceGroupID Unique identifier of the evidence group that is linked to this dispute. | ||
| */ | ||
| event Dispute( | ||
| IArbitrator indexed _arbitrator, | ||
| uint256 indexed _disputeID, | ||
| uint256 _metaEvidenceID, | ||
| uint256 _evidenceGroupID | ||
| ); | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Changing the
Disputestruct is dangerous. There are implications for existing storage.For these reasons, we would more likely want to associate these new fields with the dispute via a mapping and not change the struct and all the client code (including the graph) that relies on its current shape.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Noted, will change it in the new PR.