439 lines
14 KiB
Plaintext
439 lines
14 KiB
Plaintext
// NAC跨链桥主合约
|
||
// 版本: v1.0.0
|
||
// 描述: 实现NAC与外部链(如以太坊)的跨链资产转移
|
||
|
||
module cross_chain_bridge;
|
||
|
||
import "acc20c/wrapped_asset.charter";
|
||
import "xtzh/governance.charter";
|
||
|
||
/// 跨链操作类型
|
||
public enum CrossChainOperation {
|
||
Lock, // 锁定外部链资产
|
||
Unlock, // 解锁外部链资产
|
||
Mint, // 铸造NAC包裹资产
|
||
Burn // 销毁NAC包裹资产
|
||
}
|
||
|
||
/// 跨链请求状态
|
||
public enum RequestStatus {
|
||
Pending, // 待处理
|
||
Verified, // 已验证
|
||
Completed, // 已完成
|
||
Failed, // 失败
|
||
Cancelled // 已取消
|
||
}
|
||
|
||
/// 外部链信息
|
||
public struct ExternalChain {
|
||
chain_id: uint64, // 链ID(1=以太坊主网)
|
||
chain_name: bytes32, // 链名称
|
||
bridge_contract: bytes, // 外部链桥合约地址
|
||
enabled: bool, // 是否启用
|
||
min_confirmations: uint16, // 最小确认数
|
||
max_lock_amount: uint128 // 单次最大锁定金额
|
||
}
|
||
|
||
/// 跨链请求
|
||
public struct CrossChainRequest {
|
||
request_id: bytes32, // 请求ID
|
||
operation: CrossChainOperation, // 操作类型
|
||
source_chain: uint64, // 源链ID
|
||
target_chain: uint64, // 目标链ID
|
||
source_address: bytes, // 源地址
|
||
target_address: [u8; 32], // 目标地址(NAC地址)
|
||
asset_id: bytes32, // 资产ID
|
||
amount: uint128, // 数量
|
||
tx_hash: bytes32, // 原始交易哈希
|
||
proof: bytes, // SPV证明或中继签名
|
||
status: RequestStatus, // 状态
|
||
created_at: uint64, // 创建时间
|
||
completed_at: uint64, // 完成时间
|
||
relay_signatures: []bytes // 中继节点签名
|
||
}
|
||
|
||
/// 包裹资产映射
|
||
public struct AssetMapping {
|
||
external_chain_id: uint64, // 外部链ID
|
||
external_asset_address: bytes, // 外部资产合约地址
|
||
nac_wrapped_asset_id: bytes32, // NAC包裹资产ID
|
||
symbol: bytes32, // 符号
|
||
decimals: uint8, // 小数位数
|
||
total_locked: uint128, // 总锁定量
|
||
total_minted: uint128, // 总铸造量
|
||
enabled: bool // 是否启用
|
||
}
|
||
|
||
/// NAC跨链桥合约
|
||
contract CrossChainBridge {
|
||
storage {
|
||
// 管理员地址
|
||
admin: [u8; 32],
|
||
|
||
// 支持的外部链
|
||
external_chains: map<uint64, ExternalChain>,
|
||
|
||
// 资产映射
|
||
asset_mappings: map<bytes32, AssetMapping>,
|
||
|
||
// 跨链请求
|
||
requests: map<bytes32, CrossChainRequest>,
|
||
|
||
// 中继节点列表
|
||
relay_nodes: []bytes48, // BLS公钥列表
|
||
|
||
// 最小中继签名数
|
||
min_relay_signatures: uint16,
|
||
|
||
// 暂停状态
|
||
paused: bool,
|
||
|
||
// 请求计数器
|
||
request_counter: uint64
|
||
}
|
||
|
||
/// 构造函数
|
||
constructor(
|
||
admin_address: [u8; 32],
|
||
min_signatures: uint16
|
||
) {
|
||
self.admin = admin_address;
|
||
self.min_relay_signatures = min_signatures;
|
||
self.paused = false;
|
||
self.request_counter = 0;
|
||
}
|
||
|
||
/// 添加外部链支持
|
||
pub fn add_external_chain(
|
||
chain_id: uint64,
|
||
chain_name: bytes32,
|
||
bridge_contract: bytes,
|
||
min_confirmations: uint16,
|
||
max_lock_amount: uint128
|
||
) -> bool {
|
||
require(msg.sender == self.admin, "Only admin can add chains");
|
||
require(!self.external_chains.contains(chain_id), "Chain already exists");
|
||
|
||
self.external_chains[chain_id] = ExternalChain {
|
||
chain_id: chain_id,
|
||
chain_name: chain_name,
|
||
bridge_contract: bridge_contract,
|
||
enabled: true,
|
||
min_confirmations: min_confirmations,
|
||
max_lock_amount: max_lock_amount
|
||
};
|
||
|
||
true
|
||
}
|
||
|
||
/// 添加资产映射
|
||
pub fn add_asset_mapping(
|
||
external_chain_id: uint64,
|
||
external_asset_address: bytes,
|
||
nac_wrapped_asset_id: bytes32,
|
||
symbol: bytes32,
|
||
decimals: uint8
|
||
) -> bool {
|
||
require(msg.sender == self.admin, "Only admin can add mappings");
|
||
require(self.external_chains.contains(external_chain_id), "Chain not supported");
|
||
|
||
let mapping_id = self.compute_mapping_id(external_chain_id, external_asset_address);
|
||
|
||
self.asset_mappings[mapping_id] = AssetMapping {
|
||
external_chain_id: external_chain_id,
|
||
external_asset_address: external_asset_address,
|
||
nac_wrapped_asset_id: nac_wrapped_asset_id,
|
||
symbol: symbol,
|
||
decimals: decimals,
|
||
total_locked: 0,
|
||
total_minted: 0,
|
||
enabled: true
|
||
};
|
||
|
||
true
|
||
}
|
||
|
||
/// 提交跨链锁定请求(从外部链到NAC)
|
||
/// 用户在外部链锁定资产后,中继节点调用此函数
|
||
pub fn submit_lock_request(
|
||
source_chain: uint64,
|
||
source_address: bytes,
|
||
target_address: [u8; 32],
|
||
external_asset_address: bytes,
|
||
amount: uint128,
|
||
tx_hash: bytes32,
|
||
proof: bytes,
|
||
relay_signatures: []bytes
|
||
) -> bytes32 {
|
||
require(!self.paused, "Bridge is paused");
|
||
require(self.external_chains.contains(source_chain), "Chain not supported");
|
||
require(relay_signatures.len() >= self.min_relay_signatures as usize, "Insufficient signatures");
|
||
|
||
// 验证中继签名
|
||
require(self.verify_relay_signatures(tx_hash, relay_signatures), "Invalid relay signatures");
|
||
|
||
// 生成请求ID
|
||
self.request_counter += 1;
|
||
let request_id = self.compute_request_id(source_chain, tx_hash, self.request_counter);
|
||
|
||
// 获取资产映射
|
||
let mapping_id = self.compute_mapping_id(source_chain, external_asset_address);
|
||
require(self.asset_mappings.contains(mapping_id), "Asset not supported");
|
||
|
||
let mut mapping = self.asset_mappings[mapping_id];
|
||
require(mapping.enabled, "Asset mapping disabled");
|
||
|
||
// 检查10%限制
|
||
let max_allowed = self.get_max_lockable_amount(mapping.nac_wrapped_asset_id);
|
||
require(mapping.total_locked + amount <= max_allowed, "Exceeds 10% limit");
|
||
|
||
// 创建跨链请求
|
||
self.requests[request_id] = CrossChainRequest {
|
||
request_id: request_id,
|
||
operation: CrossChainOperation::Lock,
|
||
source_chain: source_chain,
|
||
target_chain: 0, // NAC链ID
|
||
source_address: source_address,
|
||
target_address: target_address,
|
||
asset_id: mapping.nac_wrapped_asset_id,
|
||
amount: amount,
|
||
tx_hash: tx_hash,
|
||
proof: proof,
|
||
status: RequestStatus::Verified,
|
||
created_at: block.timestamp,
|
||
completed_at: 0,
|
||
relay_signatures: relay_signatures
|
||
};
|
||
|
||
// 更新锁定量
|
||
mapping.total_locked += amount;
|
||
mapping.total_minted += amount;
|
||
self.asset_mappings[mapping_id] = mapping;
|
||
|
||
// 铸造包裹资产
|
||
self.mint_wrapped_asset(target_address, mapping.nac_wrapped_asset_id, amount);
|
||
|
||
// 更新状态为已完成
|
||
self.requests[request_id].status = RequestStatus::Completed;
|
||
self.requests[request_id].completed_at = block.timestamp;
|
||
|
||
request_id
|
||
}
|
||
|
||
/// 提交跨链解锁请求(从NAC到外部链)
|
||
/// 用户在NAC销毁包裹资产后,请求解锁外部链资产
|
||
pub fn submit_unlock_request(
|
||
target_chain: uint64,
|
||
target_address: bytes,
|
||
nac_wrapped_asset_id: bytes32,
|
||
amount: uint128
|
||
) -> bytes32 {
|
||
require(!self.paused, "Bridge is paused");
|
||
require(self.external_chains.contains(target_chain), "Chain not supported");
|
||
|
||
// 查找资产映射
|
||
let mapping_id = self.find_mapping_by_nac_asset(target_chain, nac_wrapped_asset_id);
|
||
require(mapping_id != bytes32::zero(), "Asset mapping not found");
|
||
|
||
let mut mapping = self.asset_mappings[mapping_id];
|
||
require(mapping.enabled, "Asset mapping disabled");
|
||
require(mapping.total_minted >= amount, "Insufficient minted supply");
|
||
|
||
// 销毁NAC包裹资产
|
||
self.burn_wrapped_asset(msg.sender, nac_wrapped_asset_id, amount);
|
||
|
||
// 生成请求ID
|
||
self.request_counter += 1;
|
||
let request_id = self.compute_request_id(0, bytes32::zero(), self.request_counter);
|
||
|
||
// 创建跨链请求
|
||
self.requests[request_id] = CrossChainRequest {
|
||
request_id: request_id,
|
||
operation: CrossChainOperation::Unlock,
|
||
source_chain: 0, // NAC链ID
|
||
target_chain: target_chain,
|
||
source_address: msg.sender.to_bytes(),
|
||
target_address: [0u8; 32], // 不适用
|
||
asset_id: nac_wrapped_asset_id,
|
||
amount: amount,
|
||
tx_hash: bytes32::zero(),
|
||
proof: target_address, // 目标地址作为proof
|
||
status: RequestStatus::Pending,
|
||
created_at: block.timestamp,
|
||
completed_at: 0,
|
||
relay_signatures: []
|
||
};
|
||
|
||
// 更新铸造量
|
||
mapping.total_minted -= amount;
|
||
self.asset_mappings[mapping_id] = mapping;
|
||
|
||
// 中继节点会监听此事件并在外部链执行解锁
|
||
|
||
request_id
|
||
}
|
||
|
||
/// 验证中继签名
|
||
fn verify_relay_signatures(
|
||
&self,
|
||
message: bytes32,
|
||
signatures: []bytes
|
||
) -> bool {
|
||
let mut valid_count: uint16 = 0;
|
||
|
||
for signature in signatures {
|
||
// 验证BLS签名
|
||
for relay_pubkey in self.relay_nodes {
|
||
if self.verify_bls_signature(message, signature, relay_pubkey) {
|
||
valid_count += 1;
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
|
||
valid_count >= self.min_relay_signatures
|
||
}
|
||
|
||
/// 验证BLS签名(简化版)
|
||
fn verify_bls_signature(
|
||
&self,
|
||
message: bytes32,
|
||
signature: bytes,
|
||
pubkey: bytes48
|
||
) -> bool {
|
||
// TODO: 实际的BLS签名验证
|
||
// 这里需要调用NVM的BLS验证指令
|
||
true
|
||
}
|
||
|
||
/// 计算资产映射ID
|
||
fn compute_mapping_id(
|
||
&self,
|
||
chain_id: uint64,
|
||
asset_address: bytes
|
||
) -> bytes32 {
|
||
// keccak256(chain_id || asset_address)
|
||
let mut data: bytes = [];
|
||
data.extend(chain_id.to_bytes());
|
||
data.extend(asset_address);
|
||
keccak256(data)
|
||
}
|
||
|
||
/// 计算请求ID
|
||
fn compute_request_id(
|
||
&self,
|
||
chain_id: uint64,
|
||
tx_hash: bytes32,
|
||
counter: uint64
|
||
) -> bytes32 {
|
||
// keccak256(chain_id || tx_hash || counter)
|
||
let mut data: bytes = [];
|
||
data.extend(chain_id.to_bytes());
|
||
data.extend(tx_hash.to_bytes());
|
||
data.extend(counter.to_bytes());
|
||
keccak256(data)
|
||
}
|
||
|
||
/// 查找NAC资产对应的映射ID
|
||
fn find_mapping_by_nac_asset(
|
||
&self,
|
||
chain_id: uint64,
|
||
nac_asset_id: bytes32
|
||
) -> bytes32 {
|
||
// 遍历所有映射查找匹配的
|
||
// TODO: 优化为反向索引
|
||
for (mapping_id, mapping) in self.asset_mappings {
|
||
if mapping.external_chain_id == chain_id && mapping.nac_wrapped_asset_id == nac_asset_id {
|
||
return mapping_id;
|
||
}
|
||
}
|
||
bytes32::zero()
|
||
}
|
||
|
||
/// 获取最大可锁定金额(10%限制)
|
||
fn get_max_lockable_amount(&self, nac_asset_id: bytes32) -> uint128 {
|
||
// 获取NAC资产的总供应量
|
||
let total_supply = self.get_asset_total_supply(nac_asset_id);
|
||
|
||
// 返回10%
|
||
total_supply / 10
|
||
}
|
||
|
||
/// 获取资产总供应量
|
||
fn get_asset_total_supply(&self, asset_id: bytes32) -> uint128 {
|
||
// TODO: 调用ACC-20C合约查询总供应量
|
||
1_000_000_000_000 // 占位符
|
||
}
|
||
|
||
/// 铸造包裹资产
|
||
fn mint_wrapped_asset(
|
||
&self,
|
||
to: [u8; 32],
|
||
asset_id: bytes32,
|
||
amount: uint128
|
||
) {
|
||
// TODO: 调用ACC-20C合约铸造
|
||
}
|
||
|
||
/// 销毁包裹资产
|
||
fn burn_wrapped_asset(
|
||
&self,
|
||
from: [u8; 32],
|
||
asset_id: bytes32,
|
||
amount: uint128
|
||
) {
|
||
// TODO: 调用ACC-20C合约销毁
|
||
}
|
||
|
||
/// 查询跨链请求
|
||
pub fn get_request(request_id: bytes32) -> CrossChainRequest {
|
||
require(self.requests.contains(request_id), "Request not found");
|
||
self.requests[request_id]
|
||
}
|
||
|
||
/// 查询资产映射
|
||
pub fn get_asset_mapping(
|
||
chain_id: uint64,
|
||
asset_address: bytes
|
||
) -> AssetMapping {
|
||
let mapping_id = self.compute_mapping_id(chain_id, asset_address);
|
||
require(self.asset_mappings.contains(mapping_id), "Mapping not found");
|
||
self.asset_mappings[mapping_id]
|
||
}
|
||
|
||
/// 暂停桥
|
||
pub fn pause() -> bool {
|
||
require(msg.sender == self.admin, "Only admin can pause");
|
||
self.paused = true;
|
||
true
|
||
}
|
||
|
||
/// 恢复桥
|
||
pub fn unpause() -> bool {
|
||
require(msg.sender == self.admin, "Only admin can unpause");
|
||
self.paused = false;
|
||
true
|
||
}
|
||
|
||
/// 添加中继节点
|
||
pub fn add_relay_node(pubkey: bytes48) -> bool {
|
||
require(msg.sender == self.admin, "Only admin can add relay nodes");
|
||
self.relay_nodes.push(pubkey);
|
||
true
|
||
}
|
||
|
||
/// 移除中继节点
|
||
pub fn remove_relay_node(pubkey: bytes48) -> bool {
|
||
require(msg.sender == self.admin, "Only admin can remove relay nodes");
|
||
|
||
for i in 0..self.relay_nodes.len() {
|
||
if self.relay_nodes[i] == pubkey {
|
||
self.relay_nodes.remove(i);
|
||
return true;
|
||
}
|
||
}
|
||
|
||
false
|
||
}
|
||
}
|