A manipulation-resistant price oracle system implementing Time-Weighted Average Price (TWAP) calculations to provide reliable price feeds for DeFi protocols on Stacks blockchain.
ChronosOracle solves the critical problem of price manipulation in decentralized finance by using time-weighted averages rather than spot prices. This makes it significantly more expensive and difficult for attackers to manipulate price feeds, protecting DeFi protocols and their users.
Traditional oracles that report single spot prices are vulnerable to:
- Flash loan attacks
- Sandwich attacks
- Market manipulation during low liquidity periods
Time-weighted oracles mitigate these risks by:
- Averaging prices over extended time windows
- Making manipulation expensive (must sustain attack over time)
- Providing smoother, more reliable price data
- Filtering out temporary market anomalies
- Configurable observation windows (default: 24 hours)
- Multiple price observations stored in ring buffer
- Weighted averaging across time periods
- Automatic staleness detection
- Register unlimited price pairs
- Independent tracking per pair
- Customizable decimal precision
- Active/inactive pair management
- Role-based price submission
- Multiple authorized reporters
- Admin controls for reporter management
- Batch observation submissions
- Minimum observation requirements
- Maximum price age enforcement
- Zero-price rejection
- Active pair verification
Price Pairs: Register trading pairs with base/quote assets and decimals Cumulative Prices: Track cumulative sum for TWAP calculation Price Observations: Ring buffer of recent price submissions Reporter Registry: Authorized accounts for price submission
The oracle maintains a sliding window of observations:
Block Height: 1000 1010 1020 1030 1040 1050
Price: $100 $102 $101 $103 $102 $104
└─────── 24 hour window ────────┘
TWAP: Average of all prices in window
;; Register a new trading pair
(register-price-pair
(pair-name "STX-USD")
(base "STX")
(quote "USD")
(decimals u6))
;; Toggle pair active status
(toggle-pair-status "STX-USD")
;; Update decimal precision
(update-pair-decimals "STX-USD" u8);; Submit single observation
(submit-price-observation "STX-USD" u1500000)
;; Batch submit multiple pairs
(submit-batch-observations
(list
{ pair: "STX-USD", price: u1500000 }
{ pair: "BTC-USD", price: u42000000000 }
));; Get time-weighted average price
(calculate-twap "STX-USD")
;; Get latest price with staleness check
(get-latest-price "STX-USD")
;; Get specific observation
(get-observation "STX-USD" u5)
;; Get pair configuration
(get-price-pair "STX-USD");; Set observation window (in blocks)
(set-observation-window u144)
;; Set minimum observations required
(set-minimum-observations u3)
;; Set maximum price age before stale
(set-max-price-age u72)Determine collateral value and liquidation thresholds using manipulation-resistant prices
Reference prices for limit orders and fair value calculations
Settlement prices for options, futures, and perpetual contracts
Portfolio valuation and rebalancing based on reliable price data
Peg maintenance and collateral ratio monitoring
Flash Loan Attacks: TWAP requires sustained price manipulation over observation window, making flash loan attacks ineffective
Sandwich Attacks: Time-averaging smooths out temporary price spikes from front-running
Low Liquidity Manipulation: Multiple observations required before TWAP is available
- Only authorized reporters can submit prices
- Admin can disable pairs in emergencies
- Staleness checks prevent outdated prices
- Minimum observation requirements ensure data quality
High-Frequency Trading Pairs (e.g., BTC-USD):
- Observation window: 144 blocks (~24 hours)
- Minimum observations: 5
- Max price age: 36 blocks (~6 hours)
Low-Frequency Pairs (e.g., Long-tail altcoins):
- Observation window: 288 blocks (~48 hours)
- Minimum observations: 3
- Max price age: 144 blocks (~24 hours)
Critical Infrastructure (e.g., Stablecoin collateral):
- Observation window: 72 blocks (~12 hours)
- Minimum observations: 10
- Max price age: 18 blocks (~3 hours)
- Deploy Contract: Deploy ChronosOracle to Stacks mainnet
- Register Pairs: Add all required trading pairs with correct decimals
- Authorize Reporters: Add trusted reporter addresses
- Configure Windows: Set observation windows based on pair characteristics
- Start Reporting: Begin submitting regular price observations
- Integrate Protocols: Connect DeFi protocols to oracle feeds
Authorized reporters should:
- Submit prices at regular intervals (recommended: every 10 blocks)
- Use reliable price sources (CEX aggregators, DEX TWAPs)
- Monitor for submission failures and gaps
- Maintain high uptime and reliability
- Report accurate decimal-adjusted prices
;; In your DeFi protocol
(define-public (get-collateral-value (amount uint))
(let ((stx-price (unwrap! (contract-call? .chronos-oracle calculate-twap "STX-USD")
err-price-unavailable)))
(ok (/ (* amount stx-price) u1000000))
)
)- Verify observation counts remain above minimum
- Check last update times for all pairs
- Monitor reporter activity and failures
- Track price deviation from external sources
- Stale price warnings
- Reporter inactivity
- Extreme price deviations
- Observation gap detection
- Requires minimum observations before TWAP available
- Lags behind spot prices by nature (feature, not bug)
- Depends on reporter reliability and honesty
- Historical observations limited by window size
- Multi-source price aggregation
- Automated outlier detection and removal
- Weighted reporter credibility system
- Cross-chain price verification
- Chainlink integration
- Median price calculation option
# Test price submission
clarinet test tests/submit_price.test.ts
# Test TWAP calculation
clarinet test tests/calculate_twap.test.ts
# Test authorization
clarinet test tests/reporter_auth.test.tsMIT License
Issues, questions, or contributions welcome via GitHub.