feat(contracts): oracle price staleness circuit breaker#2
Open
Dev-Odun-oss wants to merge 1 commit into
Open
Conversation
Implements a circuit breaker in carbon_marketplace and a price-staleness
check in carbon_oracle to halt trades when oracle data is stale.
### carbon_oracle/src/lib.rs
- Added PRICE_STALENESS_SECS constant (24 hours).
- Added PriceUpdatedAt(String, u32) DataKey variant: stores the Unix
timestamp of the last successful update_credit_price() call in
persistent storage (survives even after the 17_280-ledger TTL on the
temporary price entry expires).
- update_credit_price() now writes PriceUpdatedAt alongside the price.
- Added is_price_current(methodology, vintage_year) -> bool: returns
true iff PriceUpdatedAt exists and is < 24 hours old. This is the
query function the marketplace calls for every purchase.
- Added 7 tests in mod staleness_tests covering: never-set returns false,
fresh update returns true, stale after 24 h, recovery after re-update,
is_monitoring_current regression (365-day window), independent
tracking per (methodology, vintage_year) pair.
### carbon_marketplace/src/lib.rs
- Added CircuitBreakerTripped = 22 to CarbonError.
- Added DataKey variants: OracleContract, CircuitBreaker,
CircuitBreakerTrippedAt.
- Added CircuitBreakerEvent and CircuitBreakerResetEvent contracttypes
for on-chain event emission (with alert design docs in comments).
- Added set_oracle_contract(admin, oracle): admin registers the oracle
contract address post-deployment.
- Added get_circuit_breaker_state() -> bool: query endpoint.
- Added get_circuit_breaker_tripped_at() -> Option<u64>: audit trail.
- Added trip_circuit_breaker(admin): manual admin halt.
- Added reset_circuit_breaker(admin): recovery endpoint; emits
CircuitBreakerResetEvent.
- purchase_credits() now:
1. Checks CircuitBreaker flag at entry — returns CircuitBreakerTripped
if already tripped.
2. After loading the listing, calls oracle.is_price_current() via
cross-contract invoke (skipped if no oracle registered).
3. On stale price: auto-trips the breaker, emits ("c_ledger",
"cb_trip") CircuitBreakerEvent, returns CircuitBreakerTripped.
- bulk_purchase() has the same two-layer circuit breaker guard.
- Added 12 tests in mod circuit_breaker_tests covering: initial state,
manual trip, purchase blocked, bulk_purchase blocked, admin reset,
recovery sequence, set_oracle_contract, non-admin cannot trip/reset,
timestamp audit trail, multiple trip/reset cycles.
Alert design (documented in CircuitBreakerEvent):
- Watch for topic ("c_ledger", "cb_trip") events from the marketplace.
- P1 alert if tripped during trading hours; Slack warn otherwise.
- Recovery: oracle submits fresh price → admin calls reset_circuit_breaker().
Closes Carbon-Ledger-stellar#534
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Implements a circuit breaker in
carbon_marketplaceand a price-staleness check incarbon_oracleto halt trades when oracle price data exceeds the 24-hour freshness threshold.Changes
contracts/carbon_oracle/src/lib.rsPRICE_STALENESS_SECSconstant (24 hours).PriceUpdatedAt(String, u32)DataKeyvariant — stores the Unix timestamp of the lastupdate_credit_price()call in persistent storage (survives the temporary price entry TTL).update_credit_price()now writesPriceUpdatedAtalongside the price value.is_price_current(methodology, vintage_year) -> bool: returnstrueiff the price was updated within the last 24 hours.mod staleness_tests.contracts/carbon_marketplace/src/lib.rsCircuitBreakerTripped = 22toCarbonError.DataKeyvariants:OracleContract,CircuitBreaker,CircuitBreakerTrippedAt.CircuitBreakerEventandCircuitBreakerResetEventcontract types with alert design documentation in comments.set_oracle_contract(admin, oracle)— admin registers the oracle address post-deployment.get_circuit_breaker_state() -> boolandget_circuit_breaker_tripped_at() -> Option<u64>.trip_circuit_breaker(admin)— manual halt.reset_circuit_breaker(admin)— recovery endpoint, emitsCircuitBreakerResetEvent.purchase_credits()now:CircuitBreakerflag at entry → returnsCircuitBreakerTrippedimmediately if already set.oracle.is_price_current()via cross-contract invoke (skipped if no oracle registered).("c_ledger", "cb_trip")event, returnsCircuitBreakerTripped.bulk_purchase()has the same two-layer circuit breaker guard.mod circuit_breaker_tests.Acceptance Criteria
is_monitoring_current()returns false if data >365 days oldCircuitBreakerEventemitted on auto-tripreset_circuit_breaker()CircuitBreakerEventdoc commentsAlert Design
External systems should watch for the event topic
("c_ledger", "cb_trip")emitted by the marketplace contract.("c_ledger", "cb_trip")CircuitBreakerEvent { methodology, vintage_year, price_age_secs, threshold_secs, tripped_at }update_credit_price()→ admin callsreset_circuit_breaker()Recovery Path
carbon_oracle::update_credit_price()carbon_marketplace::reset_circuit_breaker()purchase_credits()andbulk_purchase()resume normallyCloses Carbon-Ledger-stellar#534