208 lines
6.5 KiB
Plaintext
208 lines
6.5 KiB
Plaintext
# 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;
|
||
}
|