// ACC-20 Enhanced: 增强版ACC-20协议 // 集成GNACS资产分类和宪法层合规检查 // // 这是ACC-20的完整实现,包含所有NAC原生特性 use super::acc20::{ACC20, ACC20Error, ACC20Metadata, ACC20Token}; use nac_udm::primitives::{Address, Hash}; use serde::{Deserialize, Serialize}; use std::collections::HashMap; // 从nvm-l1导入GNACS类型 // 注意:这需要在Cargo.toml中添加依赖 // 为了编译通过,这里先用占位类型 type GNACSCode = u64; type JurisdictionId = u32; /// ACC-20增强元数据 #[derive(Debug, Clone, Serialize, Deserialize)] pub struct ACC20EnhancedMetadata { /// 基础元数据 pub base: ACC20Metadata, /// GNACS分类编码 pub gnacs_code: GNACSCode, /// 适用的司法辖区 pub jurisdictions: Vec, /// 资产DNA (NAC原生唯一标识) pub asset_dna: Hash, /// 发行者地址 pub issuer: Address, /// 合规官地址 pub compliance_officer: Option
, /// 是否需要KYC pub requires_kyc: bool, /// 是否需要AML检查 pub requires_aml: bool, /// 最小持有量 pub min_holding: u128, /// 最大持有量 pub max_holding: Option, /// 转账冷却期 (秒) pub transfer_cooldown: u64, /// 创建时间 pub created_at: u64, } /// 账户合规状态 #[derive(Debug, Clone, Serialize, Deserialize)] pub struct AccountComplianceStatus { /// 是否通过KYC pub kyc_verified: bool, /// 是否通过AML pub aml_verified: bool, /// 合规等级 (0-5) pub compliance_level: u8, /// 白名单状态 pub whitelisted: bool, /// 黑名单状态 pub blacklisted: bool, /// 最后验证时间 pub last_verified_at: u64, } impl Default for AccountComplianceStatus { fn default() -> Self { Self { kyc_verified: false, aml_verified: false, compliance_level: 0, whitelisted: false, blacklisted: false, last_verified_at: 0, } } } /// 转账记录 #[derive(Debug, Clone, Serialize, Deserialize)] pub struct TransferRecord { /// 转账ID pub id: Hash, /// 发送方 pub from: Address, /// 接收方 pub to: Address, /// 金额 pub amount: u128, /// 时间戳 pub timestamp: u64, /// 合规检查结果 pub compliance_passed: bool, } /// ACC-20增强状态 #[derive(Debug, Clone, Serialize, Deserialize)] pub struct ACC20EnhancedState { /// 基础ACC-20状态 pub base_token: ACC20Token, /// 增强元数据 pub metadata: ACC20EnhancedMetadata, /// 账户合规状态 pub compliance_status: HashMap, /// 账户最后转账时间 pub last_transfer_time: HashMap, /// 转账历史 pub transfer_history: Vec, /// 角色权限 (地址 -> 角色列表) pub roles: HashMap>, } /// 角色类型 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)] pub enum Role { /// 管理员 Admin, /// 发行者 Issuer, /// 合规官 ComplianceOfficer, /// 铸造者 Minter, /// 销毁者 Burner, /// 冻结者 Freezer, } /// ACC-20增强接口 pub trait ACC20Enhanced: ACC20 { /// 获取GNACS编码 fn gnacs_code(&self) -> GNACSCode; /// 获取适用的司法辖区 fn jurisdictions(&self) -> Vec; /// 获取资产DNA fn asset_dna(&self) -> Hash; /// 检查账户合规状态 fn check_compliance(&self, account: Address) -> Result<(), ACC20Error>; /// 更新账户合规状态 fn update_compliance_status( &mut self, account: Address, status: AccountComplianceStatus, ) -> Result<(), ACC20Error>; /// 添加到白名单 fn add_to_whitelist(&mut self, account: Address) -> Result<(), ACC20Error>; /// 从白名单移除 fn remove_from_whitelist(&mut self, account: Address) -> Result<(), ACC20Error>; /// 添加到黑名单 fn add_to_blacklist(&mut self, account: Address) -> Result<(), ACC20Error>; /// 从黑名单移除 fn remove_from_blacklist(&mut self, account: Address) -> Result<(), ACC20Error>; /// 检查转账是否符合冷却期要求 fn check_transfer_cooldown(&self, account: Address) -> Result<(), ACC20Error>; /// 检查持有量限制 fn check_holding_limits(&self, account: Address, new_balance: u128) -> Result<(), ACC20Error>; /// 获取转账历史 fn get_transfer_history(&self, account: Option
) -> Vec; /// 授予角色 fn grant_role(&mut self, account: Address, role: Role) -> Result<(), ACC20Error>; /// 撤销角色 fn revoke_role(&mut self, account: Address, role: Role) -> Result<(), ACC20Error>; /// 检查是否有角色 fn has_role(&self, account: Address, role: Role) -> bool; } /// ACC-20增强实现 #[derive(Debug, Clone, Serialize, Deserialize)] pub struct ACC20EnhancedToken { state: ACC20EnhancedState, } impl ACC20EnhancedToken { /// 创建新的增强ACC-20资产 pub fn new(metadata: ACC20EnhancedMetadata) -> Self { let base_token = ACC20Token::new(metadata.base.clone()); let mut roles = HashMap::new(); // 发行者自动获得所有角色 roles.insert( metadata.issuer, vec![ Role::Admin, Role::Issuer, Role::Minter, Role::Burner, Role::Freezer, ], ); // 合规官获得合规官角色 if let Some(compliance_officer) = metadata.compliance_officer { roles.insert(compliance_officer, vec![Role::ComplianceOfficer]); } Self { state: ACC20EnhancedState { base_token, metadata, compliance_status: HashMap::new(), last_transfer_time: HashMap::new(), transfer_history: Vec::new(), roles, }, } } /// 获取状态 pub fn state(&self) -> &ACC20EnhancedState { &self.state } /// 获取可变状态 pub fn state_mut(&mut self) -> &mut ACC20EnhancedState { &mut self.state } /// 执行完整的合规检查 fn perform_compliance_check(&self, account: Address) -> Result<(), ACC20Error> { let status = self .state .compliance_status .get(&account) .cloned() .unwrap_or_default(); // 检查黑名单 if status.blacklisted { return Err(ACC20Error::ComplianceFailed("账户在黑名单中".to_string())); } // 检查KYC要求 if self.state.metadata.requires_kyc && !status.kyc_verified { return Err(ACC20Error::ComplianceFailed("需要完成KYC验证".to_string())); } // 检查AML要求 if self.state.metadata.requires_aml && !status.aml_verified { return Err(ACC20Error::ComplianceFailed("需要完成AML检查".to_string())); } // 检查合规等级 if status.compliance_level < 1 { return Err(ACC20Error::ComplianceFailed("合规等级不足".to_string())); } Ok(()) } /// 记录转账 fn record_transfer(&mut self, from: Address, to: Address, amount: u128, timestamp: u64) { let record = TransferRecord { id: Hash::default(), // 应该生成实际的哈希 from, to, amount, timestamp, compliance_passed: true, }; self.state.transfer_history.push(record); self.state.last_transfer_time.insert(from, timestamp); } } impl ACC20 for ACC20EnhancedToken { fn name(&self) -> String { self.state.base_token.name() } fn symbol(&self) -> String { self.state.base_token.symbol() } fn decimals(&self) -> u8 { self.state.base_token.decimals() } fn total_supply(&self) -> u128 { self.state.base_token.total_supply() } fn balance_of(&self, account: &str) -> u128 { self.state.base_token.balance_of(account) } fn transfer(&mut self, from: &str, to: &str, amount: u128) -> Result<(), ACC20Error> { // 转换为Address类型进行合规检查 let from_addr = Address::zero(); // 应该解析from字符串 let to_addr = Address::zero(); // 应该解析to字符串 // 执行合规检查 self.perform_compliance_check(from_addr)?; self.perform_compliance_check(to_addr)?; // 检查转账冷却期 self.check_transfer_cooldown(from_addr)?; // 计算新余额并检查持有量限制 let new_to_balance = self.balance_of(to) + amount; self.check_holding_limits(to_addr, new_to_balance)?; // 执行基础转账 self.state.base_token.transfer(from, to, amount)?; // 记录转账 self.record_transfer(from_addr, to_addr, amount, 0); // 应该使用实际时间戳 Ok(()) } fn approve(&mut self, owner: &str, spender: &str, amount: u128) -> Result<(), ACC20Error> { self.state.base_token.approve(owner, spender, amount) } fn allowance(&self, owner: &str, spender: &str) -> u128 { self.state.base_token.allowance(owner, spender) } fn transfer_from( &mut self, spender: &str, from: &str, to: &str, amount: u128, ) -> Result<(), ACC20Error> { // 执行合规检查 let from_addr = Address::zero(); let to_addr = Address::zero(); self.perform_compliance_check(from_addr)?; self.perform_compliance_check(to_addr)?; self.check_transfer_cooldown(from_addr)?; let new_to_balance = self.balance_of(to) + amount; self.check_holding_limits(to_addr, new_to_balance)?; // 执行基础转账 self.state.base_token.transfer_from(spender, from, to, amount)?; // 记录转账 self.record_transfer(from_addr, to_addr, amount, 0); Ok(()) } fn mint(&mut self, to: &str, amount: u128) -> Result<(), ACC20Error> { // 检查铸造权限 let issuer = self.state.metadata.issuer; if !self.has_role(issuer, Role::Minter) { return Err(ACC20Error::Unauthorized); } self.state.base_token.mint(to, amount) } fn burn(&mut self, from: &str, amount: u128) -> Result<(), ACC20Error> { // 检查销毁权限 let issuer = self.state.metadata.issuer; if !self.has_role(issuer, Role::Burner) { return Err(ACC20Error::Unauthorized); } self.state.base_token.burn(from, amount) } fn freeze_account(&mut self, account: &str) -> Result<(), ACC20Error> { // 检查冻结权限 let issuer = self.state.metadata.issuer; if !self.has_role(issuer, Role::Freezer) { return Err(ACC20Error::Unauthorized); } self.state.base_token.freeze_account(account) } fn unfreeze_account(&mut self, account: &str) -> Result<(), ACC20Error> { // 检查冻结权限 let issuer = self.state.metadata.issuer; if !self.has_role(issuer, Role::Freezer) { return Err(ACC20Error::Unauthorized); } self.state.base_token.unfreeze_account(account) } fn is_frozen(&self, account: &str) -> bool { self.state.base_token.is_frozen(account) } } impl ACC20Enhanced for ACC20EnhancedToken { fn gnacs_code(&self) -> GNACSCode { self.state.metadata.gnacs_code } fn jurisdictions(&self) -> Vec { self.state.metadata.jurisdictions.clone() } fn asset_dna(&self) -> Hash { self.state.metadata.asset_dna } fn check_compliance(&self, account: Address) -> Result<(), ACC20Error> { self.perform_compliance_check(account) } fn update_compliance_status( &mut self, account: Address, status: AccountComplianceStatus, ) -> Result<(), ACC20Error> { // 检查权限 let issuer = self.state.metadata.issuer; if !self.has_role(issuer, Role::ComplianceOfficer) && !self.has_role(issuer, Role::Admin) { return Err(ACC20Error::Unauthorized); } self.state.compliance_status.insert(account, status); Ok(()) } fn add_to_whitelist(&mut self, account: Address) -> Result<(), ACC20Error> { let status = self .state .compliance_status .entry(account) .or_insert_with(AccountComplianceStatus::default); status.whitelisted = true; Ok(()) } fn remove_from_whitelist(&mut self, account: Address) -> Result<(), ACC20Error> { if let Some(status) = self.state.compliance_status.get_mut(&account) { status.whitelisted = false; } Ok(()) } fn add_to_blacklist(&mut self, account: Address) -> Result<(), ACC20Error> { let status = self .state .compliance_status .entry(account) .or_insert_with(AccountComplianceStatus::default); status.blacklisted = true; Ok(()) } fn remove_from_blacklist(&mut self, account: Address) -> Result<(), ACC20Error> { if let Some(status) = self.state.compliance_status.get_mut(&account) { status.blacklisted = false; } Ok(()) } fn check_transfer_cooldown(&self, account: Address) -> Result<(), ACC20Error> { if let Some(&last_time) = self.state.last_transfer_time.get(&account) { let current_time = 0; // 应该使用实际时间戳 let cooldown = self.state.metadata.transfer_cooldown; if current_time - last_time < cooldown { return Err(ACC20Error::ComplianceFailed(format!( "转账冷却期未满,还需等待{}秒", cooldown - (current_time - last_time) ))); } } Ok(()) } fn check_holding_limits(&self, _account: Address, new_balance: u128) -> Result<(), ACC20Error> { // 检查最小持有量 if new_balance > 0 && new_balance < self.state.metadata.min_holding { return Err(ACC20Error::ComplianceFailed(format!( "持有量低于最小要求: {} < {}", new_balance, self.state.metadata.min_holding ))); } // 检查最大持有量 if let Some(max_holding) = self.state.metadata.max_holding { if new_balance > max_holding { return Err(ACC20Error::ComplianceFailed(format!( "持有量超过最大限制: {} > {}", new_balance, max_holding ))); } } Ok(()) } fn get_transfer_history(&self, account: Option
) -> Vec { if let Some(addr) = account { self.state .transfer_history .iter() .filter(|r| r.from == addr || r.to == addr) .cloned() .collect() } else { self.state.transfer_history.clone() } } fn grant_role(&mut self, account: Address, role: Role) -> Result<(), ACC20Error> { // 检查管理员权限 let issuer = self.state.metadata.issuer; if !self.has_role(issuer, Role::Admin) { return Err(ACC20Error::Unauthorized); } self.state .roles .entry(account) .or_insert_with(Vec::new) .push(role); Ok(()) } fn revoke_role(&mut self, account: Address, role: Role) -> Result<(), ACC20Error> { // 检查管理员权限 let issuer = self.state.metadata.issuer; if !self.has_role(issuer, Role::Admin) { return Err(ACC20Error::Unauthorized); } if let Some(roles) = self.state.roles.get_mut(&account) { roles.retain(|r| *r != role); } Ok(()) } fn has_role(&self, account: Address, role: Role) -> bool { self.state .roles .get(&account) .map(|roles| roles.contains(&role)) .unwrap_or(false) } } #[cfg(test)] mod tests { use super::*; fn create_test_enhanced_token() -> ACC20EnhancedToken { let base_metadata = ACC20Metadata { name: "Enhanced Test Token".to_string(), symbol: "ETT".to_string(), decimals: 18, total_supply: 1000000, asset_dna: None, gnacs_code: None, mintable: true, burnable: true, }; let metadata = ACC20EnhancedMetadata { base: base_metadata, gnacs_code: 0x010100000101, jurisdictions: vec![1, 2], asset_dna: Hash::default(), issuer: Address::zero(), compliance_officer: None, requires_kyc: true, requires_aml: true, min_holding: 100, max_holding: Some(1000000), transfer_cooldown: 60, created_at: 0, }; ACC20EnhancedToken::new(metadata) } #[test] fn test_enhanced_metadata() { let token = create_test_enhanced_token(); assert_eq!(token.name(), "Enhanced Test Token"); assert_eq!(token.gnacs_code(), 0x010100000101); assert_eq!(token.jurisdictions().len(), 2); } #[test] fn test_compliance_check() { let token = create_test_enhanced_token(); let account = Address::zero(); // 未验证的账户应该失败 assert!(token.check_compliance(account).is_err()); } #[test] fn test_whitelist_blacklist() { let mut token = create_test_enhanced_token(); let account = Address::zero(); // 添加到白名单 assert!(token.add_to_whitelist(account).is_ok()); let status = token.state.compliance_status.get(&account).expect("mainnet: handle error"); assert!(status.whitelisted); // 添加到黑名单 assert!(token.add_to_blacklist(account).is_ok()); let status = token.state.compliance_status.get(&account).expect("mainnet: handle error"); assert!(status.blacklisted); // 黑名单账户无法通过合规检查 assert!(token.check_compliance(account).is_err()); } #[test] fn test_role_management() { let mut token = create_test_enhanced_token(); let account = Address::from([1; 20]); let issuer = token.state.metadata.issuer; // 发行者应该有管理员角色 assert!(token.has_role(issuer, Role::Admin)); // 授予角色 assert!(token.grant_role(account, Role::Minter).is_ok()); assert!(token.has_role(account, Role::Minter)); // 撤销角色 assert!(token.revoke_role(account, Role::Minter).is_ok()); assert!(!token.has_role(account, Role::Minter)); } #[test] fn test_holding_limits() { let token = create_test_enhanced_token(); let account = Address::zero(); // 低于最小持有量 assert!(token.check_holding_limits(account, 50).is_err()); // 在范围内 assert!(token.check_holding_limits(account, 500).is_ok()); // 超过最大持有量 assert!(token.check_holding_limits(account, 2000000).is_err()); } #[test] fn test_transfer_history() { let token = create_test_enhanced_token(); // 初始应该没有历史记录 assert_eq!(token.get_transfer_history(None).len(), 0); } }