712 lines
19 KiB
Plaintext
712 lines
19 KiB
Plaintext
///! # 资产生命周期管理
|
|
///!
|
|
///! Asset Lifecycle Management
|
|
///! 管理资产从创建到销毁的完整生命周期
|
|
///!
|
|
///! **版本**: v1.0
|
|
///! **模块**: charter-std/asset/lifecycle.ch
|
|
|
|
use asset::gnacs::GNACSCode;
|
|
use sovereignty::rules::SovereigntyType;
|
|
|
|
// ============================================================================
|
|
// 资产状态枚举
|
|
// ============================================================================
|
|
|
|
/// 资产生命周期状态
|
|
///
|
|
/// 定义资产在生命周期中的各个状态
|
|
pub enum AssetLifecycleState {
|
|
/// 草稿(未完成创建)
|
|
Draft,
|
|
|
|
/// 待审核(等待合规审核)
|
|
PendingReview,
|
|
|
|
/// 已激活(正常使用中)
|
|
Active,
|
|
|
|
/// 已暂停(临时暂停使用)
|
|
Suspended,
|
|
|
|
/// 已冻结(被监管冻结)
|
|
Frozen,
|
|
|
|
/// 已过期(超过有效期)
|
|
Expired,
|
|
|
|
/// 已销毁(永久销毁)
|
|
Destroyed
|
|
}
|
|
|
|
// ============================================================================
|
|
// 生命周期事件
|
|
// ============================================================================
|
|
|
|
/// 资产创建事件
|
|
event AssetCreated {
|
|
asset_id: Hash,
|
|
creator: Address,
|
|
gnacs_code: u48,
|
|
timestamp: Timestamp
|
|
}
|
|
|
|
/// 状态变更事件
|
|
event StateChanged {
|
|
asset_id: Hash,
|
|
from_state: AssetLifecycleState,
|
|
to_state: AssetLifecycleState,
|
|
operator: Address,
|
|
reason: String,
|
|
timestamp: Timestamp
|
|
}
|
|
|
|
/// 资产转移事件
|
|
event AssetTransferred {
|
|
asset_id: Hash,
|
|
from: Address,
|
|
to: Address,
|
|
timestamp: Timestamp
|
|
}
|
|
|
|
/// 资产销毁事件
|
|
event AssetDestroyed {
|
|
asset_id: Hash,
|
|
destroyer: Address,
|
|
reason: String,
|
|
timestamp: Timestamp
|
|
}
|
|
|
|
/// 有效期更新事件
|
|
event ValidityUpdated {
|
|
asset_id: Hash,
|
|
new_expiry: Timestamp,
|
|
timestamp: Timestamp
|
|
}
|
|
|
|
// ============================================================================
|
|
// 生命周期记录
|
|
// ============================================================================
|
|
|
|
/// 生命周期记录
|
|
///
|
|
/// 记录资产生命周期中的关键事件
|
|
struct LifecycleRecord {
|
|
/// 事件类型
|
|
event_type: String,
|
|
|
|
/// 旧状态
|
|
old_state: Option<AssetLifecycleState>,
|
|
|
|
/// 新状态
|
|
new_state: AssetLifecycleState,
|
|
|
|
/// 操作员
|
|
operator: Address,
|
|
|
|
/// 原因/备注
|
|
reason: String,
|
|
|
|
/// 时间戳
|
|
timestamp: Timestamp,
|
|
|
|
/// 交易哈希
|
|
transaction_hash: Hash
|
|
}
|
|
|
|
/// 资产生命周期信息
|
|
struct AssetLifecycle {
|
|
/// 资产ID
|
|
asset_id: Hash,
|
|
|
|
/// 当前状态
|
|
current_state: AssetLifecycleState,
|
|
|
|
/// 创建者
|
|
creator: Address,
|
|
|
|
/// 当前所有者
|
|
current_owner: Address,
|
|
|
|
/// 创建时间
|
|
created_at: Timestamp,
|
|
|
|
/// 激活时间
|
|
activated_at: Option<Timestamp>,
|
|
|
|
/// 过期时间
|
|
expires_at: Option<Timestamp>,
|
|
|
|
/// 销毁时间
|
|
destroyed_at: Option<Timestamp>,
|
|
|
|
/// 生命周期记录
|
|
history: Vec<LifecycleRecord>
|
|
}
|
|
|
|
// ============================================================================
|
|
// 资产生命周期管理器
|
|
// ============================================================================
|
|
|
|
/// 资产生命周期管理器
|
|
certificate AssetLifecycleManager {
|
|
/// 生命周期信息存储 (asset_id => lifecycle)
|
|
let _lifecycles: Map<Hash, AssetLifecycle>;
|
|
|
|
/// 管理员地址
|
|
let _admin: Address;
|
|
|
|
/// 审核员地址集合
|
|
let _reviewers: Set<Address>;
|
|
|
|
// ========== 构造函数 ==========
|
|
|
|
constructor() {
|
|
self._admin = msg.sender;
|
|
self._reviewers.insert(msg.sender);
|
|
}
|
|
|
|
// ========== 资产创建 ==========
|
|
|
|
/// 创建资产(草稿状态)
|
|
///
|
|
/// # 参数
|
|
/// - `asset_id`: 资产ID
|
|
/// - `gnacs_code`: GNACS编码
|
|
///
|
|
/// # 返回
|
|
/// - `bool`: 是否成功
|
|
pub fn create_asset(
|
|
asset_id: Hash,
|
|
gnacs_code: u48
|
|
) -> bool {
|
|
require(!asset_id.is_zero(), "Invalid asset ID");
|
|
require(!self._lifecycles.contains_key(asset_id), "Asset already exists");
|
|
|
|
// 验证GNACS编码
|
|
let gnacs = GNACSCode::from_u48(gnacs_code);
|
|
require(gnacs.validate(), "Invalid GNACS code");
|
|
|
|
let lifecycle = AssetLifecycle {
|
|
asset_id: asset_id,
|
|
current_state: AssetLifecycleState::Draft,
|
|
creator: msg.sender,
|
|
current_owner: msg.sender,
|
|
created_at: block.timestamp,
|
|
activated_at: None,
|
|
expires_at: None,
|
|
destroyed_at: None,
|
|
history: vec![
|
|
LifecycleRecord {
|
|
event_type: "Created",
|
|
old_state: None,
|
|
new_state: AssetLifecycleState::Draft,
|
|
operator: msg.sender,
|
|
reason: "Asset created",
|
|
timestamp: block.timestamp,
|
|
transaction_hash: tx.hash
|
|
}
|
|
]
|
|
};
|
|
|
|
self._lifecycles[asset_id] = lifecycle;
|
|
|
|
emit AssetCreated {
|
|
asset_id: asset_id,
|
|
creator: msg.sender,
|
|
gnacs_code: gnacs_code,
|
|
timestamp: block.timestamp
|
|
};
|
|
|
|
return true;
|
|
}
|
|
|
|
/// 提交审核
|
|
///
|
|
/// # 参数
|
|
/// - `asset_id`: 资产ID
|
|
///
|
|
/// # 返回
|
|
/// - `bool`: 是否成功
|
|
pub fn submit_for_review(asset_id: Hash) -> bool {
|
|
require(self._lifecycles.contains_key(asset_id), "Asset not found");
|
|
|
|
let lifecycle = self._lifecycles[asset_id];
|
|
require(lifecycle.creator == msg.sender, "Not the creator");
|
|
require(
|
|
lifecycle.current_state == AssetLifecycleState::Draft,
|
|
"Asset not in draft state"
|
|
);
|
|
|
|
return self._change_state(
|
|
asset_id,
|
|
AssetLifecycleState::PendingReview,
|
|
"Submitted for review"
|
|
);
|
|
}
|
|
|
|
/// 审核通过并激活
|
|
///
|
|
/// # 参数
|
|
/// - `asset_id`: 资产ID
|
|
/// - `expires_at`: 过期时间(可选)
|
|
///
|
|
/// # 返回
|
|
/// - `bool`: 是否成功
|
|
pub fn approve_and_activate(
|
|
asset_id: Hash,
|
|
expires_at: Option<Timestamp>
|
|
) -> bool {
|
|
require(self._reviewers.contains(msg.sender), "Not a reviewer");
|
|
require(self._lifecycles.contains_key(asset_id), "Asset not found");
|
|
|
|
let mut lifecycle = self._lifecycles[asset_id];
|
|
require(
|
|
lifecycle.current_state == AssetLifecycleState::PendingReview,
|
|
"Asset not pending review"
|
|
);
|
|
|
|
// 设置过期时间
|
|
if let Some(expiry) = expires_at {
|
|
require(expiry > block.timestamp, "Invalid expiry time");
|
|
lifecycle.expires_at = Some(expiry);
|
|
}
|
|
|
|
lifecycle.activated_at = Some(block.timestamp);
|
|
self._lifecycles[asset_id] = lifecycle;
|
|
|
|
return self._change_state(
|
|
asset_id,
|
|
AssetLifecycleState::Active,
|
|
"Approved and activated"
|
|
);
|
|
}
|
|
|
|
/// 审核拒绝
|
|
///
|
|
/// # 参数
|
|
/// - `asset_id`: 资产ID
|
|
/// - `reason`: 拒绝原因
|
|
///
|
|
/// # 返回
|
|
/// - `bool`: 是否成功
|
|
pub fn reject(asset_id: Hash, reason: String) -> bool {
|
|
require(self._reviewers.contains(msg.sender), "Not a reviewer");
|
|
require(self._lifecycles.contains_key(asset_id), "Asset not found");
|
|
|
|
let lifecycle = self._lifecycles[asset_id];
|
|
require(
|
|
lifecycle.current_state == AssetLifecycleState::PendingReview,
|
|
"Asset not pending review"
|
|
);
|
|
|
|
return self._change_state(
|
|
asset_id,
|
|
AssetLifecycleState::Draft,
|
|
reason
|
|
);
|
|
}
|
|
|
|
// ========== 状态管理 ==========
|
|
|
|
/// 暂停资产
|
|
///
|
|
/// # 参数
|
|
/// - `asset_id`: 资产ID
|
|
/// - `reason`: 暂停原因
|
|
///
|
|
/// # 返回
|
|
/// - `bool`: 是否成功
|
|
pub fn suspend(asset_id: Hash, reason: String) -> bool {
|
|
require(msg.sender == self._admin, "Only admin can suspend");
|
|
require(self._lifecycles.contains_key(asset_id), "Asset not found");
|
|
|
|
let lifecycle = self._lifecycles[asset_id];
|
|
require(
|
|
lifecycle.current_state == AssetLifecycleState::Active,
|
|
"Asset not active"
|
|
);
|
|
|
|
return self._change_state(
|
|
asset_id,
|
|
AssetLifecycleState::Suspended,
|
|
reason
|
|
);
|
|
}
|
|
|
|
/// 恢复资产
|
|
///
|
|
/// # 参数
|
|
/// - `asset_id`: 资产ID
|
|
/// - `reason`: 恢复原因
|
|
///
|
|
/// # 返回
|
|
/// - `bool`: 是否成功
|
|
pub fn resume(asset_id: Hash, reason: String) -> bool {
|
|
require(msg.sender == self._admin, "Only admin can resume");
|
|
require(self._lifecycles.contains_key(asset_id), "Asset not found");
|
|
|
|
let lifecycle = self._lifecycles[asset_id];
|
|
require(
|
|
lifecycle.current_state == AssetLifecycleState::Suspended,
|
|
"Asset not suspended"
|
|
);
|
|
|
|
return self._change_state(
|
|
asset_id,
|
|
AssetLifecycleState::Active,
|
|
reason
|
|
);
|
|
}
|
|
|
|
/// 冻结资产
|
|
///
|
|
/// # 参数
|
|
/// - `asset_id`: 资产ID
|
|
/// - `reason`: 冻结原因
|
|
///
|
|
/// # 返回
|
|
/// - `bool`: 是否成功
|
|
pub fn freeze(asset_id: Hash, reason: String) -> bool {
|
|
require(msg.sender == self._admin, "Only admin can freeze");
|
|
require(self._lifecycles.contains_key(asset_id), "Asset not found");
|
|
|
|
let lifecycle = self._lifecycles[asset_id];
|
|
require(
|
|
lifecycle.current_state == AssetLifecycleState::Active ||
|
|
lifecycle.current_state == AssetLifecycleState::Suspended,
|
|
"Invalid state for freezing"
|
|
);
|
|
|
|
return self._change_state(
|
|
asset_id,
|
|
AssetLifecycleState::Frozen,
|
|
reason
|
|
);
|
|
}
|
|
|
|
/// 解冻资产
|
|
///
|
|
/// # 参数
|
|
/// - `asset_id`: 资产ID
|
|
/// - `reason`: 解冻原因
|
|
///
|
|
/// # 返回
|
|
/// - `bool`: 是否成功
|
|
pub fn unfreeze(asset_id: Hash, reason: String) -> bool {
|
|
require(msg.sender == self._admin, "Only admin can unfreeze");
|
|
require(self._lifecycles.contains_key(asset_id), "Asset not found");
|
|
|
|
let lifecycle = self._lifecycles[asset_id];
|
|
require(
|
|
lifecycle.current_state == AssetLifecycleState::Frozen,
|
|
"Asset not frozen"
|
|
);
|
|
|
|
return self._change_state(
|
|
asset_id,
|
|
AssetLifecycleState::Active,
|
|
reason
|
|
);
|
|
}
|
|
|
|
/// 标记为过期
|
|
///
|
|
/// # 参数
|
|
/// - `asset_id`: 资产ID
|
|
///
|
|
/// # 返回
|
|
/// - `bool`: 是否成功
|
|
pub fn mark_expired(asset_id: Hash) -> bool {
|
|
require(self._lifecycles.contains_key(asset_id), "Asset not found");
|
|
|
|
let lifecycle = self._lifecycles[asset_id];
|
|
|
|
// 检查是否有过期时间
|
|
if let Some(expiry) = lifecycle.expires_at {
|
|
require(block.timestamp >= expiry, "Asset not yet expired");
|
|
} else {
|
|
require(false, "Asset has no expiry time");
|
|
}
|
|
|
|
require(
|
|
lifecycle.current_state == AssetLifecycleState::Active,
|
|
"Asset not active"
|
|
);
|
|
|
|
return self._change_state(
|
|
asset_id,
|
|
AssetLifecycleState::Expired,
|
|
"Asset expired"
|
|
);
|
|
}
|
|
|
|
// ========== 资产转移 ==========
|
|
|
|
/// 转移资产所有权
|
|
///
|
|
/// # 参数
|
|
/// - `asset_id`: 资产ID
|
|
/// - `new_owner`: 新所有者
|
|
///
|
|
/// # 返回
|
|
/// - `bool`: 是否成功
|
|
pub fn transfer_ownership(asset_id: Hash, new_owner: Address) -> bool {
|
|
require(self._lifecycles.contains_key(asset_id), "Asset not found");
|
|
require(!new_owner.is_zero(), "Invalid new owner");
|
|
|
|
let mut lifecycle = self._lifecycles[asset_id];
|
|
require(lifecycle.current_owner == msg.sender, "Not the owner");
|
|
require(
|
|
lifecycle.current_state == AssetLifecycleState::Active,
|
|
"Asset not active"
|
|
);
|
|
|
|
let old_owner = lifecycle.current_owner;
|
|
lifecycle.current_owner = new_owner;
|
|
|
|
// 添加历史记录
|
|
lifecycle.history.push(LifecycleRecord {
|
|
event_type: "Transferred",
|
|
old_state: Some(lifecycle.current_state),
|
|
new_state: lifecycle.current_state,
|
|
operator: msg.sender,
|
|
reason: format!("Transferred from {} to {}", old_owner, new_owner),
|
|
timestamp: block.timestamp,
|
|
transaction_hash: tx.hash
|
|
});
|
|
|
|
self._lifecycles[asset_id] = lifecycle;
|
|
|
|
emit AssetTransferred {
|
|
asset_id: asset_id,
|
|
from: old_owner,
|
|
to: new_owner,
|
|
timestamp: block.timestamp
|
|
};
|
|
|
|
return true;
|
|
}
|
|
|
|
// ========== 资产销毁 ==========
|
|
|
|
/// 销毁资产
|
|
///
|
|
/// # 参数
|
|
/// - `asset_id`: 资产ID
|
|
/// - `reason`: 销毁原因
|
|
///
|
|
/// # 返回
|
|
/// - `bool`: 是否成功
|
|
pub fn destroy(asset_id: Hash, reason: String) -> bool {
|
|
require(self._lifecycles.contains_key(asset_id), "Asset not found");
|
|
|
|
let mut lifecycle = self._lifecycles[asset_id];
|
|
require(
|
|
lifecycle.current_owner == msg.sender || msg.sender == self._admin,
|
|
"Not owner or admin"
|
|
);
|
|
|
|
lifecycle.destroyed_at = Some(block.timestamp);
|
|
self._lifecycles[asset_id] = lifecycle;
|
|
|
|
let result = self._change_state(
|
|
asset_id,
|
|
AssetLifecycleState::Destroyed,
|
|
reason.clone()
|
|
);
|
|
|
|
emit AssetDestroyed {
|
|
asset_id: asset_id,
|
|
destroyer: msg.sender,
|
|
reason: reason,
|
|
timestamp: block.timestamp
|
|
};
|
|
|
|
return result;
|
|
}
|
|
|
|
// ========== 有效期管理 ==========
|
|
|
|
/// 更新有效期
|
|
///
|
|
/// # 参数
|
|
/// - `asset_id`: 资产ID
|
|
/// - `new_expiry`: 新的过期时间
|
|
///
|
|
/// # 返回
|
|
/// - `bool`: 是否成功
|
|
pub fn update_expiry(asset_id: Hash, new_expiry: Timestamp) -> bool {
|
|
require(msg.sender == self._admin, "Only admin can update expiry");
|
|
require(self._lifecycles.contains_key(asset_id), "Asset not found");
|
|
require(new_expiry > block.timestamp, "Invalid expiry time");
|
|
|
|
let mut lifecycle = self._lifecycles[asset_id];
|
|
lifecycle.expires_at = Some(new_expiry);
|
|
|
|
// 如果资产已过期,可以恢复为激活状态
|
|
if lifecycle.current_state == AssetLifecycleState::Expired {
|
|
lifecycle.current_state = AssetLifecycleState::Active;
|
|
}
|
|
|
|
self._lifecycles[asset_id] = lifecycle;
|
|
|
|
emit ValidityUpdated {
|
|
asset_id: asset_id,
|
|
new_expiry: new_expiry,
|
|
timestamp: block.timestamp
|
|
};
|
|
|
|
return true;
|
|
}
|
|
|
|
// ========== 查询函数 ==========
|
|
|
|
/// 获取生命周期信息
|
|
///
|
|
/// # 参数
|
|
/// - `asset_id`: 资产ID
|
|
///
|
|
/// # 返回
|
|
/// - `AssetLifecycle`: 生命周期信息
|
|
pub fn get_lifecycle(asset_id: Hash) -> AssetLifecycle {
|
|
require(self._lifecycles.contains_key(asset_id), "Asset not found");
|
|
return self._lifecycles[asset_id];
|
|
}
|
|
|
|
/// 获取当前状态
|
|
///
|
|
/// # 参数
|
|
/// - `asset_id`: 资产ID
|
|
///
|
|
/// # 返回
|
|
/// - `AssetLifecycleState`: 当前状态
|
|
pub fn get_state(asset_id: Hash) -> AssetLifecycleState {
|
|
require(self._lifecycles.contains_key(asset_id), "Asset not found");
|
|
return self._lifecycles[asset_id].current_state;
|
|
}
|
|
|
|
/// 检查是否可用
|
|
///
|
|
/// # 参数
|
|
/// - `asset_id`: 资产ID
|
|
///
|
|
/// # 返回
|
|
/// - `bool`: 是否可用
|
|
pub fn is_active(asset_id: Hash) -> bool {
|
|
if !self._lifecycles.contains_key(asset_id) {
|
|
return false;
|
|
}
|
|
|
|
let lifecycle = self._lifecycles[asset_id];
|
|
|
|
// 检查状态
|
|
if lifecycle.current_state != AssetLifecycleState::Active {
|
|
return false;
|
|
}
|
|
|
|
// 检查是否过期
|
|
if let Some(expiry) = lifecycle.expires_at {
|
|
if block.timestamp >= expiry {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
/// 获取历史记录
|
|
///
|
|
/// # 参数
|
|
/// - `asset_id`: 资产ID
|
|
///
|
|
/// # 返回
|
|
/// - `Vec<LifecycleRecord>`: 历史记录
|
|
pub fn get_history(asset_id: Hash) -> Vec<LifecycleRecord> {
|
|
require(self._lifecycles.contains_key(asset_id), "Asset not found");
|
|
return self._lifecycles[asset_id].history;
|
|
}
|
|
|
|
// ========== 内部函数 ==========
|
|
|
|
/// 内部状态变更函数
|
|
fn _change_state(
|
|
asset_id: Hash,
|
|
new_state: AssetLifecycleState,
|
|
reason: String
|
|
) -> bool {
|
|
let mut lifecycle = self._lifecycles[asset_id];
|
|
let old_state = lifecycle.current_state;
|
|
|
|
lifecycle.current_state = new_state;
|
|
|
|
// 添加历史记录
|
|
lifecycle.history.push(LifecycleRecord {
|
|
event_type: "StateChanged",
|
|
old_state: Some(old_state),
|
|
new_state: new_state,
|
|
operator: msg.sender,
|
|
reason: reason.clone(),
|
|
timestamp: block.timestamp,
|
|
transaction_hash: tx.hash
|
|
});
|
|
|
|
self._lifecycles[asset_id] = lifecycle;
|
|
|
|
emit StateChanged {
|
|
asset_id: asset_id,
|
|
from_state: old_state,
|
|
to_state: new_state,
|
|
operator: msg.sender,
|
|
reason: reason,
|
|
timestamp: block.timestamp
|
|
};
|
|
|
|
return true;
|
|
}
|
|
|
|
// ========== 管理函数 ==========
|
|
|
|
/// 添加审核员
|
|
///
|
|
/// # 参数
|
|
/// - `reviewer`: 审核员地址
|
|
///
|
|
/// # 返回
|
|
/// - `bool`: 是否成功
|
|
pub fn add_reviewer(reviewer: Address) -> bool {
|
|
require(msg.sender == self._admin, "Only admin");
|
|
require(!reviewer.is_zero(), "Invalid reviewer");
|
|
|
|
self._reviewers.insert(reviewer);
|
|
|
|
return true;
|
|
}
|
|
|
|
/// 移除审核员
|
|
///
|
|
/// # 参数
|
|
/// - `reviewer`: 审核员地址
|
|
///
|
|
/// # 返回
|
|
/// - `bool`: 是否成功
|
|
pub fn remove_reviewer(reviewer: Address) -> bool {
|
|
require(msg.sender == self._admin, "Only admin");
|
|
|
|
self._reviewers.remove(reviewer);
|
|
|
|
return true;
|
|
}
|
|
|
|
/// 检查是否为审核员
|
|
///
|
|
/// # 参数
|
|
/// - `reviewer`: 审核员地址
|
|
///
|
|
/// # 返回
|
|
/// - `bool`: 是否为审核员
|
|
pub fn is_reviewer(reviewer: Address) -> bool {
|
|
return self._reviewers.contains(reviewer);
|
|
}
|
|
}
|