Metacenter

Example: coverage-guard-cached (mainnet)

A live mainnet contract that pauses when coverage gets thin or the feed goes stale. Copy it.

This is the example consumer, deployed on mainnet and calling the real feed. It holds no funds, owns nothing and can move nothing: check returns a verdict its caller acts on.

ContractNetworkID
pox5-readermainnetSP2Q3XVGTTA4CW3E2AHFZPAGQ0HM9QPHTTBJTQGJY.pox5-reader
risk-feed-traitmainnetSP2Q3XVGTTA4CW3E2AHFZPAGQ0HM9QPHTTBJTQGJY.risk-feed-trait
coverage-cachemainnetSP2Q3XVGTTA4CW3E2AHFZPAGQ0HM9QPHTTBJTQGJY.coverage-cache
risk-feedtestnetST24MYZSDF0TAVZ452R2TJY3RCQAVT3KR0FJHYCAJ.risk-feed
risk-feed-traittestnetST24MYZSDF0TAVZ452R2TJY3RCQAVT3KR0FJHYCAJ.risk-feed-trait
coverage-guard-cached (example consumer)mainnetSP2Q3XVGTTA4CW3E2AHFZPAGQ0HM9QPHTTBJTQGJY.coverage-guard-cached
coverage-guardtestnetST24MYZSDF0TAVZ452R2TJY3RCQAVT3KR0FJHYCAJ.coverage-guard
pox-5 (read by pox5-reader)mainnetSP000000000000000000002Q6VF78.pox-5

The whole integration

Five lines inside your own function: take the feed as a trait, check it is the one you trust, read the summary, and refuse when coverage is thin or the reading is old.

(use-trait risk-feed .risk-feed-trait.risk-feed-trait)
(define-constant TRUSTED_FEED 'SP2Q3XVGTTA4CW3E2AHFZPAGQ0HM9QPHTTBJTQGJY.coverage-cache)
(define-constant MIN_COVERAGE_BPS u20000) ;; 2.0x

(define-public (deposit (feed <risk-feed>) (amount uint))
    (let ((s (try! (contract-call? feed get-coverage-summary))))
        (asserts! (is-eq (contract-of feed) TRUSTED_FEED) (err u200))
        (asserts! (match (get coverage-bps s) c (>= c MIN_COVERAGE_BPS) true) (err u202))
        (asserts! (<= (- burn-block-height (get updated-at s)) u1300) (err u203))
        ;; ... your deposit logic
        (ok amount)
    )
)

What it returns

check answers (ok { status, coverage-bps, age-blocks, stale, provenance }):

FieldMeaning
status"ok", or "paused" when coverage is below the threshold or the reading is stale
coverage-bpscoverage in basis points, none when there are no bonds to cover
age-blocksBitcoin blocks since the feed's reading was recorded
staleage-blocks exceeds the staleness window
provenance"onchain": the figures are pox5-reader's, computed from pox-5 state

Errors: u200 the feed is not the trusted one, u201 only the deployer may change the staleness window, and any error the feed itself returns (coverage-cache answers u200 before its first refresh).

The two settings, and why

SettingValueReasoning
MIN_COVERAGE_BPSu20000, 2.0×The coverage target discussed in the Bitcoin Staking SIP thread. Equivalent to 50% headroom. Coverage is 16.68× onchain (block 967,911), so a vault using this threshold is not paused today.
max-age-blocksu1300 Bitcoin blockspox-5 computes a distribution every 1,050 blocks, and the keeper refreshes coverage-cache at least every 1,100. 1,300 leaves about 200 blocks, roughly a day and a half, before a feed that stopped being refreshed pauses the caller. Only the deployer can change it; a contract copying this pattern should set its own.

Pick your own numbers: a conservative vault might pause at 4.0× (u40000), and one that reads the feed every block could use a tighter staleness window.

Proven on mainnet

WhatTransactionResult
Called with the trusted feed0xa5faac80…(ok { status "ok", coverage-bps (some u166780), age-blocks u117, stale false, provenance "onchain" })
Called with another contract as the feed0xf51d4309…(err u200): refused, because it is not the trusted feed

The "paused" branches cannot be shown on mainnet without a real shortfall, so they are covered against live chain state in contracts/tests-tip, which mines past the staleness window and checks the verdict flips. See Health and degradation for how the feed behaves when a piece of the service is down.

Source: contracts/contracts/coverage-guard-cached.clar. The testnet coverage-guard is the same guard reading the testnet risk-feed.

Edit on GitHub

On this page