//! ACC协议模块 ///! # ACC-20: 可替代代币标准 ///! ///! UID: nac.acc.ACC20.v1 ///! ///! ACC-20是NAC的可替代代币标准,完全替代以太坊的ERC-20。 #[allow(unused_imports)] use crate::primitives::{Address, Hash, Timestamp}; use serde::{Deserialize, Serialize}; use std::collections::HashMap; /// ACC-20代币 /// /// UID: nac.acc.ACC20.v1 #[derive(Debug, Clone, Serialize, Deserialize)] /// ACC20Token pub struct ACC20Token { /// 代币名称 pub name: String, /// 代币符号 pub symbol: String, /// 小数位数 pub decimals: u8, /// 总供应量 pub total_supply: u128, /// 合约地址 pub contract_address: Address, /// 余额映射 pub balances: HashMap
, /// 授权映射 (owner -> spender -> amount) pub allowances: HashMap>, /// 创建时间 pub created_at: Timestamp, } impl ACC20Token { /// 创建新的ACC-20代币 pub fn new(name: String, symbol: String, decimals: u8, total_supply: u128) -> Self { Self { name, symbol, decimals, total_supply, contract_address: Address::zero(), balances: HashMap::new(), allowances: HashMap::new(), created_at: Timestamp::now(), } } /// 获取余额 pub fn balance_of(&self, owner: &Address) -> u128 { *self.balances.get(owner).unwrap_or(&0) } /// 转账 pub fn transfer(&mut self, from: &Address, to: &Address, amount: u128) -> Result<(), String> { let from_balance = self.balance_of(from); if from_balance < amount { return Err("Insufficient balance".to_string()); } self.balances.insert(*from, from_balance - amount); let to_balance = self.balance_of(to); self.balances.insert(*to, to_balance + amount); Ok(()) } /// 授权 pub fn approve(&mut self, owner: &Address, spender: &Address, amount: u128) { self.allowances .entry(*owner) .or_insert_with(HashMap::new) .insert(*spender, amount); } /// 获取授权额度 pub fn allowance(&self, owner: &Address, spender: &Address) -> u128 { self.allowances .get(owner) .and_then(|spenders| spenders.get(spender)) .copied() .unwrap_or(0) } /// 从授权额度转账 pub fn transfer_from( &mut self, spender: &Address, from: &Address, to: &Address, amount: u128, ) -> Result<(), String> { let allowed = self.allowance(from, spender); if allowed < amount { return Err("Insufficient allowance".to_string()); } self.transfer(from, to, amount)?; self.approve(from, spender, allowed - amount); Ok(()) } /// 铸造代币 pub fn mint(&mut self, to: &Address, amount: u128) -> Result<(), String> { let balance = self.balance_of(to); self.balances.insert(*to, balance + amount); self.total_supply += amount; Ok(()) } /// 销毁代币 pub fn burn(&mut self, from: &Address, amount: u128) -> Result<(), String> { let balance = self.balance_of(from); if balance < amount { return Err("Insufficient balance to burn".to_string()); } self.balances.insert(*from, balance - amount); self.total_supply -= amount; Ok(()) } } #[cfg(test)] mod tests { use super::*; #[test] fn test_acc20_creation() { let token = ACC20Token::new("Test Token".to_string(), "TEST".to_string(), 18, 1_000_000); assert_eq!(token.name, "Test Token"); assert_eq!(token.symbol, "TEST"); assert_eq!(token.decimals, 18); assert_eq!(token.total_supply, 1_000_000); } #[test] fn test_acc20_transfer() { let mut token = ACC20Token::new("Test".to_string(), "TST".to_string(), 18, 1_000_000); let addr1 = Address::new([1u8; 32]); let addr2 = Address::new([2u8; 32]); token.mint(&addr1, 1000).expect("mainnet: handle error"); assert_eq!(token.balance_of(&addr1), 1000); token.transfer(&addr1, &addr2, 500).expect("mainnet: handle error"); assert_eq!(token.balance_of(&addr1), 500); assert_eq!(token.balance_of(&addr2), 500); } }