Kleros
Kleros.ioGithub
  • Introduction to Kleros
  • Kleros FAQ
  • Governance
  • PNK Token
  • They talk about Kleros
  • Products
    • Court
      • Kleros Juror Tutorial
      • Famous Kleros Cases
      • What happens during a dispute?
      • Kleros & Credible Neutrality
    • Court V2
    • Proof of Humanity
      • Proof of Humanity 2.0 Tutorial: (Register & Vouch)
      • Proof of Humanity 2.0 Tutorial (Remove & Challenge)
      • Proof of Humanity 2.0 Tutorial (Transferring a Profile)
      • Proof of Humanity 2.0 Integration Guide
      • Proof of Humanity FAQ
        • Proof of Humanity 2.0 launch FAQ
    • Curate
      • Kleros Curate Tutorial
      • Kleros Scout
        • Tutorial
        • Earn With Kleros Scout
        • Partnerships
        • Kleros Scout - Metamask Snaps
          • Knowledge Base
        • FAQs
    • Oracle
    • Governor
    • Escrow
      • Kleros Escrow Tutorial
      • Kleros Escrow Specifications
    • Linguo
      • Kleros Linguo Tutorial
      • Step-by-step Tutorial
        • Requesting translations
        • Working as a translator
        • Reviewing translations
      • F.A.Q
      • High-level Overview
    • Moderate
      • Susie
        • Getting Started
          • Add Susie
          • Start Susie
        • Basics
          • Welcome
          • Language
          • Notifications
        • Rules
        • Reports
        • Evidence
        • Federations
  • INTEGRATIONS
    • Overview
    • Industry use cases
    • Types of Integrations
      • 1. Dispute resolution integration plan
        • Smart contract integration with Kleros Court (Arbitrator)
        • Use Cases
          • DeFi Insurance
          • Gaming
          • Recognition of Jurisdiction Integration
            • Integración por Reconocimiento de Jurisdicción
        • Channel partners
          • How to use Reality.eth + Kleros as an oracle
          • Safe Zodiac integration
          • Kleros Reality Module
        • Integration Tools
          • Centralized Arbitrator
          • Dispute Resolver
      • 2. Curated-data integration plan
        • Retrieving information from Kleros Dapps
    • Policy writing guide
    • Live & Upcoming Integrations
    • Kleros Analytics
    • Scalability & Cross-chain
      • Using Kleros arbitration for Dapps on xDai/Gnosis
    • Integrations FAQ
  • Developers
    • Arbitration Development
      • ERC-792: Arbitration Standard
      • ERC 1497: Evidence Standard
      • Arbitrable Proxy
    • Arbitration by Example
      • ArbitrableDeposit.sol
      • TwoPartyArbitrable.sol
      • Rental.sol
      • ArbitrableTransaction.sol
      • MultipleArbitrableTransaction.sol
      • MultipleArbitrableTokenTransaction.sol
    • Deployment Addresses
    • Curate Classic: Integration for Devs
    • Light Curate: Integration for Devs
    • Guide for Preparing Transactions
  • Contribution Guidelines
    • Overview
    • General Dev. Workflow
      • Task Tracking & Lifecycle
      • Releases
    • Smart Contract Workflow
      • Task Tracking & Lifecycle
      • RAB - Review, Audit, Bounty
      • RABd (+ Deploy)
      • Reporting Vulnerabilities
    • Code Style and Guidelines
      • Git
      • Solidity
      • Web Languages
    • License & Code of Conduct
      • License
      • Code of Conduct
  • Additional Resources
    • Discord
    • Telegram
    • Governance Forum
    • Twitter
    • Blog
    • Reddit
    • Github
    • Slack
Powered by GitBook
On this page
  • Getting Started
  • Step 1:
  • Step 2:
  • Step 3:

Was this helpful?

Edit on GitHub
  1. Developers
  2. Arbitration Development

Arbitrable Proxy

A simpler way to build arbitrable applications.

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

// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import "@kleros/erc-792/contracts/IArbitrator.sol";

/**
 *  @title IArbitrableProxy
 *  A general purpose arbitrable contract. Supports non-binary rulings.
 */
interface IArbitrableProxy {
    function arbitrator() external view returns (IArbitrator arbitrator);

    function createDispute(
        bytes calldata _arbitratorExtraData,
        string calldata _metaevidenceURI,
        uint256 _numberOfRulingOptions
    ) external payable returns (uint256 disputeID);

    struct DisputeStruct {
        bytes arbitratorExtraData;
        bool isRuled;
        uint256 ruling;
        uint256 disputeIDOnArbitratorSide;
    }

    function externalIDtoLocalID(
        uint256 _externalID
    ) external returns (uint256 localID);

    function disputes(
        uint256 _localID
    )
        external
        returns (
            bytes memory extraData,
            bool isRuled,
            uint256 ruling,
            uint256 disputeIDOnArbitratorSide
        );

    function submitEvidence(uint256 _localDisputeID, string calldata _evidenceURI) external;
}

Usage

contract MyArbitrable {
    IArbitrableProxy arbitrableProxy = IArbitrableProxy(<ARBITRATOR_ADDRESS>);
}

Step 2:

Create disputes through the proxy and paying the arbitration cost through the same transaction.

contract MyArbitrable {
    IArbitrableProxy arbitrableProxy = IArbitrableProxy(<ARBITRATOR_ADDRESS>);
    
    function foo(
        bytes calldata extraData, 
        string memory evidenceURI, 
        uint256 rulingOptions
        ) {
        uint256 disputeID = arbitrableProxy.createDispute{value: msg.value}(
            extraData, 
            evidenceURI, 
            rulingOptions
            );
            
        // do something with disputeID
    }
}

Step 3:

Create a fetchRuling function.

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.sol

contract ArbitrableProxy is IDisputeResolver {
    // ...
    // ...
    // ...
    struct DisputeStruct {
        bytes arbitratorExtraData;
        bool isRuled;
        uint256 ruling;
        uint256 disputeIDOnArbitratorSide;
    }
    
    DisputeStruct[] public disputes;
    
    function rule(uint256 _externalDisputeID, uint256 _ruling) external override {
        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];
        }

        emit Ruling(IArbitrator(msg.sender), _externalDisputeID, dispute.ruling);
    }
}
contract MyArbitrable {
    IArbitrableProxy arbitrableProxy = IArbitrableProxy(<ARBITRATOR_ADDRESS>);
    function foo(
        bytes calldata extraData, 
        string memory evidenceURI, 
        uint256 rulingOptions
        ) {
        uint256 disputeID = arbitrableProxy.createDispute{value: msg.value}(
            extraData, 
            evidenceURI, 
            rulingOptions
            );
            
        // do something with disputeID
    }
    
    function fetchRuling(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.

PreviousERC 1497: Evidence StandardNextArbitration by Example

Last updated 3 months ago

Was this helpful?

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