SPEC 03 · DOC-2026-07-11

Proof-of-Reserve

Proof-of-Reserve is the mechanism that keeps the peg honest. An attestor reads live vault balances and oracle prices, values the reserve in the peg currency, signs a domain-separated statement of the result, and the program stores the ratio only after verifying an M-of-N quorum of those signatures. No single party — not the issuer, not any one attestor — can move the recorded ratio alone.

Pipeline

Collect. Value. Sign. Commit.

The attestor runs a four-stage pipeline. Every stage is idempotent, so re-running against the same inputs produces the same on-chain commit — that determinism is what makes an attestation replayable during an audit.

StageNameAction
1collectorRead vault balances and Hermes prices
2aggregatorValue the vault, compute ratio_bps
3signer setEach attestor signs the same body
4commitM ed25519 verifies plus the program call

Price intake

Prices come from Pyth over the Hermes HTTP endpoint. The attestor pulls the latest price update for each collateral feed, checks its confidence interval, and rejects any quote that is stale or too wide before it values a single unit of collateral. Hermes is queried by the attestor process — the on-chain program never makes an HTTP call.

  • ·The feed publish time must be within max_staleness_s of wall-clock — a lagging feed halts the attestation rather than valuing collateral at a stale price.
  • ·The ratio conf / price must stay under max_confidence_bps; a wide interval means the market is uncertain and the reserve value is not yet trustworthy.
  • ·Reserve value is fixed-point reserve_value_usd_e6 — micro-dollars — so no floating point ever reaches the signed body or the chain.

Attestation payload

Every attestor signs the identical byte body. It is domain-separated with a fixed prefix so a signature over a reserve statement can never be replayed as a signature over anything else. The body is hashed with SHA-256 and signed with ed25519.

// Domain-separated PoR body. All integers little-endian.
PEGD-POR-V1
  | stable_mint            (32 bytes)
  | timestamp              (u64 LE)
  | total_supply           (u64 LE)
  | reserve_value_usd_e6   (u64 LE)
  | ratio_bps              (u32 LE)

// Signing (TypeScript attestor):
const body = serializePorBody({
  stableMint,
  timestamp,
  totalSupply,
  reserveValueUsdE6,
  ratioBps,
});
const digest    = sha256(body);
const signature = ed25519.sign(digest, attestorSecret);

Aggregation and quorum

A single signature is never sufficient. The trusted attestor set is configured on-chain, and a commit requires signatures from at least M of the N members. Across the collected statements, the framework takes the median of ratio_bps and reserve_value_usd_e6 — a single outlier attestor cannot skew the recorded reserve.

// commit_attestation verifies the quorum against the trusted set, then
// stores the median. Signature checks use the Solana ed25519 precompile:
// the program introspects the Instructions sysvar for M preceding
// Ed25519SigVerify instructions rather than verifying in-program.
pub fn commit_attestation(ctx: Context<CommitAttestation>, payload: PorPayload) -> Result<()> {
    let now = Clock::get()?.unix_timestamp;
    require!(payload.timestamp <= now,             PegdError::FutureTimestamp);
    require!(now - payload.timestamp <= 3600,      PegdError::StaleAttestation);

    let verified = verify_sigverify_quorum(
        &ctx.accounts.instructions_sysvar,
        &ctx.accounts.attestation.trusted_set,
        ctx.accounts.attestation.threshold_m, // M-of-N
        &payload.body,
    )?;
    require!(verified >= ctx.accounts.attestation.threshold_m, PegdError::QuorumNotMet);

    let a = &mut ctx.accounts.attestation;
    a.ratio_bps            = median_ratio_bps;
    a.reserve_value_usd_e6 = median_reserve_e6;
    a.last_attested_ts     = payload.timestamp;
    Ok(())
}

Attestations older than 3600 seconds, or carrying a future timestamp, are rejected outright. The stored ratio therefore always reflects a fresh, quorum-signed snapshot — and the risk module reads that same field when it decides whether to trip the breaker.

Attestor sources

An attestor is defined by where it draws its reserve figure. Three source types are supported. Every source produces the same signed body format above, so they aggregate together into one median.

ON-CHAIN CRYPTO

pyth-hermes

Values on-chain collateral by pulling Pyth Hermes prices and reading vault balances directly. Fully self-verifiable and the only source exercised by the public demo.

EXTERNAL FEED

chainlink-por

Ingests a Chainlink Proof-of-Reserve style feed for reserves held outside the vault. Used by attested-fiat and RWA issuers, not by the crypto demo mode.

CUSTODY SIGNER

internal-oracle

A custody attestor role — a key custodian who signs a periodic solvency statement for off-chain reserves. Signature only; it never holds mint authority.

Independent verification

Because the body format and the trusted set are both public, anyone can reproduce a commit without trusting Pegd. Re-serialize the body from the on-chain fields, hash it, and confirm that at least M members of the trusted set signed the same digest in the transaction's ed25519 instructions. The demo's crypto mode makes this a fully on-chain check — the vault balance and the price feed are both public accounts.

Read next

Back to Docs