// ACC-Redemption: 资产赎回协议(Redemption Protocol) // // NAC原生的资产赎回标准,用于资产退出机制 // 100% NAC原生协议,不是任何现有标准的实现 use serde::{Deserialize, Serialize}; use std::collections::HashMap; /// 赎回状态 #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] pub enum RedemptionStatus { /// 待审核 Pending, /// 已批准 Approved, /// 处理中 Processing, /// 已完成 Completed, /// 已拒绝 Rejected, /// 已取消 Cancelled, } /// 赎回类型 #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] pub enum RedemptionType { /// 全额赎回 Full, /// 部分赎回 Partial, /// 提前赎回 Early, /// 到期赎回 Maturity, } /// 赎回请求 #[derive(Debug, Clone, Serialize, Deserialize)] pub struct RedemptionRequest { /// 赎回ID pub redemption_id: String, /// 资产ID pub asset_id: String, /// 赎回人地址 pub redeemer: String, /// 赎回类型 pub redemption_type: RedemptionType, /// 赎回数量 pub amount: u128, /// 赎回价格(USD,以分为单位) pub redemption_price: u128, /// 赎回状态 pub status: RedemptionStatus, /// 请求时间 pub requested_at: u64, /// 批准时间 pub approved_at: Option, /// 完成时间 pub completed_at: Option, /// 预期完成时间 pub expected_completion: u64, /// 提前赎回费率(基点,如100表示1%) pub early_redemption_fee: Option, /// 实际费用 pub actual_fee: Option, /// 审核备注 pub notes: Vec, } /// 赎回错误类型 #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] pub enum RedemptionError { /// 赎回请求不存在 RequestNotFound, /// 赎回请求已存在 RequestAlreadyExists, /// 资产不存在 AssetNotFound, /// 赎回金额不足 InsufficientAmount, /// 赎回已完成 AlreadyCompleted, /// 赎回已取消 AlreadyCancelled, /// 未授权操作 Unauthorized, /// 赎回窗口未开放 RedemptionWindowClosed, /// 提前赎回费用过高 EarlyRedemptionFeeTooHigh, } /// 赎回状态 #[derive(Debug, Clone, Serialize, Deserialize)] pub struct RedemptionState { /// 赎回请求映射 (redemption_id -> RedemptionRequest) pub redemptions: HashMap, /// 资产赎回历史 (asset_id -> [redemption_ids]) pub asset_redemptions: HashMap>, /// 赎回人赎回列表 (redeemer -> [redemption_ids]) pub redeemer_redemptions: HashMap>, } /// ACC-Redemption接口 pub trait ACCRedemption { /// 提交赎回请求 fn submit_redemption(&mut self, request: RedemptionRequest) -> Result<(), RedemptionError>; /// 获取赎回请求 fn get_redemption(&self, redemption_id: &str) -> Result; /// 获取资产的赎回历史 fn get_asset_redemptions(&self, asset_id: &str) -> Vec; /// 批准赎回请求 fn approve_redemption(&mut self, redemption_id: &str) -> Result<(), RedemptionError>; /// 拒绝赎回请求 fn reject_redemption( &mut self, redemption_id: &str, reason: String, ) -> Result<(), RedemptionError>; /// 开始处理赎回 fn process_redemption(&mut self, redemption_id: &str) -> Result<(), RedemptionError>; /// 完成赎回 fn complete_redemption(&mut self, redemption_id: &str) -> Result<(), RedemptionError>; /// 取消赎回请求 fn cancel_redemption(&mut self, redemption_id: &str) -> Result<(), RedemptionError>; /// 计算赎回费用 fn calculate_redemption_fee(&self, redemption_id: &str) -> Result; /// 更新赎回状态 fn update_status( &mut self, redemption_id: &str, status: RedemptionStatus, ) -> Result<(), RedemptionError>; /// 获取赎回人的赎回列表 fn get_redeemer_redemptions(&self, redeemer: &str) -> Vec; /// 添加审核备注 fn add_note(&mut self, redemption_id: &str, note: String) -> Result<(), RedemptionError>; /// 获取待处理的赎回请求 fn get_pending_redemptions(&self) -> Vec; } /// ACC-Redemption标准实现 #[derive(Debug, Clone, Serialize, Deserialize)] pub struct RedemptionToken { state: RedemptionState, } impl RedemptionToken { /// 创建新的赎回管理器 pub fn new() -> Self { Self { state: RedemptionState { redemptions: HashMap::new(), asset_redemptions: HashMap::new(), redeemer_redemptions: HashMap::new(), }, } } /// 获取状态的可变引用 pub fn state_mut(&mut self) -> &mut RedemptionState { &mut self.state } /// 获取状态的不可变引用 pub fn state(&self) -> &RedemptionState { &self.state } /// 验证赎回请求 fn validate_request(&self, request: &RedemptionRequest) -> Result<(), RedemptionError> { // 检查赎回金额 if request.amount == 0 { return Err(RedemptionError::InsufficientAmount); } // 检查赎回价格 if request.redemption_price == 0 { return Err(RedemptionError::InsufficientAmount); } Ok(()) } } impl Default for RedemptionToken { fn default() -> Self { Self::new() } } impl ACCRedemption for RedemptionToken { fn submit_redemption(&mut self, mut request: RedemptionRequest) -> Result<(), RedemptionError> { // 检查赎回请求是否已存在 if self.state.redemptions.contains_key(&request.redemption_id) { return Err(RedemptionError::RequestAlreadyExists); } // 验证赎回请求 self.validate_request(&request)?; let now = std::time::SystemTime::now() .duration_since(std::time::UNIX_EPOCH) .unwrap() .as_secs(); request.requested_at = now; request.status = RedemptionStatus::Pending; // 计算提前赎回费用 if request.redemption_type == RedemptionType::Early { if let Some(fee_rate) = request.early_redemption_fee { let fee = request.amount * fee_rate as u128 / 10000; request.actual_fee = Some(fee); } } let redemption_id = request.redemption_id.clone(); let asset_id = request.asset_id.clone(); let redeemer = request.redeemer.clone(); // 保存赎回请求 self.state .redemptions .insert(redemption_id.clone(), request); // 更新资产赎回历史 self.state .asset_redemptions .entry(asset_id) .or_insert_with(Vec::new) .push(redemption_id.clone()); // 更新赎回人赎回列表 self.state .redeemer_redemptions .entry(redeemer) .or_insert_with(Vec::new) .push(redemption_id); Ok(()) } fn get_redemption(&self, redemption_id: &str) -> Result { self.state .redemptions .get(redemption_id) .cloned() .ok_or(RedemptionError::RequestNotFound) } fn get_asset_redemptions(&self, asset_id: &str) -> Vec { self.state .asset_redemptions .get(asset_id) .map(|redemption_ids| { redemption_ids .iter() .filter_map(|id| self.state.redemptions.get(id).cloned()) .collect() }) .unwrap_or_default() } fn approve_redemption(&mut self, redemption_id: &str) -> Result<(), RedemptionError> { let mut request = self.get_redemption(redemption_id)?; if request.status != RedemptionStatus::Pending { return Err(RedemptionError::AlreadyCompleted); } let now = std::time::SystemTime::now() .duration_since(std::time::UNIX_EPOCH) .unwrap() .as_secs(); request.status = RedemptionStatus::Approved; request.approved_at = Some(now); self.state .redemptions .insert(redemption_id.to_string(), request); Ok(()) } fn reject_redemption( &mut self, redemption_id: &str, reason: String, ) -> Result<(), RedemptionError> { let mut request = self.get_redemption(redemption_id)?; if request.status != RedemptionStatus::Pending { return Err(RedemptionError::AlreadyCompleted); } request.status = RedemptionStatus::Rejected; request.notes.push(format!("Rejected: {}", reason)); self.state .redemptions .insert(redemption_id.to_string(), request); Ok(()) } fn process_redemption(&mut self, redemption_id: &str) -> Result<(), RedemptionError> { let mut request = self.get_redemption(redemption_id)?; if request.status != RedemptionStatus::Approved { return Err(RedemptionError::Unauthorized); } request.status = RedemptionStatus::Processing; self.state .redemptions .insert(redemption_id.to_string(), request); Ok(()) } fn complete_redemption(&mut self, redemption_id: &str) -> Result<(), RedemptionError> { let mut request = self.get_redemption(redemption_id)?; if request.status != RedemptionStatus::Processing { return Err(RedemptionError::Unauthorized); } let now = std::time::SystemTime::now() .duration_since(std::time::UNIX_EPOCH) .unwrap() .as_secs(); request.status = RedemptionStatus::Completed; request.completed_at = Some(now); self.state .redemptions .insert(redemption_id.to_string(), request); Ok(()) } fn cancel_redemption(&mut self, redemption_id: &str) -> Result<(), RedemptionError> { let mut request = self.get_redemption(redemption_id)?; if request.status == RedemptionStatus::Completed { return Err(RedemptionError::AlreadyCompleted); } if request.status == RedemptionStatus::Cancelled { return Err(RedemptionError::AlreadyCancelled); } request.status = RedemptionStatus::Cancelled; self.state .redemptions .insert(redemption_id.to_string(), request); Ok(()) } fn calculate_redemption_fee(&self, redemption_id: &str) -> Result { let request = self.get_redemption(redemption_id)?; if let Some(fee) = request.actual_fee { Ok(fee) } else { Ok(0) } } fn update_status( &mut self, redemption_id: &str, status: RedemptionStatus, ) -> Result<(), RedemptionError> { let mut request = self.get_redemption(redemption_id)?; request.status = status; self.state .redemptions .insert(redemption_id.to_string(), request); Ok(()) } fn get_redeemer_redemptions(&self, redeemer: &str) -> Vec { self.state .redeemer_redemptions .get(redeemer) .map(|redemption_ids| { redemption_ids .iter() .filter_map(|id| self.state.redemptions.get(id).cloned()) .collect() }) .unwrap_or_default() } fn add_note(&mut self, redemption_id: &str, note: String) -> Result<(), RedemptionError> { let mut request = self.get_redemption(redemption_id)?; request.notes.push(note); self.state .redemptions .insert(redemption_id.to_string(), request); Ok(()) } fn get_pending_redemptions(&self) -> Vec { self.state .redemptions .values() .filter(|request| request.status == RedemptionStatus::Pending) .cloned() .collect() } } #[cfg(test)] mod tests { use super::*; fn create_test_request() -> RedemptionRequest { RedemptionRequest { redemption_id: "RED-001".to_string(), asset_id: "RWA-001".to_string(), redeemer: "alice".to_string(), redemption_type: RedemptionType::Full, amount: 1000000, redemption_price: 1000000_00, status: RedemptionStatus::Pending, requested_at: 0, approved_at: None, completed_at: None, expected_completion: 1234567890 + 86400 * 7, early_redemption_fee: None, actual_fee: None, notes: Vec::new(), } } #[test] fn test_submit_redemption() { let mut redemption = RedemptionToken::new(); let request = create_test_request(); assert!(redemption.submit_redemption(request).is_ok()); } #[test] fn test_approve_redemption() { let mut redemption = RedemptionToken::new(); let request = create_test_request(); redemption.submit_redemption(request).unwrap(); assert!(redemption.approve_redemption("RED-001").is_ok()); assert_eq!( redemption.get_redemption("RED-001").unwrap().status, RedemptionStatus::Approved ); } #[test] fn test_complete_redemption() { let mut redemption = RedemptionToken::new(); let request = create_test_request(); redemption.submit_redemption(request).unwrap(); redemption.approve_redemption("RED-001").unwrap(); redemption.process_redemption("RED-001").unwrap(); assert!(redemption.complete_redemption("RED-001").is_ok()); assert_eq!( redemption.get_redemption("RED-001").unwrap().status, RedemptionStatus::Completed ); } #[test] fn test_early_redemption_fee() { let mut redemption = RedemptionToken::new(); let mut request = create_test_request(); request.redemption_type = RedemptionType::Early; request.early_redemption_fee = Some(100); // 1% redemption.submit_redemption(request).unwrap(); let fee = redemption.calculate_redemption_fee("RED-001").unwrap(); assert_eq!(fee, 10000); // 1% of 1000000 } #[test] fn test_cancel_redemption() { let mut redemption = RedemptionToken::new(); let request = create_test_request(); redemption.submit_redemption(request).unwrap(); assert!(redemption.cancel_redemption("RED-001").is_ok()); assert_eq!( redemption.get_redemption("RED-001").unwrap().status, RedemptionStatus::Cancelled ); } }