NAC_Blockchain/nvm_v2/acc-protocol/src/acc721.rs

464 lines
13 KiB
Rust
Raw 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-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,
/// 资产DNANAC原生
pub asset_dna: Option<String>,
/// GNACS分类编码NAC原生
pub gnacs_code: Option<String>,
/// 是否冻结
pub frozen: bool,
}
/// ACC-721资产状态
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ACC721State {
/// 资产信息映射 (token_id -> TokenInfo)
pub tokens: HashMap<String, TokenInfo>,
/// 所有者资产列表 (owner -> [token_ids])
pub owner_tokens: HashMap<String, Vec<String>>,
/// 资产授权映射 (token_id -> approved_address)
pub token_approvals: HashMap<String, String>,
/// 操作员授权映射 (owner -> operator -> bool)
pub operator_approvals: HashMap<String, HashMap<String, bool>>,
/// 元数据
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<String, ACC721Error>;
/// 获取资产所有者
fn owner_of(&self, token_id: &str) -> Result<String, ACC721Error>;
/// 获取账户拥有的资产数量
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<Option<String>, 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<String, ACC721Error> {
self.state
.tokens
.get(token_id)
.map(|info| info.token_uri.clone())
.ok_or(ACC721Error::TokenNotFound)
}
fn owner_of(&self, token_id: &str) -> Result<String, ACC721Error> {
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<Option<String>, 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());
}
}