Skip to main content

Continuous proof of reserves

What is continuous proof of reserves?

Continuous proof of reserves is checking a stablecoin’s supply on every chain against the reserves its custodians report, on a schedule you set, and publishing the backing ratio onchain; it’s also called real-time proof of reserves.

Issuers and issuance platforms run it so a shortfall shows up at the next scheduled check instead of at the next monthly attestation, and so holders can read the backing for themselves.

Goldsky records every mint and burn, keeps supply per chain and runs the scheduled check that compares supply with reserves, then publishes the ratio, alerts your team or pauses the token, while the reserves, their attestation and fixing any shortfall stay with you, your custodians and your accounting firm.

You can build it two ways: stream every mint and burn into your database with Turbo Pipelines and run the check as a scheduled Compose task, or have a scheduled task read total supply on each chain over Edge RPC with no pipeline at all.

Who uses continuous proof of reserves?

Stablecoin issuers, the platforms that issue coins for other brands, EU banks issuing e-money tokens under MiCA, and crypto exchanges showing they hold what customers are owed.

How continuous proof of reserves works

The diagram follows one scheduled check, from a change in supply on the chain to either a backing ratio on record or your team fixing a shortfall. Your setup may differ.

Goldsky, step 2: TurboRecord supply changesEach mint and burn, and supply per chain
Blockchains, step 1: Supply changesTokens minted or burned on any chain
Your business, step 4: CustodianReport reservesYour custodian’s API returns its holdings
Goldsky, step 3: ComposeStart the checkYour task runs every few minutes
Goldsky, step 5: ComposeCompare supply to reservesReserves fetched, backing ratio worked out
Goldsky, step 6: ComposePublish the ratioWhen healthy, attested onchain
or
Goldsky, steps 7–8: ComposeAlert, and pause if setBelow your floor; pausing needs the pause role
Your business, step 9: Fix the shortfallYour team restores backing
Blockchains: Backing on recordAnyone can read the latest ratio
  • Goldsky
  • Your provider

Ways to run continuous proof of reserves

With streaming, the check reads supply from a per-event record in your database that examiners can trace; the scheduled task on its own reads each chain’s current total over RPC and keeps no history.

Best for
Supply traced event by event, checked on a schedule
Products
TurboCompose
Best for
A few EVM chains, with no pipeline or database
Products
ComposeEdge

Option 1: Run continuous proof of reserves from a streamed supply record

A pipeline records every mint and burn in your database, and a scheduled task compares supply with your custodian’s reserve figure, then publishes the ratio onchain, alerts your team or pauses the token.

When to check reserves against a streamed supply record

Your token is on several chains, and examiners or your own team need to trace every supply figure back to the mints and burns behind it.

What you’ll need

  • Goldsky Turbo
  • Goldsky Compose
  • A custodian or bank that reports reserves over an API
  • A database for the supply record
  • A contract to record the ratio onchain, if you publish it
  • The pause role on your token contract, if the check can pause it
  • An alerting endpoint your operations team watches
  1. Mint and burn tokens on each chain

    Supply changes every time tokens are minted for a client or burned in a redemption.

    Each chain the token is on holds its own share of the supply. A check that leaves one chain out undercounts supply, so the ratio looks healthier than it is.

  2. Keep a record of every supply change

    Handled by Goldsky Turbo

    A check needs a supply figure it can trust and trace back to the events behind it.

    Every mint and burn on every chain goes into one table with its amount, chain, block and transaction, from the contract’s first event, with supply per chain kept beside it. Any figure the check uses can then be rebuilt event by event.

    With Goldsky, a Turbo Pipelines pipeline decodes your token’s mint and burn events and writes them to a database table keyed on id, so reorg corrections update the same rows. Its postgres_aggregate sink keeps supply per chain as a running total in the same database.

    Set up the Postgres sink (opens in a new tab)
  3. Run the check on a schedule

    Handled by Goldsky Compose

    Reserves are compared with supply at regular times, between the monthly attestations.

    The schedule sets how long a shortfall can go unseen. A check that stops running quietly is worse than none, because the team assumes it ran.

    A Compose task runs on a cron trigger set in compose.yaml, at whatever interval your risk policy calls for.

    Set up a cron trigger (opens in a new tab)
  4. Get the reserve figure from your custodian

    Reserves sit with banks and custodians, so the figure has to come from their records.

    The custodian’s API returns its holdings and the time they were valued. A figure that’s days old makes the check compare today’s supply with last week’s reserves.

  5. Compare supply with reserves

    Handled by Goldsky Compose

    The backing ratio, reserves divided by tokens outstanding, says whether every token is covered.

    Supply and reserves have to be read for the same moment and in the same units, with the token’s decimals applied. Checking the contract’s figure against the per-chain totals from your supply record also catches a chain or event the record missed.

    Each run of the task reads supply with wallet.readContract calling totalSupply(), fetches the reserve figure with ctx.fetch, which retries a failed request, and works out the ratio against your threshold.

    Make auditable HTTP requests (opens in a new tab)
  6. Publish the ratio when backing is healthy

    Handled by Goldsky Compose

    A ratio written onchain lets holders, wallets and other applications read the backing themselves.

    The contract that stores it should accept updates only from your publishing wallet and record when the reserves were valued. A ratio anyone can write, or one with no date, proves nothing.

    With Goldsky Compose, the task writes the ratio to your attestor contract with wallet.writeContract from a gas-sponsored wallet. The NAV oracle guide shows the same pattern publishing one figure to several chains behind a Chainlink-compatible interface.

    Write to contracts from a task (opens in a new tab)
  7. Alert, and pause the token if set

    Handled by Goldsky Compose

    When reserves fall below your threshold, someone has to know at once, and some issuers pause the token until backing is restored.

    The alert goes to the team that can act, with the ratio, supply and reserve figures that set it off. Pausing calls the token contract, so the wallet that does it needs the pause role, granted under the same approval rules as any admin key.

    On a breach, the task posts the figures to your alerting endpoint with ctx.fetch and can call the token’s pause function. If a run resumes after a failure, calls that already completed aren’t sent again, so the alert and the pause each happen once.

    Write to contracts from a task (opens in a new tab)
  8. Keep a record of every check

    Handled by Goldsky Compose

    Examiners and your own risk team will ask what each check saw, and why it did or didn’t act.

    Each run’s inputs, ratio, decision and any transaction need to be stored together. A check whose results aren’t kept can’t be shown to have run.

    Goldsky Compose logs every call a task makes, including each reserve request, contract read and transaction, so any run’s inputs and outputs can be reviewed afterwards.

    How Compose logs each call (opens in a new tab)
  9. Fix the shortfall

    An alert only helps if someone closes the gap and records what happened.

    Treasury finds the cause, such as a late reserve figure, a mint booked before funds settled or a real loss, and restores backing. Lifting a pause and writing up the incident follow your own approval rules.

What to know about checking reserves against a streamed supply record

  • The check is only as current as the custodian’s figure: supply can be read from the chain at any block, and reserves can’t.
  • Goldsky runs the pipeline and the task; the database, the threshold and what happens after an alert are yours.
  • Every run’s calls and results are logged, so a reviewer can see what the task read and why it acted.
  • Pausing from the task means granting its wallet the pause role, so that permission needs the same approval as any other admin key.

Option 2: Run continuous proof of reserves with a scheduled task and RPC reads

A scheduled task reads total supply from your token’s contract on each chain over RPC, fetches your custodian’s reserve figure and compares the two, then publishes, alerts or pauses. There’s no pipeline or database.

When to run proof of reserves as a single task

Your token is on a few EVM chains, the contract’s total supply is the figure you need, and you don’t need a history of each mint and burn behind it.

What you’ll need

  • Goldsky Compose
  • Goldsky Edge
  • A custodian or bank that reports reserves over an API
  • A contract to record the ratio onchain, if you publish it
  • The pause role on your token contract, if the check can pause it
  • An alerting endpoint your operations team watches
  1. Mint and burn tokens on each chain

    Supply changes every time tokens are minted for a client or burned in a redemption.

    Each chain the token is on holds its own share of the supply. A check that leaves one chain out undercounts supply, so the ratio looks healthier than it is.

  2. Run the check on a schedule

    Handled by Goldsky Compose

    Reserves are compared with supply at regular times, between the monthly attestations.

    The schedule sets how long a shortfall can go unseen. A check that stops running quietly is worse than none, because the team assumes it ran.

    A Compose task runs on a cron trigger set in compose.yaml, at whatever interval your risk policy calls for.

    Set up a cron trigger (opens in a new tab)
  3. Read total supply on each chain

    Handled by Goldsky Edge

    Each chain’s supply is the total supply figure held in the token contract on that chain.

    Each chain has to be read at a known block, so the figures can be added up and the read repeated later. A chain the task doesn’t read is left out of the total without any error.

    Goldsky’s Edge RPC responds to eth_call against the token’s totalSupply() at the block number you pass, so each read can be repeated at the same block.

    Read contract state with eth_call (opens in a new tab)
  4. Get the reserve figure from your custodian

    Reserves sit with banks and custodians, so the figure has to come from their records.

    The custodian’s API returns its holdings and the time they were valued. A figure that’s days old makes the check compare today’s supply with last week’s reserves.

  5. Compare supply with reserves

    Handled by Goldsky Compose

    The backing ratio, reserves divided by tokens outstanding, says whether every token is covered.

    Supply and reserves have to be read for the same moment and in the same units, with the token’s decimals applied. A ratio built from mismatched times or units can raise a false alarm or hide a real one.

    The Compose task adds up the chain totals, fetches the reserve figure with ctx.fetch and works out the ratio against your threshold; a failed request is retried before the run gives up.

    Make auditable HTTP requests (opens in a new tab)
  6. Publish the ratio when backing is healthy

    Handled by Goldsky Compose

    A ratio written onchain lets holders, wallets and other applications read the backing themselves.

    The contract that stores it should accept updates only from your publishing wallet and record when the reserves were valued. A ratio anyone can write, or one with no date, proves nothing.

    With Goldsky Compose, the task writes the ratio to your attestor contract with wallet.writeContract from a gas-sponsored wallet. The NAV oracle guide shows the same pattern publishing one figure to several chains behind a Chainlink-compatible interface.

    Write to contracts from a task (opens in a new tab)
  7. Alert, and pause the token if set

    Handled by Goldsky Compose

    When reserves fall below your threshold, someone has to know at once, and some issuers pause the token until backing is restored.

    The alert goes to the team that can act, with the ratio, supply and reserve figures that set it off. Pausing calls the token contract, so the wallet that does it needs the pause role, granted under the same approval rules as any admin key.

    On a breach, the task posts the figures to your alerting endpoint with ctx.fetch and can call the token’s pause function. If a run resumes after a failure, calls that already completed aren’t sent again, so the alert and the pause each happen once.

    Write to contracts from a task (opens in a new tab)
  8. Keep a record of every check

    Handled by Goldsky Compose

    Examiners and your own risk team will ask what each check saw, and why it did or didn’t act.

    Each run’s inputs, ratio, decision and any transaction need to be stored together. A check whose results aren’t kept can’t be shown to have run.

    Goldsky Compose logs every call a task makes, including each reserve request, contract read and transaction, so any run’s inputs and outputs can be reviewed afterwards.

    How Compose logs each call (opens in a new tab)
  9. Fix the shortfall

    An alert only helps if someone closes the gap and records what happened.

    Treasury finds the cause, such as a late reserve figure, a mint booked before funds settled or a real loss, and restores backing. Lifting a pause and writing up the incident follow your own approval rules.

What to know about running proof of reserves as a single task

  • Supply is read at check time, so there’s no per-event history showing how it got there.
  • A ratio that moves can’t be traced to the mints or burns behind it without another source.
  • All the logic sits in one TypeScript codebase that Goldsky hosts and runs on your schedule.
  • Every run’s reads, requests and transactions are logged, which gives reviewers a record of each check.

How to run exchange proof of reserves with liabilities

Read an exchange’s wallet balances at the snapshot block, then compare them with the customer liability total its auditor checks. Also called proof of reserves audit or crypto exchange proof of reserves.

Here the onchain side is the exchange’s own wallets instead of a token’s supply. A pipeline keeps every reserve wallet’s balance after each change, and a scheduled Compose task compares the totals with customer liabilities from your ledger, asset by asset, between the accountant’s reviews.

What you’ll need

  • Goldsky Turbo
  • Goldsky Compose
  • The list of wallets that hold customer assets, by asset and chain
  • An internal API that returns customer liability totals per asset
  • A Postgres database for the watch list and balance record
  • An alerting endpoint your treasury team watches
  • An accounting firm for the periodic review
  1. List the wallets that hold customer assets

    Reserves are the assets in wallets the exchange controls, so the check starts from a complete list of them.

    Each wallet goes on the list with its asset and chain, and the exchange has to be able to sign with its key, which is how a review confirms control. A wallet left off understates reserves; one the exchange doesn’t control overstates them.

  2. Keep each reserve wallet’s balance

    Handled by Goldsky Turbo

    Any moment you later pick for a check or a review needs every wallet’s balance at that block.

    The balance has to be read at the block where it changed, for tokens and the chain’s own coin alike. Reading on a timer misses movements between reads, such as assets borrowed in just before a snapshot and returned after it.

    With Goldsky, the wallet list can be a Turbo Pipelines dynamic table, and a transform reads balanceOf with _gs_eth_call at each transfer’s block. For the chain’s own coin, _gs_evm_get_balances does the same.

    Read balances with Turbo SQL functions (opens in a new tab)
  3. Check on a schedule between reviews

    Handled by Goldsky Compose

    An accountant’s review covers one moment and says nothing about the days after it.

    The check runs often enough to find a shortfall while it’s still small, and every run is kept, so you can show reserves were held between reviews too.

    A Compose task with a cron trigger runs the check at the interval you set, and each run’s calls and results are logged.

    Run a task on a schedule (opens in a new tab)
  4. Read customer liabilities from your ledger

    Handled by Goldsky Compose

    Liabilities are what the exchange owes customers in each asset, and they live in its own books, not on the chain.

    Totals are per asset and taken at the moment of the check, with staked balances and open margin positions counted the way your review methodology counts them. Liabilities from a different moment than the balances make the ratio meaningless.

    The task calls your ledger’s API with ctx.fetch, which retries a failed request and records the call and its response in the run’s log.

    Make auditable HTTP requests (opens in a new tab)
  5. Compare reserves with liabilities

    Handled by Goldsky Compose

    The reserve ratio, assets held divided by what customers are owed, says whether every customer balance is covered.

    Each asset is checked on its own, because a surplus in one asset doesn’t cover a shortfall in another. A ratio below your floor raises an alert with the asset, both totals and the block, and a ratio at or above it is still recorded.

    Each run of the Compose task adds up the latest balances in the pipeline’s record for each asset, works out the ratio against your floor and posts an alert to your endpoint when it falls short.

    See the reserve-check task (opens in a new tab)
  6. Have an accountant review a snapshot

    Customers and counterparties want an outside party to confirm the exchange holds what it owes.

    The accountant puts every customer balance at the snapshot into a Merkle tree (a structure that lets each customer check their balance is included), checks the exchange’s signatures for its wallets and compares their balances with the total. The review isn’t an audit: it covers one moment and may not show whether assets were borrowed for it.

How to publish proof-of-reserve ratios onchain

Publish the ratio of reserves to supply onchain so contracts and users can read it. Also called collateralization ratio or proof of reserve feed.

A pipeline keeps the token’s supply on each chain in your database, and a TypeScript task that you write and Goldsky hosts reads it with the latest reserve figure on a schedule and writes the ratio to a contract on each chain. Each call the task makes is retried and logged. Unlike an exchange’s proof of reserves, an attestation at one point in time that customer balances are covered, this ratio compares a token’s supply with its reserves and is published onchain on every run.

When to keep supply in your database

The token is on many chains, or your team also needs every mint and burn on file to explain a change in the ratio.

What you’ll need

  • Goldsky Compose
  • Goldsky Turbo
  • A custodian or bank that reports the reserve balance at an endpoint you can call
  • A database you run, such as Postgres, with an API the task can call for supply
  • A reserve contract on each chain where the token is issued
  1. Keep supply on each chain

    Handled by Goldsky Turbo

    The ratio compares reserves with every token in circulation, so supply has to be known on every chain the token is on.

    Every mint and burn on every chain has to be counted once, and a reorg (the chain replacing its newest blocks) can undo one already counted. A chain left out makes the ratio look healthier than it is.

    Turbo Pipelines can pick mints and burns out of the token’s transfers and keep a running supply per chain in a Postgres table with the postgres_aggregate sink, correcting it when a reorg removes a row, as long as the SQL that picks them keeps the _gs_op column.

    Keep running totals in Postgres (opens in a new tab)
  2. Report the reserve balance

    The other side of the ratio is the cash, securities or assets held for the token, which only the custodian or bank can confirm.

    Your custodian or bank reports the reserve balance with the time it applies to. A balance with no time can’t be matched to the supply it’s compared with.

  3. Set up a contract for the reserve ratio on each chain

    Apps can only read the reserve ratio from a contract on their own chain, so each chain needs one that stores it.

    Deploy a contract on each chain that stores the latest reserve ratio and its date, and lets only your publishing wallet update it. If anyone can write to it, anyone can change the reserve ratio the apps read.

  4. Work out the ratio on schedule

    Handled by Goldsky Compose

    The ratio is only current if someone recomputes it each time supply or reserves change.

    Each run reads the reserve balance and the total supply across chains and divides one by the other. If the reserve source can’t be reached, the run should fail loudly rather than publish an old ratio as new.

    A Compose task with a cron trigger reads the reserve balance, and your supply per chain through an API you expose over your database, with context.fetch, which retries a failed call with backoff.

    Set up a cron trigger (opens in a new tab)
  5. Publish the ratio to each chain

    Handled by Goldsky Compose

    Contracts and users read the ratio on their own chain, so each chain gets the same value.

    Each chain is written separately, so one failing chain doesn’t block the others. Wait for the confirmations you set before treating an update as published.

    With Goldsky Compose, the task writes each chain with wallet.writeContract, can wait for confirmations, and with onReorg set to replay sends a dropped update again.

    Handle confirmations and reorgs (opens in a new tab)
  6. Keep a record of every update

    Handled by Goldsky Compose

    If an app or an auditor asks why a value was on the chain, the answer has to come from records of what was read and written.

    The record ties each value on the chain to the source response it came from, the time it was read and the transaction that wrote it. Without it, rebuilding one update means searching logs on each side by hand.

    Every call a Compose task makes, including each fetch from your source and each transaction it sends, is logged for auditing. If a run is interrupted, calls that already finished aren’t repeated, so a write isn’t sent twice.

    How Compose logs each call (opens in a new tab)
  7. Contracts act on the ratio

    The ratio matters because contracts can refuse to mint, or pause, when reserves fall short.

    A token’s mint function or a lending market reads the ratio and its date from the contract on its chain. What it does below a threshold is set by the contract’s owner, and an old ratio should count as stale.

What you control

Your team
  • Fix the shortfall
Your providers
  • Custodian

Continuous checks, attestations and audits

Continuous check
How often
On a schedule you set
Who runs it
Your team, on Goldsky
What it shows
Onchain supply against the latest reserve figure
Monthly attestation
How often
Monthly
Who runs it
An accounting firm
What it shows
Reserves on a date, against supply on that date
Financial-statement audit
How often
Yearly
Who runs it
An accounting firm
What it shows
The issuer’s full financial position

Run the continuous check to catch a gap between reports; keep the attestation and audit for the independent opinion.

Questions and answers

What is proof of reserves?

Proof of reserves is evidence that the assets backing a token or customer balances exist and cover what’s owed. For a stablecoin issuer, it compares the tokens outstanding on every chain with the cash and securities its custodians hold. The supply side is public and can be read from the chain at any block. The reserve side comes from the custodian’s records, so a proof is only as current as the latest reserve figure behind it.

What is a proof-of-reserves (PoR) in crypto?

In crypto, a proof of reserves (PoR) is a published check that an exchange, custodian or token issuer holds the assets it owes. Exchanges publish one to show customer balances are covered. Stablecoin issuers publish a backing ratio, reserves divided by tokens outstanding, and some write it to a contract onchain so wallets and other applications can read the latest figure for themselves.

What is a proof of reserves audit?

What people call a proof of reserves audit is usually an accounting firm’s attestation or a proof of reserves report, a check of reserves at one point in time. Staff at the PCAOB, the US regulator of public-company auditors, have warned that proof of reserves reports aren’t audits and give no meaningful assurance: they cover one moment and may not address liabilities. A continuous check compares onchain supply with the reserves your custodians report, between attestations. It doesn’t test those reserve figures, so it adds to the attestation and doesn’t replace it.

Security and deployment

  • SOC 2 Type IIIndependently audited security controls.
  • Dedicated infrastructureSingle-tenant options for production workloads.
  • Data residencyCloud, on-premises or co-located.

Run continuous proof of reserves with Goldsky

We’ll map it to your systems and show you what Goldsky runs, so your team builds the product, not the pipelines underneath it.

© Endless Sky Inc. All rights reserved.

PrivacyTermsSecurity

System status