For the complete documentation index, see llms.txt. This page is also available as Markdown.

Collateral Escrow Contract

A generic escrow that custodies borrower-posted collateral against a loan. It is one of Trilobyte's two collateral systems — the other (pool-manager skin-in-the-game collateral) lives in Globals.

Source: contracts/collateral-escrow/

Overview

The escrow custodies pledged collateral of any asset that implements the token interface — fungible tokens, RWA certificates via the Stellar Asset Contract, or NFTs. Its only job is lock / release / seize. Valuation, LTV, and what "seize" means by collateral type are policy that lives in configuration around the escrow, not in the contract.

Vault-triggered. Each pledge names its own controller — the Trilobyte vault the loan funds against — and only that controller may release or seize it. A single shared escrow can therefore back many loans and be authorised once by a permissioned-cert issuer.

The minimal escrow holds at most one active pledge per token. With one pledge per token, the escrow's balance of that token equals exactly that pledge's collateral, which removes cross-pledge balance ambiguity (e.g. after an issuer clawback). Resolved pledges are pruned — their final state lives in the emitted event.

Source Modules

File
Purpose

contract.rs

__constructor, lock, release, seize, queries, the available() clamp helper

storage.rs

Pledge struct, pledge counter, per-id pledge records, active-pledge-per-token index

errors.rs

#[contracterror] enum (3 variants)

events.rs

PledgeLocked, PledgeReleased, PledgeSeized

test.rs

11 tests

Data Model

Pledge

The record exists only while the pledge is active; it is deleted on release / seize.

Functions

Function
Signature
Auth
Description

lock

lock(borrower, token, amount, recovery_party, controller) -> u64

borrower

Borrower pledges amount of token, naming the controller vault and the recovery_party. Pulls the collateral into the escrow and returns the pledge id. Fails with TokenAlreadyPledged if an active pledge for that token already exists.

release

release(pledge_id)

pledge controller

Return the collateral to the borrower (loan repaid). Prunes the pledge first (effects-before-interaction), then transfers the available amount.

seize

seize(pledge_id)

pledge controller

Send the collateral to the recovery_party (loan defaulted). Prunes the pledge first, then transfers the available amount.

get_pledge

get_pledge(pledge_id) -> Option<Pledge>

The active pledge record, or None once resolved.

get_active_pledge

get_active_pledge(token) -> Option<u64>

The active pledge id for a token (lets a controller find a pledge without having stored the id).

available_collateral

available_collateral(pledge_id) -> i128

Currently transferable amount: the recorded amount clamped to the escrow's live balance. Returns 0 if the pledge does not exist.

__constructor

__constructor()

Deploy the shared escrow. No global authority — each pledge carries its own controller.

How the Vault Uses It

  1. Setup — the loan is created with collateral_escrow, collateral_token, collateral_recovery, and collateral_min set on VaultParams.

  2. Lock — the borrower calls lock(...) naming the vault as controller, and passes the returned pledge_id to approve_and_disburse(caller, Some(pledge_id)).

  3. Disbursement gate — the vault verifies the pledge backs this vault: controller == vault, token == collateral_token, borrower == loan borrower, recovery_party == collateral_recovery, and both pledge.amount and the live available_collateral are ≥ collateral_min. Any mismatch → CollateralPledgeInvalid.

  4. Repaid — on FullyRepaid the vault calls escrow.release(pledge_id) → collateral back to the borrower.

  5. Defaulted — on check_default the vault calls escrow.seize(pledge_id) → collateral to the recovery_party for off-chain disposition.

  6. Cancelled before disbursement — on funding/approval expiry the vault looks the pledge up by token (the id was never recorded), re-verifies controller + borrower, and releases it back to the borrower.

Events

Event
Key Fields
When

PledgeLocked

borrower, pledge_id, token, amount, controller

Collateral locked

PledgeReleased

pledge_id, amount

Released to the borrower

PledgeSeized

recovery_party, pledge_id, amount

Seized to the recovery party

Error Codes

Code
Name
Description

1

PledgeNotFound

No active pledge with that id (never created, or already resolved)

2

InvalidAmount

The pledged amount must be positive

3

TokenAlreadyPledged

This token already has an active pledge — resolve it first

Storage Design

The pledge counter, per-id pledge records, and the active-pledge-per-token index are all in persistent storage with a TTL clamped to the network maximum (max_ttl()). Reads (get_pledge) do not bump TTL — reads must not side-effect storage.

Last updated