# Escrow

#### Escrow Smart Contract

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

{% embed url="<https://youtu.be/B0D79P8pxRU>" %}

**Purpose:** Facilitates secure transactions by holding funds in a contract-controlled treasury until specific conditions are met.

#### **Technical Specifications**

* **State Machine:**
  * `active`: Funds are locked and ready for release.
  * `released`: Funds have been sent to the beneficiary.
  * `refunded`: Funds returned to the depositor (lifecycle state defined, logic implementation pending in snippet).
* **Data Structure:**

  ```
  struct Escrow {
      contributor: ZswapCoinPublicKey, // The party involved
      state: ESCROW_STATE,             // Current status
      amount: Uint<128>,               // Value locked
  }

  ```

#### **Functions**

* **`create(contributor, coin)`**
  * **Action:** Ingests a user's coin (`receive`), locks it in the contract's `treasury` (`writeCoin`), and generates a unique Escrow ID.
  * **Privacy Note:** The `amount` is disclosed publicly (`disclose(coin.value)`), but the transaction graph remains shielded via Z-swap.

```jsx
export circuit create(
    contributor: ZswapCoinPublicKey,
    coin: CoinInfo
): Uint<32> {
    // Receive the coin into the contract
    receive(disclose(coin));

    // Store the coin in the treasury using writeCoin
    const contractAddress = right<ZswapCoinPublicKey, ContractAddress>(kernel.self());
    treasury.writeCoin(disclose(coin), contractAddress);

    // Increment escrow ID
    last_escrow_id = (last_escrow_id + 1) as Uint<32>;

    // Store escrow metadata
    const newEscrow = Escrow {
        contributor: disclose(contributor),
        state: ESCROW_STATE.active,
        amount: disclose(coin.value),
    };
    escrows.insert(disclose(last_escrow_id), newEscrow);

    return last_escrow_id;
}
```

* **`release(id)`**
  * **Action:** Checks if the escrow is `active`. If yes, transfers funds to the `contributor` address.
  * **Change Management:** Automatically calculates UTXO change. If the treasury coin is larger than the escrow amount, the remainder is written back to the treasury.

```jsx
export circuit release(id: Uint<32>): [] {
    // Lookup escrow
    const e = escrows.lookup(disclose(id));
    assert(e.state == ESCROW_STATE.active, "Escrow not active");

    // Send funds to contributor
    const recipient = left<ZswapCoinPublicKey, ContractAddress>(e.contributor);
    const sendResult = send(treasury, recipient, e.amount);
    assert(sendResult.sent.value == e.amount, "Failed to send release payment");
// Handle change using writeCoin
    if (sendResult.change.is_some) {
        const contractAddress = right<ZswapCoinPublicKey, ContractAddress>(kernel.self());
        treasury.writeCoin(sendResult.change.value, contractAddress);  // Changed to writeCoin
    } else {
        treasury.resetToDefault();
    }

    // Update escrow state
    const updated = Escrow {
        contributor: e.contributor,
        state: ESCROW_STATE.released,
        amount: e.amount,
    };
    escrows.insert(disclose(id), updated);

    return [];
}
```

## Developer Tutorials

#### Tutorial 1: Deploying the Escrow Contract

**Prerequisite:** A Midnight wallet (e.g., Lace) with `tDUST` for fees.

**Step-by-Step Guide:**

1. **Setup Environment:** Ensure you are running the `Compact` compiler version 0.16–0.18.
2. **Deploy Contract:** Run the deployment script. The contract constructor will initialize `last_escrow_id` to 0.
3. **Witness Functions:**
   * *Warning:* The current implementation requires careful handling of the `release` witness function. You must ensure `queryContext.insertCommitment(commitment, index)` is called to allow the runtime to locate the coin in the Merkle tree.

#### Tutorial 2: Creating an Escrow (Deposit)

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

1. **Prepare Coin Info:** Select a coin from your wallet. You must pass the `CoinInfo` struct, including the nonce and value.
2. **Call Circuit:**

   ```
   // Pseudo-code example
   contract.create(
      beneficiaryPublicKey,
      myCoinData
   );

   ```
3. **Verify:** The contract will return a `Uint<32>` ID. Store this ID; you will need it to release funds.

#### Tutorial 3: Releasing Funds

**Code Reference:** `export circuit release(...)`

1. **Input:** Provide the `Escrow ID`.
2. **Execution:** The contract verifies the state is `active`.
3. **Output:** The recipient receives the funds. Any "change" from the input coin is securely returned to the contract treasury.
