Payment Flow
From Deposit to Release
The depositor side and the agent side never share signing authority. Each step is an independent transaction initiated by the party responsible for it.
Depositor side
// 1. Approve USDC to TrustGate
usdc.approve(trustGate, amount)
// 2. Credit pooled balance
trustGate.deposit(amount)
// 3. Set per-agent cap
trustGate.setAgentAllowance(agent, maxSpend)Allowances are per-(depositor, agent) pairs. Setting an allowance to zero stops new claims but does not invalidate ones already pending. Existing balance can be withdrawn at any time through withdraw(amount), subject to funds not locked in pending claims.
Agent side
// Claim against a specific depositor
trustGate.claim(depositor, amount)The call reverts if the agent is not Active, if amount exceeds allowance, or if the depositor balance is insufficient. On success, the contract reads TrustScoring.getTier(agent) and branches:
- HIGH — USDC transferred; claim marked Released in the same tx.
- MEDIUM — Claim recorded with
releaseTime = block.timestamp + 24 hours. Status: Pending. - LOW — Claim recorded, awaiting
approveEscrow. Status: Pending.
Release
// Agent: after 24h (MEDIUM) or after approval (LOW)
trustGate.release(claimId)
// Depositor: only needed for LOW tier escrow
trustGate.approveEscrow(claimId)
// Depositor: abort any Pending claim
trustGate.cancel(claimId)State transitions
A Claim struct moves through three terminal states. Only one can win:
- Released — USDC transferred to the agent.
- Cancelled — USDC returned to the depositor's pooled balance.
- Expired — reserved for future use (not currently triggered).
Every transition emits an event. Frontends and indexers can follow the full lifecycle through ClaimCreated, ClaimReleased, ClaimCancelled, and EscrowApproved.