> ## Documentation Index
> Fetch the complete documentation index at: https://kleros-mintlify-6ebc7975.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Escrow Contract

> Example SimpleEscrow contract using Kleros V1 arbitration, ERC-792, and ERC-1497 to hold funds until release or juror-resolved dispute payout.

## Overview

This example demonstrates how to build an escrow contract that uses Kleros Court V1 as an external arbitrator, following the ERC-792 arbitration standard and ERC-1497 evidence standard. The contract holds funds in escrow until the payer releases them, or a dispute is raised and resolved by Kleros jurors.

It is based on the SimpleEscrow tutorial on [docs.kleros.io](https://docs.kleros.io/) and illustrates the core V1 integration pattern.

***

## Contract

```solidity theme={null}
// SPDX-License-Identifier: MIT
pragma solidity ^0.7.6;

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

contract SimpleEscrow is IArbitrable, IEvidence {
    address payable public payer = msg.sender;
    address payable public payee;
    uint256 public value;
    IArbitrator public arbitrator;
    string public agreement;
    uint256 public createdAt;
    uint256 public constant reclamationPeriod = 3 days;
    uint256 public constant arbitrationFeeDepositPeriod = 3 days;

    uint256 public reclaimedAt;

    enum Status { Initial, Reclaimed, Disputed, Resolved }
    Status public status;

    uint256 public disputeID;
    uint256 constant numberOfRulingOptions = 2;
    enum RulingOptions { RefusedToArbitrate, PayerWins, PayeeWins }

    constructor(
        address payable _payee,
        IArbitrator _arbitrator,
        string memory _agreement
    ) payable {
        value = msg.value;
        payee = _payee;
        arbitrator = _arbitrator;
        agreement = _agreement;
        createdAt = block.timestamp;

        // ERC-1497: announce the agreement (MetaEvidence) at deployment.
        emit MetaEvidence(0, _agreement);
    }

    /// @dev Payer releases the funds to the payee.
    function releaseFunds() public {
        require(status == Status.Initial, "Transaction is not in Initial state.");
        if (msg.sender != payer)
            require(block.timestamp - createdAt > reclamationPeriod, "Payer still has time to reclaim.");
        status = Status.Resolved;
        payee.transfer(value);
    }

    /// @dev Payer reclaims the funds, opening a window for the payee to dispute.
    function reclaimFunds() public payable {
        require(status == Status.Initial || status == Status.Reclaimed, "Cannot reclaim in this state.");
        require(msg.sender == payer, "Only the payer can reclaim.");

        if (status == Status.Reclaimed) {
            require(block.timestamp - reclaimedAt > arbitrationFeeDepositPeriod, "Payee still has time to deposit.");
            payer.transfer(address(this).balance);
            status = Status.Resolved;
        } else {
            require(msg.value == arbitrator.arbitrationCost(""), "Must deposit the arbitration cost.");
            reclaimedAt = block.timestamp;
            status = Status.Reclaimed;
        }
    }

    /// @dev Payee deposits the arbitration fee, creating a dispute in Kleros Court.
    function depositArbitrationFeeForPayee() public payable {
        require(status == Status.Reclaimed, "Transaction is not in Reclaimed state.");
        disputeID = arbitrator.createDispute{value: msg.value}(numberOfRulingOptions, "");
        status = Status.Disputed;
        // ERC-1497: link the dispute to metaEvidence 0 and evidence group 0.
        emit Dispute(arbitrator, disputeID, 0, 0);
    }

    /// @dev Called by the arbitrator to enforce the ruling.
    function rule(uint256 _disputeID, uint256 _ruling) public override {
        require(msg.sender == address(arbitrator), "Only the arbitrator can rule.");
        require(status == Status.Disputed, "There must be a dispute to execute a ruling.");
        require(_ruling <= numberOfRulingOptions, "Ruling out of bounds.");

        status = Status.Resolved;
        if (_ruling == uint256(RulingOptions.PayerWins)) payer.transfer(address(this).balance);
        else payee.transfer(address(this).balance);

        emit Ruling(arbitrator, _disputeID, _ruling);
    }

    /// @dev Submit evidence for the dispute (ERC-1497).
    function submitEvidence(string memory _evidence) public {
        require(status != Status.Resolved, "The dispute is already resolved.");
        emit Evidence(arbitrator, 0, msg.sender, _evidence);
    }
}
```

***

## Key Integration Points

**`createDispute()`**: Sends the arbitration fee to the V1 arbitrator (KlerosLiquid) and receives a `disputeID`. The `_extraData` argument (empty string here) can encode the subcourt ID and juror count.

**`rule()`**: The arbitrator calls this when the dispute is resolved. The ruling is enforced immediately by transferring the escrowed funds.

**ERC-1497 events**: `MetaEvidence` announces the agreement at deployment, `Dispute` links the dispute to that metaEvidence and an evidence group, and `Evidence` records each submission. These are the V1 evidence standard events consumed by the Court V1 and Dispute Resolver interfaces.

***

## Agreement (MetaEvidence)

In V1, the agreement is described with an ERC-1497 MetaEvidence JSON document, uploaded to IPFS and passed to the constructor:

```json theme={null}
{
  "title": "Escrow Payment Dispute",
  "description": "Should the escrowed funds be released to the payee or returned to the payer?",
  "question": "Which party should receive the escrowed funds?",
  "rulingOptions": {
    "titles": ["Refuse to Arbitrate", "Payer Wins", "Payee Wins"],
    "descriptions": [
      "The arbitrator refuses to rule.",
      "Return the funds to the payer.",
      "Release the funds to the payee."
    ]
  },
  "category": "Escrow",
  "fileURI": "/ipfs/QmEscrowAgreement..."
}
```

***

## Next Steps

* Add appeal support so a losing party can fund additional rounds
* Add ERC20 token support alongside native ETH (see the token compatibility notes for [Escrow V1](/products/escrow))
* Review the [ERC-792](/developers/arbitrable-apps/erc-792) and [ERC-1497](/developers/arbitrable-apps/erc-1497) standards in full
