This commit is contained in:
Gulshan Yadav 2026-01-11 19:05:44 +05:30
parent 162227dc71
commit 3c9470abba
3 changed files with 912 additions and 0 deletions

View file

@ -0,0 +1,242 @@
# Milestone 1: Pricing Oracle
> Build decentralized price feeds for SYNOR/USD conversion, enabling stable pricing for L2 services.
---
## Overview
The Pricing Oracle aggregates price data from multiple sources to provide reliable SYNOR/USD rates for service pricing. This ensures users can estimate costs in familiar fiat terms while paying in SYNOR tokens.
---
## Components
### 1.1 Price Feed Aggregator
```rust
// crates/synor-economics/src/oracle/price_feed.rs
/// Price source for SYNOR/USD rates
pub enum PriceSource {
/// On-chain DEX (Synor DEX, Uniswap, etc.)
Dex { pool_address: Address, pair: TradingPair },
/// Centralized exchange API
Cex { exchange: String, api_endpoint: String },
/// Chainlink-style oracle
Chainlink { feed_address: Address },
/// Off-chain oracle (signed by trusted nodes)
OffChain { oracle_id: OracleId },
}
/// Aggregated price with metadata
pub struct AggregatedPrice {
/// SYNOR/USD price (6 decimal places)
pub price: u64,
/// Unix timestamp
pub timestamp: u64,
/// Sources used
pub sources: Vec<PriceSource>,
/// Confidence (0-100)
pub confidence: u8,
/// 24h high
pub high_24h: u64,
/// 24h low
pub low_24h: u64,
/// 24h volume
pub volume_24h: u64,
}
pub struct PriceFeedAggregator {
sources: Vec<PriceSource>,
cache: LruCache<TradingPair, AggregatedPrice>,
update_interval_ms: u64,
}
impl PriceFeedAggregator {
/// Get current price with aggregation across sources
pub async fn get_price(&self, pair: &TradingPair) -> Result<AggregatedPrice, OracleError> {
// Fetch from all sources in parallel
let prices = futures::future::join_all(
self.sources.iter().map(|s| self.fetch_from_source(s, pair))
).await;
// Filter out failures and outliers
let valid_prices = self.filter_outliers(prices);
// Calculate median price
let median = self.calculate_median(&valid_prices);
// Calculate confidence based on source agreement
let confidence = self.calculate_confidence(&valid_prices, median);
Ok(AggregatedPrice {
price: median,
timestamp: current_timestamp(),
sources: self.sources.clone(),
confidence,
..Default::default()
})
}
}
```
### 1.2 Time-Weighted Average Price (TWAP)
```rust
// crates/synor-economics/src/oracle/twap.rs
/// TWAP calculator for stable pricing
pub struct TwapCalculator {
/// Price observations
observations: VecDeque<PriceObservation>,
/// TWAP window (e.g., 1 hour)
window_seconds: u64,
/// Minimum observations required
min_observations: usize,
}
pub struct PriceObservation {
pub price: u64,
pub timestamp: u64,
pub cumulative_price: u128,
}
impl TwapCalculator {
/// Calculate TWAP over the configured window
pub fn calculate_twap(&self) -> Option<u64> {
if self.observations.len() < self.min_observations {
return None;
}
let oldest = self.observations.front()?;
let newest = self.observations.back()?;
let time_elapsed = newest.timestamp - oldest.timestamp;
if time_elapsed == 0 {
return None;
}
let cumulative_diff = newest.cumulative_price - oldest.cumulative_price;
Some((cumulative_diff / time_elapsed as u128) as u64)
}
/// Add new price observation
pub fn observe(&mut self, price: u64) {
let timestamp = current_timestamp();
let cumulative = self.observations
.back()
.map(|o| o.cumulative_price + (price as u128 * (timestamp - o.timestamp) as u128))
.unwrap_or(0);
self.observations.push_back(PriceObservation {
price,
timestamp,
cumulative_price: cumulative,
});
// Remove old observations outside window
let cutoff = timestamp - self.window_seconds;
while self.observations.front().map(|o| o.timestamp < cutoff).unwrap_or(false) {
self.observations.pop_front();
}
}
}
```
### 1.3 Oracle Smart Contract
```rust
// crates/synor-economics/src/oracle/contract.rs
/// On-chain oracle contract for price storage
pub struct OracleContract {
/// Current price (6 decimals)
pub price: u64,
/// Last update timestamp
pub updated_at: u64,
/// Authorized updaters
pub updaters: HashSet<Address>,
/// TWAP values
pub twap_1h: u64,
pub twap_24h: u64,
/// Deviation threshold for updates (basis points)
pub deviation_threshold_bps: u16,
}
impl OracleContract {
/// Update price (only authorized updaters)
pub fn update_price(
&mut self,
caller: Address,
new_price: u64,
sources: Vec<SignedPriceAttestation>,
) -> Result<(), OracleError> {
// Verify caller is authorized
if !self.updaters.contains(&caller) {
return Err(OracleError::Unauthorized);
}
// Verify attestations
let verified_prices = self.verify_attestations(&sources)?;
// Check consensus among sources
let median = self.calculate_median(&verified_prices);
// Check deviation from current price
let deviation = self.calculate_deviation(self.price, median);
if deviation < self.deviation_threshold_bps {
return Ok(()); // No significant change
}
// Update price
self.price = median;
self.updated_at = current_timestamp();
// Emit event
emit_event(PriceUpdatedEvent { price: median, timestamp: self.updated_at });
Ok(())
}
}
```
---
## Tasks
- [ ] Implement PriceFeedAggregator with multiple source support
- [ ] Implement TWAP calculator with configurable windows
- [ ] Deploy oracle smart contract to testnet
- [ ] Set up price updater nodes
- [ ] Integrate with DEX liquidity pools
- [ ] Add CEX price feed support (optional)
- [ ] Implement price staleness detection
- [ ] Add circuit breaker for extreme volatility
---
## Validation Commands
```bash
# Run oracle tests
cargo test --package synor-economics --lib oracle
# Check price feed connectivity
synor oracle status
# Get current SYNOR/USD price
synor oracle price SYNOR/USD
# Check TWAP values
synor oracle twap SYNOR/USD --window 1h
```
---
## Security Considerations
- **Manipulation Resistance**: TWAP smooths out flash loan attacks
- **Source Diversity**: Multiple independent sources prevent single point of failure
- **Deviation Limits**: Large price swings require multiple confirmations
- **Staleness Detection**: Alert when prices haven't updated recently

View file

@ -0,0 +1,483 @@
# Milestone 3: Billing Engine
> Generate invoices, process payments, and manage account credits.
---
## Overview
The Billing Engine transforms metered usage into invoices, processes SYNOR payments, and manages prepaid balances and credits.
---
## Components
### 3.1 Invoice Generator
```rust
// crates/synor-economics/src/billing/invoice.rs
/// Invoice for a billing period
pub struct Invoice {
/// Invoice ID
pub invoice_id: InvoiceId,
/// Account ID
pub account_id: AccountId,
/// Billing period
pub period_start: u64,
pub period_end: u64,
/// Line items
pub line_items: Vec<LineItem>,
/// Subtotal before discounts
pub subtotal_micro_synor: u64,
/// Applied discounts
pub discounts: Vec<AppliedDiscount>,
/// Credits applied
pub credits_applied: u64,
/// Total due
pub total_due_micro_synor: u64,
/// Invoice status
pub status: InvoiceStatus,
/// Due date
pub due_date: u64,
/// Payment transaction (if paid)
pub payment_tx: Option<TxId>,
/// Created at
pub created_at: u64,
}
pub struct LineItem {
pub service: ServiceType,
pub resource: ResourceType,
pub description: String,
pub quantity: u64,
pub unit: MeteringUnit,
pub unit_price_micro_synor: u64,
pub amount_micro_synor: u64,
}
pub struct AppliedDiscount {
pub discount_type: DiscountType,
pub description: String,
pub amount_micro_synor: u64,
}
pub enum DiscountType {
/// Volume discount based on usage tier
Volume { tier: u8 },
/// Commitment discount (reserved capacity)
Commitment { commitment_id: CommitmentId },
/// Promotional credit
Promotional { promo_code: String },
/// Referral credit
Referral { referrer_id: AccountId },
}
pub enum InvoiceStatus {
Draft,
Finalized,
Sent,
Paid,
Overdue,
Voided,
}
pub struct InvoiceGenerator {
metering: UsageAggregator,
pricing: PricingEngine,
discounts: DiscountEngine,
}
impl InvoiceGenerator {
/// Generate invoice for an account
pub async fn generate_invoice(
&self,
account: &AccountId,
period_start: u64,
period_end: u64,
) -> Result<Invoice, BillingError> {
// Get usage summary
let usage = self.metering.get_usage_summary(account, period_start, period_end).await?;
// Convert to line items
let line_items = self.usage_to_line_items(&usage);
// Calculate subtotal
let subtotal = line_items.iter().map(|li| li.amount_micro_synor).sum();
// Apply discounts
let discounts = self.discounts.calculate_discounts(account, &line_items).await?;
let discount_total: u64 = discounts.iter().map(|d| d.amount_micro_synor).sum();
// Apply credits
let available_credits = self.get_available_credits(account).await?;
let credits_applied = std::cmp::min(available_credits, subtotal - discount_total);
// Calculate total
let total_due = subtotal.saturating_sub(discount_total).saturating_sub(credits_applied);
Ok(Invoice {
invoice_id: InvoiceId::new(),
account_id: account.clone(),
period_start,
period_end,
line_items,
subtotal_micro_synor: subtotal,
discounts,
credits_applied,
total_due_micro_synor: total_due,
status: InvoiceStatus::Draft,
due_date: period_end + 30 * 24 * 3600, // 30 days
payment_tx: None,
created_at: current_timestamp(),
})
}
}
```
### 3.2 Payment Processor
```rust
// crates/synor-economics/src/billing/payment.rs
/// Payment processor for SYNOR token payments
pub struct PaymentProcessor {
/// Synor blockchain client
blockchain: SynorClient,
/// Billing contract address
billing_contract: Address,
}
pub struct PaymentRequest {
pub invoice_id: InvoiceId,
pub amount_micro_synor: u64,
pub payer: Address,
}
pub struct PaymentResult {
pub payment_id: PaymentId,
pub tx_id: TxId,
pub amount_micro_synor: u64,
pub timestamp: u64,
pub status: PaymentStatus,
}
pub enum PaymentStatus {
Pending,
Confirmed,
Failed { reason: String },
}
impl PaymentProcessor {
/// Process payment for an invoice
pub async fn process_payment(
&self,
request: PaymentRequest,
) -> Result<PaymentResult, PaymentError> {
// Verify invoice exists and is payable
let invoice = self.get_invoice(&request.invoice_id).await?;
if invoice.status != InvoiceStatus::Finalized && invoice.status != InvoiceStatus::Sent {
return Err(PaymentError::InvoiceNotPayable);
}
// Build payment transaction
let tx = self.blockchain.build_transaction(
TransactionType::Transfer {
to: self.billing_contract,
amount: request.amount_micro_synor,
memo: format!("Invoice payment: {}", request.invoice_id),
},
request.payer,
)?;
// Submit and wait for confirmation
let tx_id = self.blockchain.submit_transaction(tx).await?;
let confirmation = self.blockchain.wait_for_confirmation(&tx_id).await?;
// Update invoice status
self.mark_invoice_paid(&request.invoice_id, &tx_id).await?;
Ok(PaymentResult {
payment_id: PaymentId::new(),
tx_id,
amount_micro_synor: request.amount_micro_synor,
timestamp: current_timestamp(),
status: PaymentStatus::Confirmed,
})
}
/// Set up auto-pay for an account
pub async fn setup_auto_pay(
&self,
account: &AccountId,
funding_source: Address,
max_amount_per_invoice: u64,
) -> Result<AutoPayConfig, PaymentError> {
// Verify funding source has sufficient balance/allowance
// Store auto-pay configuration
Ok(AutoPayConfig {
account_id: account.clone(),
funding_source,
max_amount_per_invoice,
enabled: true,
})
}
}
```
### 3.3 Credit System
```rust
// crates/synor-economics/src/billing/credit.rs
/// Account credit management
pub struct CreditManager {
storage: CreditStorage,
}
pub struct AccountCredit {
pub account_id: AccountId,
pub balance_micro_synor: u64,
pub credits: Vec<CreditEntry>,
}
pub struct CreditEntry {
pub credit_id: CreditId,
pub amount_micro_synor: u64,
pub remaining_micro_synor: u64,
pub source: CreditSource,
pub expires_at: Option<u64>,
pub created_at: u64,
}
pub enum CreditSource {
/// Prepaid balance deposit
Prepaid { tx_id: TxId },
/// Promotional credit
Promotional { campaign: String },
/// Referral bonus
Referral { referred_by: AccountId },
/// SLA credit (compensation)
SlaCredit { incident_id: String },
/// Manual adjustment
Manual { reason: String, admin: Address },
}
impl CreditManager {
/// Add credits to an account
pub async fn add_credits(
&self,
account: &AccountId,
amount: u64,
source: CreditSource,
expires_at: Option<u64>,
) -> Result<CreditEntry, CreditError> {
let entry = CreditEntry {
credit_id: CreditId::new(),
amount_micro_synor: amount,
remaining_micro_synor: amount,
source,
expires_at,
created_at: current_timestamp(),
};
self.storage.add_credit(account, &entry).await?;
Ok(entry)
}
/// Get available credit balance
pub async fn get_balance(&self, account: &AccountId) -> Result<u64, CreditError> {
let credits = self.storage.get_credits(account).await?;
let now = current_timestamp();
let balance = credits.iter()
.filter(|c| c.expires_at.map(|e| e > now).unwrap_or(true))
.map(|c| c.remaining_micro_synor)
.sum();
Ok(balance)
}
/// Apply credits to an invoice
pub async fn apply_credits(
&self,
account: &AccountId,
amount: u64,
invoice_id: &InvoiceId,
) -> Result<u64, CreditError> {
let mut credits = self.storage.get_credits(account).await?;
let now = current_timestamp();
// Sort by expiration (FIFO for expiring credits)
credits.sort_by_key(|c| c.expires_at.unwrap_or(u64::MAX));
let mut remaining = amount;
let mut applied = 0u64;
for credit in credits.iter_mut() {
if remaining == 0 {
break;
}
// Skip expired credits
if credit.expires_at.map(|e| e <= now).unwrap_or(false) {
continue;
}
let apply_amount = std::cmp::min(credit.remaining_micro_synor, remaining);
credit.remaining_micro_synor -= apply_amount;
remaining -= apply_amount;
applied += apply_amount;
// Record usage
self.storage.record_credit_usage(
&credit.credit_id,
apply_amount,
invoice_id,
).await?;
}
Ok(applied)
}
}
```
### 3.4 Prepaid Balance
```rust
// crates/synor-economics/src/billing/prepaid.rs
/// Prepaid balance management (pay-as-you-go with deposits)
pub struct PrepaidManager {
credits: CreditManager,
blockchain: SynorClient,
deposit_address: Address,
}
impl PrepaidManager {
/// Deposit SYNOR to prepaid balance
pub async fn deposit(
&self,
account: &AccountId,
amount: u64,
from: Address,
) -> Result<DepositResult, PrepaidError> {
// Build deposit transaction
let tx = self.blockchain.build_transaction(
TransactionType::Transfer {
to: self.deposit_address,
amount,
memo: format!("Prepaid deposit: {}", account),
},
from,
)?;
// Submit and confirm
let tx_id = self.blockchain.submit_transaction(tx).await?;
self.blockchain.wait_for_confirmation(&tx_id).await?;
// Add to credits
self.credits.add_credits(
account,
amount,
CreditSource::Prepaid { tx_id: tx_id.clone() },
None, // Prepaid credits don't expire
).await?;
Ok(DepositResult {
tx_id,
amount,
new_balance: self.credits.get_balance(account).await?,
})
}
/// Check if account has sufficient balance
pub async fn has_sufficient_balance(
&self,
account: &AccountId,
required: u64,
) -> Result<bool, PrepaidError> {
let balance = self.credits.get_balance(account).await?;
Ok(balance >= required)
}
/// Deduct from prepaid balance (for real-time billing)
pub async fn deduct(
&self,
account: &AccountId,
amount: u64,
reason: &str,
) -> Result<DeductResult, PrepaidError> {
let balance = self.credits.get_balance(account).await?;
if balance < amount {
return Err(PrepaidError::InsufficientBalance {
available: balance,
required: amount,
});
}
// Create a temporary invoice for the deduction
let invoice_id = InvoiceId::new_instant();
self.credits.apply_credits(account, amount, &invoice_id).await?;
Ok(DeductResult {
amount_deducted: amount,
remaining_balance: self.credits.get_balance(account).await?,
})
}
}
```
---
## Tasks
- [ ] Implement Invoice data model and generator
- [ ] Build PaymentProcessor for SYNOR payments
- [ ] Implement CreditManager for account credits
- [ ] Build PrepaidManager for deposit-based billing
- [ ] Create billing smart contract
- [ ] Implement auto-pay functionality
- [ ] Add invoice email/notification system
- [ ] Build billing dashboard API
- [ ] Implement usage alerts and spending limits
---
## Validation Commands
```bash
# Check account balance
synor billing balance
# Get current invoice
synor billing invoice --current
# View invoice history
synor billing invoices --limit 10
# Add prepaid balance
synor billing deposit 100 SYNOR
# Set up auto-pay
synor billing auto-pay enable --max 500
# Export usage report
synor billing export --format csv --period 2026-01
```
---
## API Endpoints
```
GET /api/v1/billing/balance - Get account balance
GET /api/v1/billing/invoices - List invoices
GET /api/v1/billing/invoices/:id - Get invoice details
POST /api/v1/billing/invoices/:id/pay - Pay invoice
GET /api/v1/billing/usage - Get usage summary
POST /api/v1/billing/deposit - Deposit prepaid balance
GET /api/v1/billing/credits - List credits
POST /api/v1/billing/auto-pay - Configure auto-pay
```

View file

@ -0,0 +1,187 @@
# Phase 12: Economics & Billing
> **Mission**: Build a comprehensive billing infrastructure to monetize Synor's L2 services (Storage, Hosting, Database, Compute) with real-time metering, pricing oracles, and transparent cost management.
---
## Executive Summary
Phase 12 creates the economic backbone for Synor's service ecosystem:
- **Real-time Metering**: Track resource usage across all L2 services
- **Pricing Oracles**: Dynamic SYNOR/USD price feeds for stable pricing
- **Billing Engine**: Usage-based invoicing and payment processing
- **Cost Calculator**: CLI and API tools for cost estimation
- **Revenue Distribution**: Automatic fee distribution to stakeholders
---
## Architecture Overview
```
┌─────────────────────────────────────────────────────────────────────────────┐
│ SYNOR ECONOMICS LAYER │
├─────────────────────────────────────────────────────────────────────────────┤
│ │
│ ┌─────────────────────────────────────────────────────────────────────────┐ │
│ │ USER INTERFACE LAYER │ │
│ ├──────────────┬──────────────┬──────────────┬──────────────┬────────────┤ │
│ │ Billing │ Cost │ Usage │ Payment │ Admin │ │
│ │ Dashboard │ Calculator │ Reports │ Portal │ Console │ │
│ └──────────────┴──────────────┴──────────────┴──────────────┴────────────┘ │
│ │
│ ┌─────────────────────────────────────────────────────────────────────────┐ │
│ │ BILLING ENGINE LAYER │ │
│ ├──────────────┬──────────────┬──────────────┬──────────────┬────────────┤ │
│ │ Invoice │ Payment │ Credit │ Prepaid │ SLA │ │
│ │ Generator │ Processor │ System │ Balance │ Credits │ │
│ └──────────────┴──────────────┴──────────────┴──────────────┴────────────┘ │
│ │
│ ┌─────────────────────────────────────────────────────────────────────────┐ │
│ │ METERING LAYER │ │
│ ├──────────────┬──────────────┬──────────────┬──────────────┬────────────┤ │
│ │ Storage │ Hosting │ Database │ Compute │ Network │ │
│ │ Meter │ Meter │ Meter │ Meter │ Meter │ │
│ └──────────────┴──────────────┴──────────────┴──────────────┴────────────┘ │
│ │
│ ┌─────────────────────────────────────────────────────────────────────────┐ │
│ │ PRICING LAYER │ │
│ ├──────────────┬──────────────┬──────────────┬──────────────┬────────────┤ │
│ │ Price │ Spot │ Reserved │ Discount │ Tiered │ │
│ │ Oracle │ Market │ Pricing │ Engine │ Pricing │ │
│ └──────────────┴──────────────┴──────────────┴──────────────┴────────────┘ │
│ │
│ ┌─────────────────────────────────────────────────────────────────────────┐ │
│ │ SYNOR L1 BLOCKCHAIN (Smart Contracts) │ │
│ └─────────────────────────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────────────────┘
```
---
## Milestones
| Milestone | Description | Progress |
|-----------|-------------|----------|
| 1 | Pricing Oracle | 0% |
| 2 | Metering Service | 0% |
| 3 | Billing Engine | 0% |
---
## Fee Distribution Model
```
Transaction Fees:
├── 10% → Burn (deflationary)
├── 60% → Stakers (rewards)
├── 20% → Community Pool (treasury)
└── 10% → Miners/Validators
L2 Service Fees (Storage, Hosting, Database, Compute):
├── 70% → Node Operators
├── 20% → Protocol Treasury
└── 10% → Burn
```
---
## Service Pricing Summary
### Storage L2
| Resource | Unit | Price (SYNOR) |
|----------|------|---------------|
| Storage | GB/month | 0.02 |
| Retrieval | GB | 0.01 |
| Deal creation | per deal | 0.001 |
### Hosting
| Resource | Unit | Price (SYNOR) |
|----------|------|---------------|
| Bandwidth | GB | 0.05 |
| Custom domain | month | 0.50 |
| SSL certificate | month | FREE |
### Database L2
| Resource | Unit | Price (SYNOR) |
|----------|------|---------------|
| Storage | GB/month | 0.10 |
| Queries | 1M | 0.01 |
| Vector search | 1M | 0.05 |
### Compute L2
| Resource | Unit | Price (SYNOR) |
|----------|------|---------------|
| CPU | core/hour | 0.02 |
| GPU (RTX 4090) | hour | 0.50 |
| Memory | GB/hour | 0.005 |
| Serverless | 1M invocations | 0.20 |
---
## Implementation Timeline
### Week 1-2: Pricing Oracle
- SYNOR/USD price aggregation from DEXes
- Time-weighted average pricing (TWAP)
- Oracle smart contract deployment
### Week 3-4: Metering Service
- Real-time usage tracking for all L2 services
- Event stream processing with Kafka/Redis Streams
- Usage aggregation and storage
### Week 5-6: Billing Engine
- Invoice generation from metered usage
- Payment processing with SYNOR tokens
- Credit system and prepaid balances
### Week 7-8: Cost Calculator & Dashboard
- CLI `synor cost estimate` command
- Web dashboard for usage visualization
- Cost alerts and budget limits
---
## Files to Create
```
crates/synor-economics/
├── Cargo.toml
├── src/
│ ├── lib.rs
│ ├── oracle/
│ │ ├── mod.rs
│ │ ├── price_feed.rs
│ │ └── twap.rs
│ ├── metering/
│ │ ├── mod.rs
│ │ ├── storage.rs
│ │ ├── hosting.rs
│ │ ├── database.rs
│ │ └── compute.rs
│ ├── billing/
│ │ ├── mod.rs
│ │ ├── invoice.rs
│ │ ├── payment.rs
│ │ └── credit.rs
│ ├── pricing/
│ │ ├── mod.rs
│ │ ├── tiers.rs
│ │ └── discounts.rs
│ └── calculator/
│ ├── mod.rs
│ └── estimator.rs
```
---
## Next Steps
1. Create [01-Milestone-01-PricingOracle.md](./01-Milestone-01-PricingOracle.md)
2. Create [01-Milestone-02-MeteringService.md](./01-Milestone-02-MeteringService.md)
3. Create [01-Milestone-03-BillingEngine.md](./01-Milestone-03-BillingEngine.md)
---
*Created: January 11, 2026*