# Dispute Resolution Smart Contract

## Tutorial: Decentralized Dispute Resolution

Code: <https://github.com/socious-io/midnight-escrow/>

{% embed url="<https://youtu.be/b0Q-eg3cncs>" %}

### 1. Overview

The Dispute Resolution mechanism is a core feature of the Midnight Escrow contract. It replaces the need for a centralized arbitrator with a decentralized panel of three voters. If the **Sender** and **Contributor** cannot agree on the completion of work, the **Voters** step in to cast binding votes on whether to release funds or refund them.

### 2. Roles & Permissions

To use this feature, you must understand the specific roles involved:

* **Voters (3):** Independent parties whose public keys are registered when the escrow is created. They are the only ones permitted to call the `vote` circuit.
* **Admin:** The entity authorized to trigger the final settlement (`dispute` circuit) once a consensus is reached.
* **Sender/Contributor:** The disputing parties. They cannot cast votes.

### 3. The Resolution Workflow

#### Step 1: Initial Setup (During Creation)

When creating an escrow, you must initialize the voter slots. While the current contract version in the repository initializes them with a placeholder (the contributor's key) or flags them as empty (`voter*_set: 0`), a robust deployment should assign these to independent third parties.

**Code Reference (`create` circuit):**

```
// In a production scenario, these would be distinct keys
voter1: disclose(voterKey1),
voter2: disclose(voterKey2),
voter3: disclose(voterKey3),
```

#### Step 2: Casting Votes

When a dispute arises, each of the three voters must examine the evidence (off-chain) and cast their vote on-chain using the `vote` circuit.

**Function Signature:**

```
export circuit vote(
    id: Uint<32>,
    voter: ZswapCoinPublicKey,
    vote_choice: ESCROW_VOTE
): []
```

**Parameters:**

* **`id`**: The unique ID of the escrow in dispute.
* **`voter`**: The public key of the voter (must match one of the registered `voter1`, `voter2`, or `voter3`).
* **`vote_choice`**: An Enum value indicating the decision.
  * `1`: **Release** (Pay the Contributor)
  * `2`: **Refund** (Return funds to Sender)

**Example Usage (TypeScript/JS SDK):**

```
// Example: Voter 1 votes to RELEASE funds
await contract.vote(
  escrowId,
  voter1PublicKey,
  1 // Enum value for ESCROW_VOTE.release
);
```

#### Step 3: Reaching Consensus

The contract automatically tracks the tally in the state variables `release_votes` and `refund_votes`.

* **Threshold:** A simple majority of **2 out of 3** votes is required.
* **Automatic Trigger:** The current smart contract logic checks the vote count immediately after a vote is cast. If the threshold (2 votes) is met, the contract **automatically** executes the transfer.
  * *Note:* In older versions, a separate `dispute` call was required. In the `Secure Decentralized Escrow Contract with Voting` version, the `vote` circuit explicitly calls `release` or `refund` internally if the count `>= 2`.

#### Step 4: Final Settlement (The `dispute` Circuit)

*Note: This step is technically redundant in the latest "Voting" contract version because the `vote` function handles execution, but the `dispute` function remains available as a manual trigger if needed by the Admin.*

**Function Signature:**

```
export circuit dispute(
    id: Uint<32>,
    admin: ZswapCoinPublicKey
): []
```

**Usage:** If for some reason the automatic trigger fails or creates a state where funds didn't move (but votes are recorded), the Admin can call this function to force the settlement based on the existing vote count.

**Logic:**

```
if (e.release_votes >= 2) {
    release(disclose(id), e.admin);
} else if (e.refund_votes >= 2) {
    refund(disclose(id), e.admin);
}
```

### 4. Troubleshooting

#### "Voter already voted" Error

* **Cause:** The specific voter address attempting to transact has already cast a vote for this Escrow ID.
* **Fix:** Votes are immutable. Once cast, a voter cannot change their decision.

#### "No majority to resolve dispute" Error

* **Cause:** The Admin called the `dispute` function, but the vote tally is currently split (e.g., 1 Release, 0 Refund) or insufficient.
* **Fix:** Wait for the remaining voters to cast their votes using the `vote` circuit.

#### "Voter must differ from sender and contributor" Error

* **Cause:** The wallet attempting to vote matches the Sender or Contributor's public key.
* **Fix:** Ensure you are using the specific wallet associated with the designated Voter ID.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://socious.gitbook.io/midnight-smart-contract-library/dispute-resolution/dispute-resolution-smart-contract.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
