// ACC-721: 唯一资产协议(Non-Fungible Token Protocol) // // NAC原生的唯一资产标准,专为RWA资产设计 // 不是ERC-721的实现,是完全独立的NAC原生协议 use serde::{Deserialize, Serialize}; use std::collections::HashMap; /// ACC-721错误类型 #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] pub enum ACC721Error { /// 资产不存在 TokenNotFound, /// 资产已存在 TokenAlreadyExists, /// 无效的所有者 InvalidOwner, /// 无效的接收地址 InvalidRecipient, /// 未授权操作 Unauthorized, /// 资产已冻结 AssetFrozen, /// 合规检查失败 ComplianceFailed(String), } /// ACC-721资产元数据 #[derive(Debug, Clone, Serialize, Deserialize)] pub struct ACC721Metadata { /// 资产集合名称 pub name: String, /// 资产集合符号 pub symbol: String, /// 基础URI pub base_uri: String, } /// ACC-721资产信息 #[derive(Debug, Clone, Serialize, Deserialize)] pub struct TokenInfo { /// 资产ID pub token_id: String, /// 所有者地址 pub owner: String, /// 资产URI pub token_uri: String, /// 资产DNA(NAC原生) pub asset_dna: Option, /// GNACS分类编码(NAC原生) pub gnacs_code: Option, /// 是否冻结 pub frozen: bool, } /// ACC-721资产状态 #[derive(Debug, Clone, Serialize, Deserialize)] pub struct ACC721State { /// 资产信息映射 (token_id -> TokenInfo) pub tokens: HashMap, /// 所有者资产列表 (owner -> [token_ids]) pub owner_tokens: HashMap>, /// 资产授权映射 (token_id -> approved_address) pub token_approvals: HashMap, /// 操作员授权映射 (owner -> operator -> bool) pub operator_approvals: HashMap>, /// 元数据 pub metadata: ACC721Metadata, } /// ACC-721接口 pub trait ACC721 { /// 获取资产集合名称 fn name(&self) -> String; /// 获取资产集合符号 fn symbol(&self) -> String; /// 获取资产URI fn token_uri(&self, token_id: &str) -> Result; /// 获取资产所有者 fn owner_of(&self, token_id: &str) -> Result; /// 获取账户拥有的资产数量 fn balance_of(&self, owner: &str) -> u64; /// 转移资产 fn transfer_from(&mut self, from: &str, to: &str, token_id: &str) -> Result<(), ACC721Error>; /// 安全转移资产 fn safe_transfer_from( &mut self, from: &str, to: &str, token_id: &str, ) -> Result<(), ACC721Error>; /// 授权资产 fn approve(&mut self, to: &str, token_id: &str) -> Result<(), ACC721Error>; /// 获取资产授权地址 fn get_approved(&self, token_id: &str) -> Result, ACC721Error>; /// 设置操作员授权 fn set_approval_for_all(&mut self, owner: &str, operator: &str, approved: bool) -> Result<(), ACC721Error>; /// 检查操作员授权 fn is_approved_for_all(&self, owner: &str, operator: &str) -> bool; /// 铸造资产 fn mint(&mut self, to: &str, token_id: &str, token_uri: &str) -> Result<(), ACC721Error>; /// 销毁资产 fn burn(&mut self, token_id: &str) -> Result<(), ACC721Error>; /// 冻结资产 fn freeze_token(&mut self, token_id: &str) -> Result<(), ACC721Error>; /// 解冻资产 fn unfreeze_token(&mut self, token_id: &str) -> Result<(), ACC721Error>; /// 检查资产是否冻结 fn is_frozen(&self, token_id: &str) -> bool; } /// ACC-721标准实现 #[derive(Debug, Clone, Serialize, Deserialize)] pub struct ACC721Token { state: ACC721State, } impl ACC721Token { /// 创建新的ACC-721资产集合 pub fn new(metadata: ACC721Metadata) -> Self { Self { state: ACC721State { tokens: HashMap::new(), owner_tokens: HashMap::new(), token_approvals: HashMap::new(), operator_approvals: HashMap::new(), metadata, }, } } /// 获取状态的可变引用 pub fn state_mut(&mut self) -> &mut ACC721State { &mut self.state } /// 获取状态的不可变引用 pub fn state(&self) -> &ACC721State { &self.state } } impl ACC721 for ACC721Token { fn name(&self) -> String { self.state.metadata.name.clone() } fn symbol(&self) -> String { self.state.metadata.symbol.clone() } fn token_uri(&self, token_id: &str) -> Result { self.state .tokens .get(token_id) .map(|info| info.token_uri.clone()) .ok_or(ACC721Error::TokenNotFound) } fn owner_of(&self, token_id: &str) -> Result { self.state .tokens .get(token_id) .map(|info| info.owner.clone()) .ok_or(ACC721Error::TokenNotFound) } fn balance_of(&self, owner: &str) -> u64 { self.state .owner_tokens .get(owner) .map(|tokens| tokens.len() as u64) .unwrap_or(0) } fn transfer_from(&mut self, from: &str, to: &str, token_id: &str) -> Result<(), ACC721Error> { // 检查资产是否存在 let token_info = self.state .tokens .get(token_id) .ok_or(ACC721Error::TokenNotFound)?; // 检查资产是否冻结 if token_info.frozen { return Err(ACC721Error::AssetFrozen); } // 检查所有者 if token_info.owner != from { return Err(ACC721Error::InvalidOwner); } // 更新所有者 self.state .tokens .get_mut(token_id) .unwrap() .owner = to.to_string(); // 更新所有者资产列表 if let Some(from_tokens) = self.state.owner_tokens.get_mut(from) { from_tokens.retain(|id| id != token_id); } self.state .owner_tokens .entry(to.to_string()) .or_insert_with(Vec::new) .push(token_id.to_string()); // 清除授权 self.state.token_approvals.remove(token_id); Ok(()) } fn safe_transfer_from( &mut self, from: &str, to: &str, token_id: &str, ) -> Result<(), ACC721Error> { // 简化实现:与transfer_from相同 // 实际应用中应检查接收地址是否支持ACC-721 self.transfer_from(from, to, token_id) } fn approve(&mut self, to: &str, token_id: &str) -> Result<(), ACC721Error> { // 检查资产是否存在 if !self.state.tokens.contains_key(token_id) { return Err(ACC721Error::TokenNotFound); } // 设置授权 self.state.token_approvals.insert(token_id.to_string(), to.to_string()); Ok(()) } fn get_approved(&self, token_id: &str) -> Result, ACC721Error> { // 检查资产是否存在 if !self.state.tokens.contains_key(token_id) { return Err(ACC721Error::TokenNotFound); } Ok(self.state.token_approvals.get(token_id).cloned()) } fn set_approval_for_all(&mut self, owner: &str, operator: &str, approved: bool) -> Result<(), ACC721Error> { self.state .operator_approvals .entry(owner.to_string()) .or_insert_with(HashMap::new) .insert(operator.to_string(), approved); Ok(()) } fn is_approved_for_all(&self, owner: &str, operator: &str) -> bool { self.state .operator_approvals .get(owner) .and_then(|approvals| approvals.get(operator)) .copied() .unwrap_or(false) } fn mint(&mut self, to: &str, token_id: &str, token_uri: &str) -> Result<(), ACC721Error> { // 检查资产是否已存在 if self.state.tokens.contains_key(token_id) { return Err(ACC721Error::TokenAlreadyExists); } // 创建资产 let token_info = TokenInfo { token_id: token_id.to_string(), owner: to.to_string(), token_uri: token_uri.to_string(), asset_dna: None, gnacs_code: None, frozen: false, }; self.state.tokens.insert(token_id.to_string(), token_info); // 更新所有者资产列表 self.state .owner_tokens .entry(to.to_string()) .or_insert_with(Vec::new) .push(token_id.to_string()); Ok(()) } fn burn(&mut self, token_id: &str) -> Result<(), ACC721Error> { // 检查资产是否存在 let token_info = self.state .tokens .get(token_id) .ok_or(ACC721Error::TokenNotFound)?; let owner = token_info.owner.clone(); // 删除资产 self.state.tokens.remove(token_id); // 更新所有者资产列表 if let Some(owner_tokens) = self.state.owner_tokens.get_mut(&owner) { owner_tokens.retain(|id| id != token_id); } // 清除授权 self.state.token_approvals.remove(token_id); Ok(()) } fn freeze_token(&mut self, token_id: &str) -> Result<(), ACC721Error> { let token_info = self.state .tokens .get_mut(token_id) .ok_or(ACC721Error::TokenNotFound)?; token_info.frozen = true; Ok(()) } fn unfreeze_token(&mut self, token_id: &str) -> Result<(), ACC721Error> { let token_info = self.state .tokens .get_mut(token_id) .ok_or(ACC721Error::TokenNotFound)?; token_info.frozen = false; Ok(()) } fn is_frozen(&self, token_id: &str) -> bool { self.state .tokens .get(token_id) .map(|info| info.frozen) .unwrap_or(false) } } #[cfg(test)] mod tests { use super::*; fn create_test_collection() -> ACC721Token { let metadata = ACC721Metadata { name: "Test Collection".to_string(), symbol: "TEST".to_string(), base_uri: "https://example.com/".to_string(), }; ACC721Token::new(metadata) } #[test] fn test_metadata() { let collection = create_test_collection(); assert_eq!(collection.name(), "Test Collection"); assert_eq!(collection.symbol(), "TEST"); } #[test] fn test_mint_and_owner_of() { let mut collection = create_test_collection(); // 铸造资产 assert!(collection.mint("alice", "1", "https://example.com/1").is_ok()); assert_eq!(collection.owner_of("1").unwrap(), "alice"); assert_eq!(collection.balance_of("alice"), 1); // 重复铸造 assert_eq!( collection.mint("alice", "1", "https://example.com/1"), Err(ACC721Error::TokenAlreadyExists) ); } #[test] fn test_transfer() { let mut collection = create_test_collection(); // 铸造资产 collection.mint("alice", "1", "https://example.com/1").unwrap(); // 转移资产 assert!(collection.transfer_from("alice", "bob", "1").is_ok()); assert_eq!(collection.owner_of("1").unwrap(), "bob"); assert_eq!(collection.balance_of("alice"), 0); assert_eq!(collection.balance_of("bob"), 1); } #[test] fn test_approve() { let mut collection = create_test_collection(); // 铸造资产 collection.mint("alice", "1", "https://example.com/1").unwrap(); // 授权 assert!(collection.approve("bob", "1").is_ok()); assert_eq!(collection.get_approved("1").unwrap(), Some("bob".to_string())); } #[test] fn test_burn() { let mut collection = create_test_collection(); // 铸造资产 collection.mint("alice", "1", "https://example.com/1").unwrap(); // 销毁资产 assert!(collection.burn("1").is_ok()); assert_eq!(collection.owner_of("1"), Err(ACC721Error::TokenNotFound)); assert_eq!(collection.balance_of("alice"), 0); } #[test] fn test_freeze() { let mut collection = create_test_collection(); // 铸造资产 collection.mint("alice", "1", "https://example.com/1").unwrap(); // 冻结资产 assert!(collection.freeze_token("1").is_ok()); assert!(collection.is_frozen("1")); // 冻结资产无法转移 assert_eq!( collection.transfer_from("alice", "bob", "1"), Err(ACC721Error::AssetFrozen) ); // 解冻资产 assert!(collection.unfreeze_token("1").is_ok()); assert!(!collection.is_frozen("1")); // 解冻后可以转移 assert!(collection.transfer_from("alice", "bob", "1").is_ok()); } }