Skip to main content
This guide explains how your protocol can integrate Justly directly from smart contracts using the arbitrable-arbitrator model. Your contract keeps custody of the principal assets. Justly resolves the dispute and returns a ruling. Your contract enforces the final state change.

Integration model

Use a push model:
  • your arbitrable contract owns escrowed funds, locked positions, or claimable balances,
  • your contract opens a dispute in Justly when an edge case appears,
  • Justly runs the dispute lifecycle and finalizes a ruling,
  • and your contract consumes that ruling through callback handling or direct reads.
This keeps your core protocol logic in your contract while outsourcing dispute judgment to Justly.

Minimal interfaces

Define and depend on interfaces, not concrete implementations, so your integration remains stable if internal protocol contracts evolve.
interface IArbitrable {
    function rule(uint256 disputeId, uint256 ruling) external;
}

interface IJustly {
    struct CreateDisputeParams {
        address claimer;
        address defender;
        string category;
        string ipfsHash;
        uint256 jurorsRequired;
        uint256 paySeconds;
        uint256 evidenceSeconds;
        uint256 commitSeconds;
        uint256 revealSeconds;
    }

    function createDispute(CreateDisputeParams calldata params) external returns (uint256);
    function payDispute(uint256 disputeId) external;
    function submitEvidence(uint256 disputeId, string calldata ipfsHash) external;
    function getDisputeCost(uint256 disputeId) external view returns (uint256);
}
Treat this as the minimum surface your protocol needs for dispute integration.

End-to-end flow

  1. Open dispute from your contract
    Create a protocol case, lock relevant assets, then call createDispute(...).
  2. Fund dispute
    Both sides of the dispute must be covered before activation. The parties can fund their own side, and a platform or sponsor can cover one or both sides when your product model requires it.
  3. Submit evidence
    Parties submit evidence references through submitEvidence(disputeId, ipfsHash) during the evidence window.
  4. Wait for ruling
    Justly handles evidence freeze, voting, reveal, and settlement internally.
  5. Consume the ruling
    Your integration can receive a callback through rule(disputeId, ruling) or read the final ruling directly.

Ruling semantics

At the integration layer, treat the ruling as binary:
  • 0: defender wins
  • 1: claimer wins
If no effective vote exists at finalization, the defender is the default outcome. Your contract should map this result to protocol actions, such as:
  • release escrow to one side,
  • split according to predefined terms,
  • or cancel and refund.
Keep this mapping explicit in your state machine.

Callback and direct reads

Callback is optional from the perspective of finality. That means:
  • a successful callback can notify your contract immediately,
  • a direct read can be used as a fallback or primary integration mode,
  • and callback failure does not invalidate the ruling.
Your integration should account for this separation between dispute finality and external settlement handling.

Evidence strategy

Store only compact references on-chain. Recommended approach:
  • put the root case file in createDispute(..., ipfsHash, ...),
  • append additional evidence during the evidence window with submitEvidence(...),
  • keep your own case metadata keyed by disputeId in your contract or indexer.
This gives you low gas overhead and an auditable evidence timeline.

Security and implementation checklist

  • Restrict rule(...) so only the Justly arbitrator address can call it.
  • Make ruling execution idempotent. A dispute should not settle twice.
  • Track protocolCaseId -> disputeId and disputeId -> protocolCaseId mappings.
  • Lock disputed assets before opening a dispute.
  • Validate party roles before forwarding calls to payDispute(...) and submitEvidence(...).
  • Emit protocol-level events for dispute opened, funded, evidence submitted, and ruling applied.

Practical integration pattern

A production integration usually keeps three layers:
  • Protocol contract: escrow and final enforcement.
  • Arbitration adapter: thin wrapper that talks to Justly interfaces.
  • Indexer/back end: evidence UX, timeline, notifications, and analytics.
This separation keeps your on-chain core small while preserving a full product experience.

What to version-pin

To protect your integration from contract changes:
  • pin the deployed arbitrator address per chain,
  • pin the ABI version your adapter uses,
  • keep interfaces in your repo and upgrade through explicit release steps.
This lets you evolve safely while preserving deterministic enforcement for users.