The arbitrable proxy contract abstracts away most of the heavy lifting associated with implementing the ERC792 and ERC1497 standards from scratch in an arbitrable application. It abstracts away the evidence and appeal management logic from your contact, requiring you to handle just the dispute creation and ruling retrieval logic.
Getting Started
Step 1:
Import the IArbitrableProxy interface into your project
Create disputes through the proxy and paying the arbitration cost through the same transaction.
The arbitration cost paid when calling the createDispute() function of the arbitrableProxy is the same as that of calling the same function on the final arbitrator (i.e. Kleros Court). The cost estimation is therefore best done by directly polling it from the final arbitrator (i.e. the arbitrationCost() function of Kleros Liquid)
A key difference between using the proxy and implementing your own ERC792 arbitrable from scratch is that a rule function is not directly called in your contract by the arbitrator. The proxy stores the data of rulings locally in an array and its up to you to query the rulings relevant to your contract.
Let's first take a look at how rulings are stored on the arbitrable proxy then move on to how to implement a fetchRuling function in your contract.
/// https://github.com/kleros/arbitrable-proxy-contracts/blob/master/contracts/ArbitrableProxy.solcontractArbitrableProxyisIDisputeResolver {// ...// ...// ...structDisputeStruct {bytes arbitratorExtraData;bool isRuled;uint256 ruling;uint256 disputeIDOnArbitratorSide; } DisputeStruct[] public disputes;functionrule(uint256_externalDisputeID,uint256_ruling) externaloverride {uint256 localDisputeID = externalIDtoLocalID[_externalDisputeID]; DisputeStruct storage dispute = disputes[localDisputeID];require(msg.sender ==address(arbitrator),"Only the arbitrator can execute this.");require(_ruling <= numberOfRulingOptions[localDisputeID],"Invalid ruling.");require(dispute.isRuled ==false,"This dispute has been ruled already."); dispute.isRuled =true; dispute.ruling = _ruling; Round[] storage rounds = disputeIDtoRoundArray[localDisputeID]; Round storage lastRound = disputeIDtoRoundArray[localDisputeID][rounds.length -1]; // If only one ruling option is funded, it wins by default. Note that if any other ruling had funded, an appeal would have been created.
if (lastRound.fundedRulings.length ==1) { dispute.ruling = lastRound.fundedRulings[0]; }emitRuling(IArbitrator(msg.sender), _externalDisputeID, dispute.ruling); }}
contract MyArbitrable { IArbitrableProxy arbitrableProxy =IArbitrableProxy(<ARBITRATOR_ADDRESS>);functionfoo(bytescalldata extraData,stringmemory evidenceURI,uint256 rulingOptions ) {uint256 disputeID = arbitrableProxy.createDispute{value: msg.value}( extraData, evidenceURI, rulingOptions );// do something with disputeID }functionfetchRuling(uint256 disputeID) { (,bool isRuled,uint256 ruling) = arbitrableProxy.disputes(disputeID)// do something with ruling if isRuled }}
And that's it! With this, you would have a fully trustless integration with Kleros Court for less than half the work of a fully ERC792 compliant integration.