The escrow program
trench_escrow is an Anchor program on devnet. Every checkout creates and funds an escrow account in one buyer-signed transaction; the API verifies the account before it marks the order paid. The program is built and tested in CI.
- Cluster
- devnet
- Program id
- Dbrq2sACPk98FGzLihajJd4r2Q4jdKNn62GSURndv2kw
- PDA seeds
- escrow + buyer + order id
- Escrow window
- 1 hour
Accounts
The escrow account is a PDA seeded with the byte string escrow and the 16-byte order id. It stores the buyer, seller, resolver, and the buyback, verification, ops, and safety pubkeys, plus status, disputed_from, price, deposit, fee and rebate basis points, the four split basis points, expires_at, escrow_until, and the bump.
Instructions
- initialize
Buyer creates the escrow PDA and stores the seller, resolver, buckets, price, and fee.
- fund
Buyer transfers the quoted total into the escrow account. Status becomes paid.
- release
After escrow_until, price goes to the seller and the net fee is split to the four buckets.
- expire
After expires_at, an unpaid order becomes expired. No funds have been deposited.
- open_dispute
Buyer (or the resolver, from paid inside the window) moves the order to disputed and stores the previous status.
- refund
Resolver returns the deposit to the buyer, and only when the dispute started from paid.
- reject_dispute
Resolver restores the order to paid or released.
- refund_after_timeout
If a dispute is still open 7 days after escrow_until, anyone can return the deposit to the buyer.
- close
Closes a refunded, expired, or long-released escrow and returns its rent to the buyer.
- init_config
Upgrade authority creates the config that names the dispute resolver.
- set_config
Config admin rotates the resolver or the dispute timeout for every escrow.
States
Refunded and expired are terminal. Release and expire on the program are permissionless once the clock allows them. The buyer signs initialize, fund, and open_dispute.
- pending → paid
- pending → expired
- paid → released
- paid → disputed
- released → disputed
- disputed → paid
- disputed → released
- disputed → refunded
Check it yourself
- Program on Solana Explorer: Dbrq2sACPk98FGzLihajJd4r2Q4jdKNn62GSURndv2kw (Solana devnet). The IDL is published on chain (Program Metadata, seed idl): npx @solana-program/program-metadata fetch idl Dbrq2sACPk98FGzLihajJd4r2Q4jdKNn62GSURndv2kw --rpc <devnet RPC>
- The binary embeds a security.txt (name, project URL, source, policy). Explorer shows it on the program page.
- Live program hash, upgrade authority, multisig, buckets and the latest escrows are on /verify. Your own order's escrow account and release time are on your purchases page, read from chain.
- A verified (reproducible) build is not published yet, so compare the deployed hash with your own anchor build of programs/trench_escrow.
Resolver
The resolver lives in a program config account, so it can be rotated for every open escrow. Refund and reject_dispute require the configured resolver as a signer, and the resolver freezes the escrow on chain as soon as a dispute is filed. If it never acts, the buyer is refunded automatically after the dispute timeout. Refund pays the deposit back only when disputed_from is paid, because a release has already moved the lamports out of the account. The API holds the resolver key: its cron sends release after escrow_until, and resolving a dispute sends refund or reject_dispute. Release only moves funds out of paid, so a disputed escrow cannot be released. A refund after release is funded from the creator bond and then the safety bucket. Release pays every bucket directly, so each bucket wallet must already hold the rent-exempt minimum.