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.
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.
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.
| Stage | Name | Action |
|---|---|---|
| 1 | collector | Read vault balances and Hermes prices |
| 2 | aggregator | Value the vault, compute ratio_bps |
| 3 | signer set | Each attestor signs the same body |
| 4 | commit | M ed25519 verifies plus the program call |
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.
max_staleness_s of wall-clock — a lagging feed halts the attestation rather than valuing collateral at a stale price.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_usd_e6 — micro-dollars — so no floating point ever reaches the signed body or the chain.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);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.
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.
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.
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.
A custody attestor role — a key custodian who signs a periodic solvency statement for off-chain reserves. Signature only; it never holds mint authority.
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.