kleros / kleros-v2

Kleros version 2
https://v2.kleros.builders
MIT License
62 stars 44 forks source link

Dispute template data mappings #1083

Open jaybuidl opened 1 year ago

jaybuidl commented 1 year ago

Overview

The data mappings describe how the variables from the dispute templates are populated from a data source.

The following data sources are initially supported: json (=hardcoded), subgraph, abi/call, abi/event, fetch/ipfs/json

A generic fetch might be added if really necessary, but likely requires additional security considerations to prevent XSS.

Example

Input 1: Dispute Template

{
    "title": "A reality.eth question",
    "description": "A reality.eth question has been raised to arbitration.",
    "frontendUrl": "https://reality.eth.limo/app/#!/question/{{ realityAddress }}-{{ questionId }}",
}

Input 2: Dispute Template Mappings

This is a basic mapping with hardcoded data (json type). A more advanced example would retrieve the values from an onchain event or a subgraph endpoint.

[
  {
    "type": "json",
    "value": {
      "questionId": "0xe2a3bd38e3ad4e22336ac35b221bbbdd808d716209f84014c7bc3bf62f8e3b39",
      "realityAddress": "0x14a6748192aBC6E10CA694Ae07bDd4327D6c7A51"
    },
    "seek": [
      "questionId",
      "realityAddress"
    ],
    "populate": [
      "questionId",
      "realityAddress"
    ]
  }
]

Output: Dispute Details

{
    "title": "A reality.eth question",
    "description": "A reality.eth question has been raised to arbitration.",
    "frontendUrl": "https://reality.eth.limo/app/#!/question/0x14a6748192aBC6E10CA694Ae07bDd4327D6c7A51-0xe2a3bd38e3ad4e22336ac35b221bbbdd808d716209f84014c7bc3bf62f8e3b39",
}

API

type SubgraphMapping = {
  endpoint: string; // Subgraph endpoint
  query: string; // Subgraph query
  seek: string[]; // Subgraph query parameters value used to populate the template variables
  populate: string[]; // Populated template variables
};

type AbiEventMapping = {
  abi: string; // ABI of the contract emitting the event
  address: string; // Address of the contract emitting the event
  eventFilter: { // Event filter (eg. specific parameter value, block number range, event index)
    fromBlock: BigInt | string; // Block number range start
    toBlock: BigInt | string; // Block number range end
    args: any; // Event parameter value to filter on
  };
  seek: string[]; // Event parameters value used to populate the template variables
  populate: string[]; // Populated template variables
};

type AbiCallMapping = {
  abi: string; // ABI of the contract emitting the event
  address: string; // Address of the contract emitting the event
  args: any[]; // Function arguments
  seek: string[]; // Call return parameters used to populate the template variables
  populate: string[]; // Populated template variables
};

type JsonMapping = {
  value: object; // Hardcoded object, to be stringified.
  seek: string[]; // JSON keys used to populate the template variables
  populate: string[]; // Populated template variables
};

type FetchIpfsJsonMapping = {
  ipfsUri: string; // IPFS URL
  seek: string[]; // JSON keys used to populate the template variables
  populate: string[]; // Populated template variables
};

Full JSON Example

[
    {
        "type": "subgraph",
        "endpoint": "https://api.thegraph.com/subgraphs/name/uniswap/uniswap-v2",
        "query": "query($id: ID!) { pair(id: $id) { id token0Price token1Price } }",
        "seek": [
            "token0Price",
            "token1Price"
        ],
        "populate": [
            "price1",
            "price2"
        ]
    },
    {
        "type": "abi/event",
        "abi": "event StakeSet(address indexed _address, uint256 _courtID, uint256 _amount)",
        "address": "0x9f8f72aa9304c8b593d555f12ef6589cc3a579a2",
        "eventFilter": {
            "fromBlock": "36205881",
            "toBlock": "latest",
            "args": {
                "_courtID": 1
            }
        },
        "seek": [
            "amount"
        ],
        "populate": [
            "amount"
        ]
    },
    {
        "type": "abi/call",
        "abi": "function appealCost(uint256 _disputeID) public view returns (uint256)",
        "address": "0x5a2bC1477ABE705dB4955Cda7DE064eA79D563d1",
        "args": [
            "1"
        ],
        "seek": [
            "cost"
        ],
        "populate": [
            "cost"
        ]
    },
    {
        "type": "json",
        "value": {
            "name": "John Doe",
            "age": 30,
            "email": "johndoe@example.com"
        },
        "seek": [
            "name",
            "age",
            "email"
        ],
        "populate": [
            "name",
            "age",
            "email"
        ]
    },
    {
        "type": "fetch/ipfs/json",
        "ipfsUri": "ipfs://QmZ3Cmnip8bmFNruuTuCdxPymEjyK9VcQEyf2beDYcaHaK/metaEvidence.json",
        "seek": [
            "title"
        ],
        "populate": [
            "title"
        ]
    }
]

Acceptance Criteria

This specification and implementation must accommodate complex use cases such as mappings for a Reality dispute.

⚠️ Disambiguation: the "Reality template" and "Reality question" are part of the Reality datamodel designed by Reality and outside the control of Kleros. In contrast, the "dispute template" and "dispute question" are part of the Kleros datamodel and are the subject of this specification.

For a Reality dispute:

Here is an example of Reality question created on Arbitrum Goerli which can be used for testing:

jaybuidl commented 11 months ago

EDIT: added type fetch/ipfs/json, which is safer than a generic fetch

jaybuidl commented 10 months ago

Reopening: work will continue in a different PR.

https://github.com/kleros/kleros-v2/pull/1165#issuecomment-1906778483