治理与未来 阶段五 ✅ 验证通过
// contracts/SimpleBridge.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/utils/cryptography/ECDSA.sol";
import "@openzeppelin/contracts/utils/cryptography/MessageHashUtils.sol";
/**
* @title SimpleBridge
* @dev 简化版Lock-Mint跨链桥(2-of-3多签验证)
*
* 流程:
* 1. 用户在链A锁定代币
* 2. 验证者确认锁定事件
* 3. 验证者在链B签名确认
* 4. 用户在链B提交签名,铸造wrapped代币
*/
contract SimpleBridge is Ownable {
using SafeERC20 for IERC20;
using ECDSA for bytes32;
using MessageHashUtils for bytes32;
uint256 public constant REQUIRED_SIGNATURES = 2;
uint256 public feeBps; // 手续费基点
IERC20 public immutable token;
mapping(address => bool) public validators;
mapping(bytes32 => bool) public processedDeposits;
mapping(bytes32 => bool) public processedWithdrawals;
event Deposited(bytes32 indexed depositId, address sender, uint256 amount, uint256 targetChain);
event Minted(bytes32 indexed depositId, address recipient, uint256 amount);
event BurnRequested(bytes32 indexed withdrawId, address sender, uint256 amount, uint256 targetChain);
event Withdrawn(bytes32 indexed withdrawId, address recipient, uint256 amount);
constructor(address _token, uint256 _feeBps) Ownable(msg.sender) {
token = IERC20(_token);
feeBps = _feeBps;
}
// ═══════ 锁定(链A:存款) ═══════
function deposit(uint256 amount, uint256 targetChain) external {
require(amount > 0, "Zero amount");
// 计算手续费
uint256 fee = (amount * feeBps) / 10000;
uint256 netAmount = amount - fee;
// 生成唯一存款ID
bytes32 depositId = keccak256(abi.encodePacked(
msg.sender, amount, targetChain, block.number, block.timestamp
));
require(!processedDeposits[depositId], "Already processed");
processedDeposits[depositId] = true;
// 锁定代币
token.safeTransferFrom(msg.sender, address(this), amount);
emit Deposited(depositId, msg.sender, netAmount, targetChain);
}
// ═══════ 铸造(链B:提款) ═══════
function mint(
bytes32 depositId,
address recipient,
uint256 amount,
bytes[] memory signatures
) external {
require(!processedDeposits[depositId], "Already minted");
require(signatures.length >= REQUIRED_SIGNATURES, "Not enough signatures");
// 构造消息哈希
bytes32 messageHash = keccak256(abi.encodePacked(depositId, recipient, amount));
bytes32 ethSignedHash = messageHash.toEthSignedMessageHash();
// 验证多重签名
address[] memory signers = new address[](signatures.length);
for (uint256 i = 0; i < signatures.length; i++) {
address signer = ethSignedHash.recover(signatures[i]);
require(validators[signer], "Invalid signer");
// 防止同一验证者重复签名
for (uint256 j = 0; j < i; j++) {
require(signer != signers[j], "Duplicate signer");
}
signers[i] = signer;
}
processedDeposits[depositId] = true;
// 实际项目中:铸造wrapped代币给接收者
// 这里简化为直接转账(单链模拟)
token.safeTransfer(recipient, amount);
emit Minted(depositId, recipient, amount);
}
// ═══════ 管理函数 ═══════
function addValidator(address _validator) external onlyOwner {
validators[_validator] = true;
}
function removeValidator(address _validator) external onlyOwner {
validators[_validator] = false;
}
function setFeeBps(uint256 _feeBps) external onlyOwner {
require(_feeBps < 1000, "Fee too high"); // 最高10%
feeBps = _feeBps;
}
}
| 桥类型 | 安全假设 | 风险等级 |
|---|---|---|
| 中心化托管 | 信任单一实体 | 🔴 高 |
| M-of-N多签 | 信任N个验证者中至少M个诚实 | 🟡 中 |
| 轻客户端验证 | 信任目标链共识 | 🟢 低 |
| ZK证明 | 信任数学 | 🟢 最低 |
| 方案 | 类型 | 支持链 | 特点 |
|---|---|---|---|
| Chainlink CCIP | M-of-N+风险管理 | 多链 | 最安全,速率限制 |
| LayerZero | 超轻节点+预言机 | 多链 | 可配置安全级别 |
| Axelar | POS验证者网络 | 多链 | 通用消息传递 |
| Stargate | LayerZero+流动性池 | 多链 | 统一流动性 |
| 官方桥(Optimism/Arbitrum) | Rollup原生 | L1↔L2 | 最安全,仅限L2 |
1. Lock-Mint桥的核心原理是什么?
2. 为什么跨链桥成为黑客攻击的重灾区?
3. 哪种跨链桥安全模型最强?
你已掌握跨链桥技术!从Lock-Mint到ZK桥,从多签验证到安全模型,你理解了多链世界的资产流动基础设施。
关键收获:
✅ 跨链桥分类(信任模型+桥接机制)
✅ Lock-Mint/Burn-Mint/Liquidity Pool模式
✅ 多签验证桥合约实现
✅ 跨链桥安全模型与攻击案例
✅ 主流跨链方案对比