Skip to main content
Dispute templates define the question, answer options, and metadata presented to jurors. They are registered on-chain via the DisputeTemplateRegistry contract and can contain dynamic placeholders populated at dispute-creation time via the data mappings system.

Template Structure

A complete dispute template is a JSON object. Fields marked {{variable}} are placeholders resolved by the data mappings at dispute time. Fields marked {{{variable}}} (triple-brace) are treated as raw/unescaped values (e.g. URIs).

Fields Reference

Answer IDs

Answer IDs are hex-encoded ruling values: The 0x00 ruling is handled specially by KlerosCore - if a majority selects it, no party is considered to have won.

Pre-dispute Evidence (extraEvidences)

The extraEvidences field lets arbitrable contracts surface evidence that was submitted before the dispute was created - such as a requester’s registration submission or a challenger’s objection - directly in the Kleros Court UI. Without this field, jurors would need to navigate to the arbitrable app separately to find that evidence.

Schema

Usage in Templates

extraEvidences is an array populated by the data mappings system. In practice, Curate V2 uses Handlebars conditionals to include requester and challenger evidence only when they exist, joined by a comma when both are present:
The requesterEvidence and challengerEvidence variables are populated by a fetch/ipfs/json mapping that fetches each party’s evidence file from IPFS:
extraEvidences is the mechanism that connects pre-dispute activity (registration submissions, challenger objections) to the Kleros dispute UI. Without it, jurors must leave Court to find context. Always populate it when your arbitrable generates structured evidence at submission time.

Data Mappings

The templateDataMappings parameter is a JSON array that defines how template {{variable}} placeholders are populated from external data sources at dispute creation time. The system resolves mappings sequentially - later mappings can reference values populated by earlier ones. Each mapping object has a type field that determines its structure, plus seek (list of data paths to extract) and populate (list of template variable names to fill, in the same order as seek).

Mapping Types

1. graphql - Subgraph Query

Fetches data from a TheGraph subgraph endpoint.
  • endpoint: The Graph gateway URL. {{{graphApiKey}}} is injected at runtime by the SDK.
  • query: A standard GraphQL query string.
  • variables: Query variables; can reference already-populated {{template_vars}}.
  • seek: Dot-notation paths into the GraphQL response data.
  • populate: Template variable names to set, positionally matching seek.

2. fetch/ipfs/json - IPFS JSON Fetch

Retrieves a JSON file from IPFS and extracts fields.
  • ipfsUri: An IPFS URI, typically populated by a prior mapping step. Triple-brace {{{...}}} means the value is used as a raw URI without HTML-escaping.
  • seek: JSON field paths within the fetched document.
  • populate: Template variable names to fill.

3. abi/call - Smart Contract Call

Calls a view function on a contract and extracts return values.
  • abi: Human-readable ABI string for the function.
  • functionName: The function to call.
  • address: Contract address.
  • args: Arguments to pass to the function. Can reference {{template_vars}}.
  • seek: Indices (as strings) into the returned tuple, or named return values.
  • populate: Template variable names to fill.

4. abi/event - On-Chain Event Data

Extracts data from a previously emitted on-chain event.
  • abi: Human-readable ABI string for the event.
  • eventName: The event to look up.
  • address: Contract address that emitted the event.
  • seek: Event parameter names to extract.
  • populate: Template variable names to fill.

5. json - Hardcoded Values

Injects hardcoded values directly into template variables.
Useful for injecting static configuration values that differ per deployment.

Chaining Mappings

Mappings execute in array order. A variable populated in step 1 can be used in step 2. For example:
Here transactionUri is populated in step 1 and used as {{{transactionUri}}} in step 2.

Real-World Examples

Escrow V2

With mappings:

Curate V2 - Registration

Registration and removal disputes use separate templates with inverted answer logic. For registration, accepting means the item should be added; for removal, accepting means the item should be removed.
Removal template uses inverted semantics - 0x01 means “yes, remove”:

Reality V2

Note: Reality V2 includes a "type" field ("single-select", "multiple-select", "uint", "datetime", "bool") matching the Reality.eth question type. The “Answered Too Soon” option (0x00) is always present in Reality disputes.

Registration

Templates are registered on DisputeTemplateRegistry:
When raising a dispute, emit DisputeRequest with your stored templateId:
If the template is large, store it on IPFS and pass its URI as _templateUri instead of registering inline.

Updating Templates

Use changeDisputeTemplate() (available on arbitrable contracts like Escrow) to update the template after deployment - new disputes will use the updated template while old ones retain the original templateId snapshot.
The templateId is emitted in the DisputeTemplate event on DisputeTemplateRegistry and must be stored by your contract for use in DisputeRequest.