// ACC-XTZH: XTZH原生代币协议 // XTZH是NAC公链的原生资产稳定币,具有双重价值锚定: // 1. 一级锚定:RWA资产或合格跨链资产的价值 // 2. 二级锚定:1.25倍黄金永续合约储备 use serde::{Deserialize, Serialize}; use std::collections::HashMap; /// XTZH代币信息 #[derive(Debug, Clone, Serialize, Deserialize)] pub struct XTZHToken { /// 代币名称 pub name: String, /// 代币符号 pub symbol: String, /// 小数位数 pub decimals: u8, /// 总供应量 pub total_supply: u128, /// 流通供应量 pub circulating_supply: u128, /// 黄金储备覆盖率(GCR,百分比,100表示100%) pub gold_coverage_ratio: u16, /// 最低黄金覆盖率(宪法级参数,需90%超级多数修改) pub min_gold_coverage_ratio: u16, } /// XTZH账户余额 #[derive(Debug, Clone, Serialize, Deserialize)] pub struct XTZHBalance { /// 可用余额 pub available: u128, /// 锁定余额(用于铸造抵押) pub locked: u128, /// 冻结余额(用于清算) pub frozen: u128, } /// XTZH转账记录 #[derive(Debug, Clone, Serialize, Deserialize)] pub struct XTZHTransfer { /// 转账ID pub transfer_id: String, /// 发送方地址 pub from: String, /// 接收方地址 pub to: String, /// 转账金额 pub amount: u128, /// 时间戳 pub timestamp: u64, /// 交易哈希 pub tx_hash: String, } /// XTZH铸造记录 #[derive(Debug, Clone, Serialize, Deserialize)] pub struct XTZHMintRecord { /// 铸造ID pub mint_id: String, /// 资产DNA哈希(RWA资产或跨链资产) pub asset_dna_hash: String, /// 资产类型(RWA或CrossChain) pub asset_type: AssetType, /// 铸造数量 pub amount: u128, /// 所有者DID pub owner_did: String, /// 黄金储备锚定哈希 pub gold_reserve_anchor_hash: String, /// 健康因子(HF,百分比,100表示100%) pub health_factor: u16, /// 铸造时间戳 pub timestamp: u64, /// 状态 pub status: MintStatus, } /// 资产类型 #[derive(Debug, Clone, Serialize, Deserialize, PartialEq)] pub enum AssetType { /// RWA资产 RWA, /// 跨链资产 CrossChain, } /// 铸造状态 #[derive(Debug, Clone, Serialize, Deserialize, PartialEq)] pub enum MintStatus { /// 活跃 Active, /// 预警(HF < 1.1) Warning, /// 清算中(HF < 1.0) Liquidating, /// 已赎回 Redeemed, } /// XTZH协议管理器 #[derive(Debug, Clone)] pub struct XTZHProtocol { /// XTZH代币信息 pub token: XTZHToken, /// 账户余额映射(地址 -> 余额) pub balances: HashMap, /// 铸造记录映射(铸造ID -> 铸造记录) pub mint_records: HashMap, /// 转账记录 pub transfers: Vec, } impl XTZHProtocol { /// 创建新的XTZH协议实例 pub fn new() -> Self { Self { token: XTZHToken { name: "XTZH".to_string(), symbol: "XTZH".to_string(), decimals: 8, total_supply: 0, circulating_supply: 0, gold_coverage_ratio: 125, // 初始125%覆盖率 min_gold_coverage_ratio: 100, // 最低100%覆盖率 }, balances: HashMap::new(), mint_records: HashMap::new(), transfers: Vec::new(), } } /// 获取账户余额 pub fn balance_of(&self, address: &str) -> XTZHBalance { self.balances .get(address) .cloned() .unwrap_or(XTZHBalance { available: 0, locked: 0, frozen: 0, }) } /// 获取账户总余额 pub fn total_balance_of(&self, address: &str) -> u128 { let balance = self.balance_of(address); balance.available + balance.locked + balance.frozen } /// 转账 pub fn transfer( &mut self, from: &str, to: &str, amount: u128, timestamp: u64, ) -> Result { // 检查发送方余额 let from_balance = self.balance_of(from); if from_balance.available < amount { return Err("Insufficient balance".to_string()); } // 扣除发送方余额 let mut new_from_balance = from_balance.clone(); new_from_balance.available -= amount; self.balances.insert(from.to_string(), new_from_balance); // 增加接收方余额 let to_balance = self.balance_of(to); let mut new_to_balance = to_balance.clone(); new_to_balance.available += amount; self.balances.insert(to.to_string(), new_to_balance); // 生成转账ID和交易哈希 let transfer_id = format!("transfer_{}", timestamp); let tx_hash = format!("0x{:x}", timestamp); // 记录转账 let transfer = XTZHTransfer { transfer_id: transfer_id.clone(), from: from.to_string(), to: to.to_string(), amount, timestamp, tx_hash, }; self.transfers.push(transfer); Ok(transfer_id) } /// 铸造XTZH(内部方法,由铸造协议调用) pub fn mint( &mut self, mint_id: &str, asset_dna_hash: &str, asset_type: AssetType, amount: u128, owner_did: &str, gold_reserve_anchor_hash: &str, timestamp: u64, ) -> Result<(), String> { // 检查铸造ID是否已存在 if self.mint_records.contains_key(mint_id) { return Err("Mint ID already exists".to_string()); } // 创建铸造记录 let mint_record = XTZHMintRecord { mint_id: mint_id.to_string(), asset_dna_hash: asset_dna_hash.to_string(), asset_type, amount, owner_did: owner_did.to_string(), gold_reserve_anchor_hash: gold_reserve_anchor_hash.to_string(), health_factor: 150, // 初始健康因子150% timestamp, status: MintStatus::Active, }; // 增加所有者余额 let owner_balance = self.balance_of(owner_did); let mut new_owner_balance = owner_balance.clone(); new_owner_balance.available += amount; self.balances .insert(owner_did.to_string(), new_owner_balance); // 更新总供应量和流通供应量 self.token.total_supply += amount; self.token.circulating_supply += amount; // 记录铸造 self.mint_records .insert(mint_id.to_string(), mint_record); Ok(()) } /// 销毁XTZH(内部方法,由赎回/清算协议调用) pub fn burn(&mut self, address: &str, amount: u128) -> Result<(), String> { // 检查余额 let balance = self.balance_of(address); if balance.available < amount { return Err("Insufficient balance to burn".to_string()); } // 扣除余额 let mut new_balance = balance.clone(); new_balance.available -= amount; self.balances.insert(address.to_string(), new_balance); // 更新总供应量和流通供应量 self.token.total_supply -= amount; self.token.circulating_supply -= amount; Ok(()) } /// 锁定XTZH(用于铸造抵押) pub fn lock(&mut self, address: &str, amount: u128) -> Result<(), String> { let balance = self.balance_of(address); if balance.available < amount { return Err("Insufficient available balance to lock".to_string()); } let mut new_balance = balance.clone(); new_balance.available -= amount; new_balance.locked += amount; self.balances.insert(address.to_string(), new_balance); Ok(()) } /// 解锁XTZH pub fn unlock(&mut self, address: &str, amount: u128) -> Result<(), String> { let balance = self.balance_of(address); if balance.locked < amount { return Err("Insufficient locked balance to unlock".to_string()); } let mut new_balance = balance.clone(); new_balance.locked -= amount; new_balance.available += amount; self.balances.insert(address.to_string(), new_balance); Ok(()) } /// 冻结XTZH(用于清算) pub fn freeze(&mut self, address: &str, amount: u128) -> Result<(), String> { let balance = self.balance_of(address); if balance.available < amount { return Err("Insufficient available balance to freeze".to_string()); } let mut new_balance = balance.clone(); new_balance.available -= amount; new_balance.frozen += amount; self.balances.insert(address.to_string(), new_balance); Ok(()) } /// 解冻XTZH pub fn unfreeze(&mut self, address: &str, amount: u128) -> Result<(), String> { let balance = self.balance_of(address); if balance.frozen < amount { return Err("Insufficient frozen balance to unfreeze".to_string()); } let mut new_balance = balance.clone(); new_balance.frozen -= amount; new_balance.available += amount; self.balances.insert(address.to_string(), new_balance); Ok(()) } /// 更新健康因子 pub fn update_health_factor( &mut self, mint_id: &str, new_health_factor: u16, ) -> Result<(), String> { let mint_record = self .mint_records .get_mut(mint_id) .ok_or("Mint record not found")?; mint_record.health_factor = new_health_factor; // 更新状态 if new_health_factor < 100 { mint_record.status = MintStatus::Liquidating; } else if new_health_factor < 110 { mint_record.status = MintStatus::Warning; } else { mint_record.status = MintStatus::Active; } Ok(()) } /// 更新黄金储备覆盖率 pub fn update_gold_coverage_ratio(&mut self, new_gcr: u16) -> Result<(), String> { if new_gcr < self.token.min_gold_coverage_ratio { return Err(format!( "GCR {} is below minimum {}", new_gcr, self.token.min_gold_coverage_ratio )); } self.token.gold_coverage_ratio = new_gcr; Ok(()) } /// 获取所有预警铸造记录 pub fn get_warning_mints(&self) -> Vec<&XTZHMintRecord> { self.mint_records .values() .filter(|record| record.status == MintStatus::Warning) .collect() } /// 获取所有清算中铸造记录 pub fn get_liquidating_mints(&self) -> Vec<&XTZHMintRecord> { self.mint_records .values() .filter(|record| record.status == MintStatus::Liquidating) .collect() } } #[cfg(test)] mod tests { use super::*; #[test] fn test_xtzh_protocol_creation() { let protocol = XTZHProtocol::new(); assert_eq!(protocol.token.symbol, "XTZH"); assert_eq!(protocol.token.decimals, 8); assert_eq!(protocol.token.total_supply, 0); assert_eq!(protocol.token.gold_coverage_ratio, 125); } #[test] fn test_xtzh_mint() { let mut protocol = XTZHProtocol::new(); let result = protocol.mint( "mint_001", "asset_dna_hash_001", AssetType::RWA, 1000_0000_0000, // 1000 XTZH "owner_did_001", "gold_reserve_anchor_001", 1700000000, ); assert!(result.is_ok()); assert_eq!(protocol.token.total_supply, 1000_0000_0000); assert_eq!(protocol.balance_of("owner_did_001").available, 1000_0000_0000); } #[test] fn test_xtzh_transfer() { let mut protocol = XTZHProtocol::new(); // 先铸造一些XTZH protocol .mint( "mint_001", "asset_dna_hash_001", AssetType::RWA, 1000_0000_0000, "alice", "gold_reserve_anchor_001", 1700000000, ) .expect("mainnet: handle error"); // 转账 let result = protocol.transfer("alice", "bob", 300_0000_0000, 1700000001); assert!(result.is_ok()); assert_eq!(protocol.balance_of("alice").available, 700_0000_0000); assert_eq!(protocol.balance_of("bob").available, 300_0000_0000); } #[test] fn test_xtzh_burn() { let mut protocol = XTZHProtocol::new(); // 先铸造 protocol .mint( "mint_001", "asset_dna_hash_001", AssetType::RWA, 1000_0000_0000, "alice", "gold_reserve_anchor_001", 1700000000, ) .expect("mainnet: handle error"); // 销毁 let result = protocol.burn("alice", 300_0000_0000); assert!(result.is_ok()); assert_eq!(protocol.balance_of("alice").available, 700_0000_0000); assert_eq!(protocol.token.total_supply, 700_0000_0000); } #[test] fn test_xtzh_lock_unlock() { let mut protocol = XTZHProtocol::new(); // 先铸造 protocol .mint( "mint_001", "asset_dna_hash_001", AssetType::RWA, 1000_0000_0000, "alice", "gold_reserve_anchor_001", 1700000000, ) .expect("mainnet: handle error"); // 锁定 protocol.lock("alice", 300_0000_0000).expect("mainnet: handle error"); let balance = protocol.balance_of("alice"); assert_eq!(balance.available, 700_0000_0000); assert_eq!(balance.locked, 300_0000_0000); // 解锁 protocol.unlock("alice", 100_0000_0000).expect("mainnet: handle error"); let balance = protocol.balance_of("alice"); assert_eq!(balance.available, 800_0000_0000); assert_eq!(balance.locked, 200_0000_0000); } #[test] fn test_health_factor_update() { let mut protocol = XTZHProtocol::new(); // 先铸造 protocol .mint( "mint_001", "asset_dna_hash_001", AssetType::RWA, 1000_0000_0000, "alice", "gold_reserve_anchor_001", 1700000000, ) .expect("mainnet: handle error"); // 更新健康因子到预警状态 protocol.update_health_factor("mint_001", 105).expect("mainnet: handle error"); let record = protocol.mint_records.get("mint_001").expect("mainnet: handle error"); assert_eq!(record.health_factor, 105); assert_eq!(record.status, MintStatus::Warning); // 更新健康因子到清算状态 protocol.update_health_factor("mint_001", 95).expect("mainnet: handle error"); let record = protocol.mint_records.get("mint_001").expect("mainnet: handle error"); assert_eq!(record.health_factor, 95); assert_eq!(record.status, MintStatus::Liquidating); } #[test] fn test_gold_coverage_ratio() { let mut protocol = XTZHProtocol::new(); // 更新GCR protocol.update_gold_coverage_ratio(110).expect("mainnet: handle error"); assert_eq!(protocol.token.gold_coverage_ratio, 110); // 尝试设置低于最低值的GCR let result = protocol.update_gold_coverage_ratio(95); assert!(result.is_err()); } }