//! acc_reserve - NAC 原生协议实现 //! 从 acc_remaining_protocols.rs 提取 use crate::primitives::{Address, Hash, Timestamp}; use serde::{Deserialize, Serialize}; use std::collections::HashMap; #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] pub enum ACCReserveError { ReserveNotFound(String), InsufficientReserve { asset: String, available: u128, requested: u128 }, InvalidConstitutionalReceipt, Unauthorized(Address), ReserveRatioViolation { required: u8, actual: u8 }, } impl std::fmt::Display for ACCReserveError { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { Self::ReserveNotFound(s) => write!(f, "储备资产不存在: {}", s), Self::InsufficientReserve { asset, available, requested } => write!(f, "储备不足 {}: 可用 {},请求 {}", asset, available, requested), Self::InvalidConstitutionalReceipt => write!(f, "宪法收据无效"), Self::Unauthorized(a) => write!(f, "未授权: {}", a.to_hex()), Self::ReserveRatioViolation { required, actual } => write!(f, "储备率违规: 要求 {}%,实际 {}%", required, actual), } } } #[derive(Debug, Clone, Serialize, Deserialize)] pub struct ReserveEntry { pub asset_symbol: String, pub amount: u128, pub custodian: Address, pub last_audited: Timestamp, pub audit_hash: Hash, } #[derive(Debug, Clone, Serialize, Deserialize)] pub enum ReserveProtocolEvent { ReserveDeposited { asset: String, amount: u128, custodian: Address, timestamp: Timestamp }, ReserveWithdrawn { asset: String, amount: u128, recipient: Address, constitutional_receipt: Hash, timestamp: Timestamp }, ReserveAudited { asset: String, audit_hash: Hash, timestamp: Timestamp }, } /// ACC-Reserve 储备协议 /// UID: nac.acc.ACCReserveProtocol.v1 #[derive(Debug, Clone, Serialize, Deserialize)] pub struct ACCReserveProtocol { pub protocol_uid: String, pub lens_protocol_vector: String, pub reserves: HashMap, /// 最低储备率(百分比) pub min_reserve_ratio: u8, pub pending_events: Vec, pub created_at: Timestamp, pub updated_at: Timestamp, } impl ACCReserveProtocol { pub fn new(min_reserve_ratio: u8) -> Self { Self { protocol_uid: "nac.acc.ACCReserveProtocol.v1".to_string(), lens_protocol_vector: "ACC-Reserve".to_string(), reserves: HashMap::new(), min_reserve_ratio, pending_events: Vec::new(), created_at: Timestamp::now(), updated_at: Timestamp::now(), } } pub fn deposit( &mut self, asset_symbol: String, amount: u128, custodian: Address, constitutional_receipt: Hash, timestamp: Timestamp, ) -> Result<(), ACCReserveError> { if constitutional_receipt.is_zero() { return Err(ACCReserveError::InvalidConstitutionalReceipt); } let entry = self.reserves.entry(asset_symbol.clone()).or_insert(ReserveEntry { asset_symbol: asset_symbol.clone(), amount: 0, custodian: custodian.clone(), last_audited: timestamp.clone(), audit_hash: Hash::zero(), }); entry.amount = entry.amount.saturating_add(amount); entry.custodian = custodian.clone(); self.pending_events.push(ReserveProtocolEvent::ReserveDeposited { asset: asset_symbol, amount, custodian, timestamp }); self.updated_at = Timestamp::now(); Ok(()) } pub fn withdraw( &mut self, asset_symbol: String, amount: u128, recipient: Address, constitutional_receipt: Hash, timestamp: Timestamp, ) -> Result<(), ACCReserveError> { if constitutional_receipt.is_zero() { return Err(ACCReserveError::InvalidConstitutionalReceipt); } let entry = self.reserves.get_mut(&asset_symbol) .ok_or_else(|| ACCReserveError::ReserveNotFound(asset_symbol.clone()))?; if entry.amount < amount { return Err(ACCReserveError::InsufficientReserve { asset: asset_symbol.clone(), available: entry.amount, requested: amount }); } entry.amount -= amount; self.pending_events.push(ReserveProtocolEvent::ReserveWithdrawn { asset: asset_symbol, amount, recipient, constitutional_receipt, timestamp }); self.updated_at = Timestamp::now(); Ok(()) } pub fn audit( &mut self, asset_symbol: String, audit_hash: Hash, timestamp: Timestamp, ) -> Result<(), ACCReserveError> { let entry = self.reserves.get_mut(&asset_symbol) .ok_or_else(|| ACCReserveError::ReserveNotFound(asset_symbol.clone()))?; entry.last_audited = timestamp.clone(); entry.audit_hash = audit_hash; self.pending_events.push(ReserveProtocolEvent::ReserveAudited { asset: asset_symbol, audit_hash, timestamp }); Ok(()) } pub fn get_reserve(&self, asset: &str) -> Option<&ReserveEntry> { self.reserves.get(asset) } pub fn total_reserve_count(&self) -> usize { self.reserves.len() } pub fn drain_pending_events(&mut self) -> Vec { std::mem::take(&mut self.pending_events) } }