Settlement
Settlement is how Covenant accounts for resource consumption. Today the daemon writes local receipts. The future on-chain path batches those receipts into the Solana settlement program once the authority, mint, oracle, and reconciliation flows are ready.
Receipt
SettlementReceipt {
id: uuid,
payer: AgentId, // who consumed resources
resource: "memory" | "compute" | "tool" | "message" | "registration",
credits_consumed: u64,
settled_at: u64, // unix milliseconds
memory_record_id: uuid | null, // set when resource == "memory"
chain: string | null, // populated when anchored on-chain
cluster: string | null, // Solana cluster identifier when anchored on-chain
batch_id: string | null, // identifier of the receipt batch
merkle_root: string | null, // batch merkle root committed on-chain
tx_sig: string | null, // signature of anchor_receipt_batch tx
slot: u64 | null, // chain slot where the batch confirmed
confirmed_at: u64 | null, // unix milliseconds at confirmation
onchain_sig: string | null // populated when flushed on-chain
}Receipts accumulate in $COVENANT_HOME/receipts/working.jsonl. The daemon writes one receipt per resource event. For example, every memory write produces a receipt with resource = "memory", memory_record_id, and credits_consumed proportional to bytes written.
Credit pricing
Each resource kind has a pricing function that maps the underlying unit (bytes, milliseconds, calls) to credits. The pricing functions are deliberately simple and live in one place, so operators can audit them at a glance and downstream integrations can replicate the math without a dependency.
The default for memory writes is one credit per kilobyte (round up). Compute, tool calls, and egress have their own pricing functions that compose the same way.
Future on-chain flush
The planned on-chain side is an Anchor program for Solana. Three of its instruction shapes describe the credit flow:
initialize: one-shot setup of aConfigPDA under seedb"settlement-config"; records the authority, mints, and rates.buy_credits(amount_covnt): transfer$COVNTinto the treasury in exchange for credits at the configured rate.consume_credits(amount, receipt_hash): destroy credits at the point of consumption (memory write, tool call, etc.).receipt_hashbinds the on-chain consumption to a specific local receipt batch for reconciliation.
The intended production flow is for the daemon to batch local receipts and submit consumption to the program. Once an on-chain transaction confirms, the receipt's onchain_sig can be populated with the signature. This is a planned reconciliation path, not deployed behavior.
Planned economic model
The target model is credits minted against an external payment input, credits consumed at resource-use time, and treasury policy that can route a portion of inflows toward buyback or provider payout. Those mechanics require oracle integration, mint authority decisions, and deployment review before they should be treated as operational.
Storage layout
| Path | Format | Purpose |
|---|---|---|
receipts/working.jsonl | JSONL, append-only | Local receipts. Future flushed receipts can populate onchain_sig. |
Reading recent receipts
covenant chain status --json
covenant receipts recent --limit 20 --json
covenant chain flush-receipts --limit 20 --json
covenant chain receipt-batches --limit 20 --json
# Or via HTTP:
curl -s '127.0.0.1:8421/receipts/recent?limit=20&since_ms=1714938000000' | jqVerification
covenant verify --json cross-checks memory writes against settlement receipts by memory_record_id when the receipt carries one, with owner/resource count fallback for older rows. Missing, duplicate, orphaned, or wrong-payer correlations surface as drift. The daemon is fail-soft on receipt write (a failed receipt does not cancel the memory write), so drift in this dimension is the principal operator-visible indicator of a settlement-side fault.
Backfill
When covenant verify reports legacy receipts without a memory_record_id correlation, the operator can repair them with the covenant settlement backfill-receipts --json CLI verb (HTTP equivalent: POST /settlement/receipts/backfill). Verify remains read-only; the backfill mutator runs only when explicitly invoked. The verb applies by default; pass --dry-run to report the row_count an apply would change without writing. Dry-run requires the settlement.backfill.dry_run capability; apply requires settlement.backfill.apply. See capabilities for the scope contract. An apply path writes a rollback checkpoint sibling file before mutation, fsyncs both the rewrite and the rename, then emits an operator-issued SettlementReceiptBackfillApplied audit row carrying row_count, rollback_path, and dry_run.
$ covenant settlement backfill-receipts --dry-run --json
{"schema":"covenant.settlement.backfill.v1","row_count":12,"rollback_path":null,"dry_run":true}x402 payment rail
Distinct from the internal receipt flush above, the agent-to-service payment rail over HTTP 402 (x402) is live. The daemon can pay for metered x402 resources outbound, and Covenant operates deployed x402 seller, facilitator, and escrow services that settle in USDC on Solana — selling Covenant-Verified attestations, on-chain identity passports, and reputation reads, with the seller’s signing key published at /.well-known/x402. This is a separate concern from anchoring internal resource receipts: the payment rail being live does not make the receipt flush production.
Release
Local receipts and recent-receipt reads are implemented. On-chain settlement is planned and scaffolded; it is not production and should not be described as deployed.
Related
- Architecture: the settlement scaffold in the broader system map.
- Identity and keys: the same local identity signs capability grants today and is the planned signer boundary for future settlement transactions.
- Audit log: settlement receipts pair 1:1 with memory writes; drift shows up here.