NAC_Blockchain/_archive/acc20_v1_backup.rs

165 lines
4.5 KiB
Rust
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//! 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<Address, u128>,
/// 授权映射 (owner -> spender -> amount)
pub allowances: HashMap<Address, HashMap<Address, u128>>,
/// 创建时间
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);
}
}