NAC_Blockchain/charter-std/acc/acc20c_wrapper.ch

208 lines
6.5 KiB
Plaintext
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-20C 兼容层协议 - 包装器核心合约
# 版本: 1.0
# 路径: charter-std/acc/acc20c_wrapper.ch
# --- 核心原则 ---
# 1. 状态容器: 本合约仅作为状态容器,不包含任何主动的合规检查逻辑。
# 2. 宪法驱动: 所有关键操作wrap, unwrap, transfer都假定已通过 CEE 的宪法审查并获得了有效的宪法收据CR
# 3. 原生实现: 完全使用 Charter 语言原生特性。
# --- 标准库与接口导入 ---
import std::types::{ Address, Uint256, Uint64, Bool, String }
import std::collections::{ mapping }
import std::events::{ emit }
# 导入 ACC-20 标准接口,用于与底层资产交互
# 注意:此处的 IAcc20 接口需要在 charter-std 中有明确定义
import charter-std::acc::i_acc20::{ IAcc20 }
# --- 合约状态定义 ---
state {
# 包装后资产的详细信息
# mapping: wrapper_token_id -> WrappedAsset
wrapped_assets: mapping(Uint256 => WrappedAsset),
# 从原始 ACC-20 资产到包装后资产的映射
# mapping: acc20_contract_address -> (acc20_token_id -> wrapper_token_id)
acc20_to_wrapper: mapping(Address => mapping(Uint256 => Uint256)),
# 下一个可用的包装 Token ID
next_wrapper_token_id: Uint256,
# 合约管理员
admin: Address,
}
# --- 数据结构定义 ---
# 包装资产的状态枚举
enum WrappedStatus {
ACTIVE, # 活跃,可交易
FROZEN, # 冻结,由管理员操作,不可交易
PENDING_UNWRAP, # 等待解包中
}
# 包装后资产的核心数据结构
struct WrappedAsset {
acc20_deed_address: Address, # 原始 ACC-20 权证合约地址
acc20_deed_token_id: Uint256, # 原始 ACC-20 权证代币 ID
owner: Address, # 当前包装后资产的所有者
status: WrappedStatus, # 当前状态
wrapped_at: Uint64, # 包装时间戳
unlock_timestamp: Uint64, # 解包冷却期截止时间
}
# --- 事件定义 ---
# 资产被成功包装事件
event AssetWrapped {
wrapper_token_id: Uint256,
acc20_contract: Address,
acc20_token_id: Uint256,
owner: Address,
}
# 资产被成功解包事件
event AssetUnwrapped {
wrapper_token_id: Uint256,
owner: Address,
}
# 包装后资产所有权转移事件
event Transfer {
from: Address,
to: Address,
wrapper_token_id: Uint256,
}
# --- 合约初始化 ---
fn constructor() {
state.next_wrapper_token_id = 1;
state.admin = msg.sender;
}
# --- 核心功能函数 ---
# @dev 包装一个 ACC-20 资产
# @param acc20_contract 原始 ACC-20 合约地址
# @param acc20_token_id 原始 ACC-20 代币 ID
# @returns 新铸造的包装资产 ID
fn wrap(acc20_contract: Address, acc20_token_id: Uint256) -> Uint256 {
# 前置检查:确保该资产未被包装
require(state.acc20_to_wrapper[acc20_contract][acc20_token_id] == 0, "Asset already wrapped");
# [核心交互] 将底层 ACC-20 资产的所有权安全转移到本合约
# 此操作依赖于 ACC-20 标准接口的 `safe_transfer_from`
let acc20 = IAcc20(acc20_contract);
acc20.safe_transfer_from(msg.sender, self.address, acc20_token_id);
# 分配新的包装资产 ID
let wrapper_id = state.next_wrapper_token_id;
state.next_wrapper_token_id += 1;
# 创建并存储新的包装资产记录
let new_asset = WrappedAsset {
acc20_deed_address: acc20_contract,
acc20_deed_token_id: acc20_token_id,
owner: msg.sender,
status: WrappedStatus::ACTIVE,
wrapped_at: block.timestamp,
# 设置 24 小时解包冷却期
unlock_timestamp: block.timestamp + 86400,
};
state.wrapped_assets[wrapper_id] = new_asset;
# 记录双向映射关系
state.acc20_to_wrapper[acc20_contract][acc20_token_id] = wrapper_id;
# 触发事件
emit AssetWrapped {
wrapper_token_id: wrapper_id,
acc20_contract: acc20_contract,
acc20_token_id: acc20_token_id,
owner: msg.sender,
};
return wrapper_id;
}
# @dev 解包一个已包装的资产
# @param wrapper_token_id 要解包的资产 ID
fn unwrap(wrapper_token_id: Uint256) {
let asset = state.wrapped_assets[wrapper_token_id];
# 前置检查
require(asset.owner == msg.sender, "Caller is not the owner");
require(asset.status == WrappedStatus::ACTIVE, "Asset is not active");
require(block.timestamp >= asset.unlock_timestamp, "Unlock period has not passed");
# [核心交互] 将底层 ACC-20 资产归还给所有者
let acc20 = IAcc20(asset.acc20_deed_address);
acc20.safe_transfer_from(self.address, msg.sender, asset.acc20_deed_token_id);
# 清理存储
delete state.acc20_to_wrapper[asset.acc20_deed_address][asset.acc20_deed_token_id];
delete state.wrapped_assets[wrapper_token_id];
# 触发事件
emit AssetUnwrapped {
wrapper_token_id: wrapper_token_id,
owner: msg.sender,
};
}
# @dev 转移一个包装后资产的所有权
# @param to 接收方地址
# @param wrapper_token_id 被转移的资产 ID
fn transfer(to: Address, wrapper_token_id: Uint256) {
require(to != Address(0), "Transfer to zero address is not allowed");
let asset = state.wrapped_assets[wrapper_token_id];
# 前置检查
require(asset.owner == msg.sender, "Caller is not the owner");
require(asset.status == WrappedStatus::ACTIVE, "Asset is not active");
# 更新所有者
let from = asset.owner;
state.wrapped_assets[wrapper_token_id].owner = to;
# 触发事件
emit Transfer {
from: from,
to: to,
wrapper_token_id: wrapper_token_id,
};
}
# --- 视图函数 ---
# @dev 查询包装后资产的详情
fn get_wrapped_asset(wrapper_token_id: Uint256) -> WrappedAsset {
return state.wrapped_assets[wrapper_token_id];
}
# @dev 查询包装后资产的所有者
fn owner_of(wrapper_token_id: Uint256) -> Address {
return state.wrapped_assets[wrapper_token_id].owner;
}
# @dev 查询原始 ACC-20 资产对应的包装 ID
fn get_wrapper_id(acc20_contract: Address, acc20_token_id: Uint256) -> Uint256 {
return state.acc20_to_wrapper[acc20_contract][acc20_token_id];
}
# --- 管理员函数 ---
# @dev 冻结指定的包装资产
fn freeze_asset(wrapper_token_id: Uint256) {
require(msg.sender == state.admin, "Only admin can freeze");
state.wrapped_assets[wrapper_token_id].status = WrappedStatus::FROZEN;
}
# @dev 解冻指定的包装资产
fn unfreeze_asset(wrapper_token_id: Uint256) {
require(msg.sender == state.admin, "Only admin can unfreeze");
state.wrapped_assets[wrapper_token_id].status = WrappedStatus::ACTIVE;
}