本项目是一个基于多签验证的跨链桥系统,支持在 EVM 链(Arbitrum Sepolia)和 SVM 链(1024chain)之间进行 USDC 代币的跨链转移。系统采用质押-解锁机制,通过多个独立的 relayer 进行多签验证,确保跨链转账的安全性。
扩展功能: 支持从任意链到 1024chain 的跨链转账(通过成熟的跨链桥如 LiFi 实现第一步,本仓库的 cross-chain-gateway 服务完成第二步)。
当前阶段: M4 - Relayer 服务开发(S2E Relayer 完整实现并验证成功 ✅)
详细进度: 参见 docs/progress.md
测试计划: 参见 docs/testplan.md
API文档: 参见 docs/api.md
设计文档: 参见 docs/design.md
- 支持 EVM(Arbitrum Sepolia)与 SVM(1024chain)之间的双向跨链转移
- 仅支持 USDC 代币的跨链转移
- 采用质押-解锁机制,而非铸币-销毁模式
- 多签验证机制,需要超过 2/3 的 relayer 签名才能完成解锁(最多支持18个relayer)
- 原生密码学算法:SVM 使用 Ed25519,EVM 使用 ECDSA (secp256k1) + EIP-191
- 防重放攻击机制:nonce 递增判断(64位无符号整数,溢出重置为0)+ block_height
- 支持至少100个未完成的跨链请求同时存在
- 支持至少1200个签名缓存(100个请求 × 18个relayer = 1800个签名)
系统采用各自原生密码学算法的设计原则:
SVM 端(Solana/1024chain):
- 签名算法:Ed25519(Solana 原生)
- 数据序列化:Borsh(Anchor 标准)
- 验证方式:Ed25519Program 预编译合约
- 特点:64 字节签名,性能极优
EVM 端(Ethereum/Arbitrum):
- 签名算法:ECDSA (secp256k1)(Ethereum 原生)
- 数据序列化:JSON 字符串
- 哈希算法:SHA-256 + Keccak256 (EIP-191)
- 验证方式:ecrecover 预编译合约
- 特点:65 字节签名,与 Ethereum 生态完全兼容
跨链兼容性:
- Relayer 负责在两种格式之间转换
- 监听 SVM 事件 → 用 ECDSA 签名 → 提交到 EVM
- 监听 EVM 事件 → 用 Ed25519 签名 → 提交到 SVM
EVM 工具链:
# 安装 Foundry
curl -L https://foundry.paradigm.xyz | bash && foundryupSVM 工具链:
# 安装 Anchor 和 Solana CLI
cargo install --git https://github.com/coral-xyz/anchor avm --locked --force
sh -c "$(curl -sSfL https://release.solana.com/stable/install)"
solana-keygen new -o ~/.config/solana/id.jsoncp .env.evm.deploy.example .env.evm.deploy
cp .env.svm.deploy.example .env.svm.deploy
cp .env.invoke.example .env.invoke
cp .env.config-usdc-peer.example .env.config-usdc-peer
# 填写缺失的配置
vim .env.evm.deploy
vim .env.svm.deploy
vim .env.invoke
vim .env.config-usdc-peer
cd scripts
# 1. 部署 EVM 合约
./01-deploy-evm.sh
# 2. 部署 SVM 合约(选择升级或全新部署)
./02-deploy-svm.sh
# 检查并确保 PEER_CONTRACT_ADDRESS_FOR_EVM 和 PEER_CONTRACT_ADDRESS_FOR_SVM 配置正确
vim ../.env.invoke
# 3. 配置 USDC 和对端地址
cd -
cd scripts
./03-config-usdc-peer.sh
# 4.1 注册 Relayer(自动生成密钥)
./04-register-relayer.sh
# 之后假设 relayer 账户拥有充足的SOL和ETH支付交易费,因此需要手动向这些账户充值
# 4.2 充值 Relayer 账户(可选,用于支付 gas 费用)
./05-fund-relayer.sh
# 4.3 启动 Relayer 服务
./06-start-relayer.sh start
# 5 添加流动性:管理员从自己的账户向金库地址转入USDC
npx ts-node evm-admin.ts add_liquidity 100000000
npx ts-node svm-admin.ts add_liquidity 100000000
# 6. 测试跨链转账
npx ts-node svm-user.ts balance
npx ts-node evm-user.ts stake 100 <SVM_RECEIVER_PUBKEY>
npx ts-node svm-user.ts balance # 确认SVM余额增加
npx ts-node evm-user.ts balance
npx ts-node svm-user.ts stake 100 <EVM_RECEIVER_ADDRESS>
npx ts-node evm-user.ts balance # 确认EVM余额增加详细说明见 scripts/README.md
主要不同的是上面的第四步
# 确保完成上面的1~3步
cd scripts
# 4.1 生成新的relayer密钥
./04-register-relayer.sh # 选择y覆盖现有密钥
cd ../relayer
# 4.2 初始化relayer配置文件和日志文件夹
./init-new-relayer.sh 1 # 将env文件统一复制到一个文件夹,并修改submitter的QUEUE__PATH
# 4.3 启动relayer容器
./start-container.sh 1
# 4.4 检查relayer容器是否启动成功
docker ps | grep relayer-container-relayer1
# 4.5 运行下一个relayer
cd ../scripts
./04-register-relayer.sh # 选择y覆盖现有密钥
cd ../relayer
./init-new-relayer.sh 2
./start-container.sh 2
docker ps | grep relayer-container-relayer2- 用户在发送端链调用质押接口,传入质押数量和接收端地址
- 发送端合约将用户的 USDC 转入质押金库,并触发质押事件
- 多个 relayer 监听到质押事件后,分别对事件数据进行签名
- 每个 relayer 将签名后的数据发送到接收端合约
- 接收端合约验证签名,当达到 2/3 阈值后,从金库解锁等量 USDC 到接收地址
-
svm/:Solana 智能合约(1024chain 部署)
- 统一初始化:
initialize函数同时初始化发送端和接收端合约 - USDC配置:
configure_usdc函数配置USDC mint account地址 - 统一对端配置:
configure_peer函数同时配置发送端和接收端的对端信息 - 发送端合约:负责质押 USDC 并触发质押事件(nonce自动递增)
- 接收端合约:验证 relayer Ed25519 签名并解锁 USDC(使用nonce递增判断防重放)
- 每个跨链请求使用独立的 CrossChainRequest PDA 账户存储签名缓存
- 密码学:Ed25519 签名 + Borsh 序列化(Solana 原生)
- 统一初始化:
-
evm/:EVM 智能合约(Arbitrum Sepolia 部署)
- 初始化:
initialize函数初始化发送端和接收端合约 - USDC配置:
configure_usdc函数配置USDC ERC20合约地址 - 对端配置:
configure_peer函数配置对端合约和链ID - 发送端合约:负责质押 USDC 并触发质押事件
- 接收端合约:验证 relayer ECDSA 签名并解锁 USDC
- 金库设计(v2.0):合约本身作为金库,无需外部 vault 或 approve
- 密码学:ECDSA (secp256k1) + EIP-191 + SHA-256 + JSON(Ethereum 原生)
- 初始化:
- relayer/:中继服务器(Rust 实现 🦀)
- s2e 服务 (SVM→EVM):✅ 完整实现并验证
- 单一进程架构
- 监听 1024chain 事件(HTTP RPC 轮询)
- ECDSA 签名(SHA-256 + EIP-191)
- 提交到 Arbitrum
- HTTP API(端口 8081)
- 详细说明:relayer/README_S2E.md
- e2s 服务 (EVM→SVM):✅ 完整实现并运行
- 分离式架构(解决依赖冲突)
e2s-listener:监听 Arbitrum 事件 → 文件队列e2s-submitter:队列处理 → Ed25519 签名 → 提交到 1024chain- HTTP API(端口 8082)
- 详细说明:relayer/README_E2S.md
- HTTP API:健康检查、状态查询、Prometheus 指标
- 高性能架构:Tokio 异步运行时 + 文件队列(e2s)/ 内存队列(s2e)
- 详细设计见 relayer/README.md
- s2e 服务 (SVM→EVM):✅ 完整实现并验证
-
broker/:跨链网关服务,实现两段式跨链桥方案 ✅ 已完整实现
系统采用两段式跨链桥设计,通过成熟的跨链桥(LiFi SDK)和自定义 Broker 服务,实现任意链与 1024chain 之间的跨链转账:
Deposit 方向(存入):任意链 → Arbitrum → 1024chain ✅
- 第一步:用户使用 LiFi SDK 将资产从任意链跨链到 Arbitrum 的 USDC
- 支持的源链:Ethereum、Polygon、BSC、Avalanche、Base、Optimism、Arbitrum 等
- 支持的源代币:各链上的原生代币或稳定币
- 目标:Arbitrum 上的 USDC
- USDC 转入 Broker 的中转钱包地址
- 第二步:调用 Broker EVM Gateway Service 完成从 Arbitrum 到 1024chain 的跨链
- HTTP API:
POST /stake(端口 8084) - 参数:
amount(USDC 金额)、target_address(1024chain 接收地址) - 服务使用中转钱包自动调用 EVM stake 合约接口
- 自动检查 USDC 余额和授权
- HTTP API:
Withdraw 方向(提取):1024chain → Arbitrum → 任意链 ✅
- 第一步:用户在 1024chain 调用 SVM stake 合约,将 USDC 发送到 Broker 的 Arbitrum 地址
- 用户调用 SVM 合约的
stake方法 - 参数:
amount(USDC 金额)、receiver_address(Broker 的 Arbitrum 地址) - USDC 从 1024chain 跨链到 Arbitrum,转入 Broker 的中转钱包
- 用户调用 SVM 合约的
- 第二步:调用 Broker Withdraw Gateway Service 完成从 Arbitrum 到目标链的跨链
- HTTP API:
POST /withdraw(端口 8085) - 参数:
target_chain(目标链 ID)、target_asset(目标代币地址)、usdc_amount(USDC 金额)、recipient_address(接收地址) - 服务使用 LiFi SDK 自动执行跨链交易
- 支持跨链到任意链的任意代币
- HTTP API:
-
evm-gateway-service:EVM 网关服务(Rust 实现)✅
- 负责 Deposit 方向的第二步:Arbitrum → 1024chain
- HTTP API(端口 8084)
- 详细说明:broker/evm-gateway-service/README.md
-
withdraw-gateway-service:提现网关服务(TypeScript/Node.js 实现)✅
- 负责 Withdraw 方向的第二步:Arbitrum → 任意链
- HTTP API(端口 8085)
- 集成 LiFi SDK 实现跨链
- 支持速率限制和并发控制
- 详细说明:broker/withdraw-gateway-service/README.md
Broker 服务与
relayer完全独立,职责不同:- relayer:负责监听链上事件、签名验证、多签提交(双向跨链:EVM ↔ SVM)
- broker:负责接收外部 HTTP 请求,完成两段式跨链桥的第二步(单向:Arbitrum → 1024chain 或 1024chain → 任意链)
Deposit 流程:
用户钱包(Ethereum USDC) ↓ [LiFi SDK 跨链] Broker 中转钱包(Arbitrum USDC) ↓ [Broker EVM Gateway Service] EVM Stake 合约(Arbitrum) ↓ [Relayer 多签验证] 1024chain 用户地址(USDC)Withdraw 流程:
1024chain 用户地址(USDC) ↓ [SVM Stake 合约] Broker 中转钱包(Arbitrum USDC) ↓ [Broker Withdraw Gateway Service + LiFi SDK] 用户钱包(目标链目标代币) - 第一步:用户使用 LiFi SDK 将资产从任意链跨链到 Arbitrum 的 USDC
- scripts/:部署和操作脚本(TypeScript + Shell)- 已精简至 11 个核心脚本
- 部署脚本:
01-deploy-evm.sh:自动化部署 EVM 合约到 Arbitrum Sepolia02-deploy-svm.sh:自动化部署 SVM 合约到 1024chain(支持升级/全新部署)03-config-usdc-peer.sh:配置 USDC 地址和对端合约地址04-register-relayer.sh:自动生成并注册 Relayer 密钥对05-fund-relayer.sh:为 Relayer 账户充值(ETH 和 SOL)06-start-relayer.sh:启动/停止 Relayer 服务(s2e, e2s-listener, e2s-submitter)
- 管理脚本:
evm-admin.ts:EVM 合约管理操作(查询状态、配置、relayer 管理、流动性管理)svm-admin.ts:SVM 合约管理操作(查询状态、配置、relayer 管理、流动性管理)
- 用户脚本:
evm-user.ts:EVM 用户操作(质押 USDC、查询余额)svm-user.ts:SVM 用户操作(质押 USDC、查询余额)
- 测试脚本:
cross-chain-test.ts:EVM→SVM 端到端测试cross-chain-test-s2e.ts:SVM→EVM 端到端测试
- 详细文档见 scripts/README.md
- 部署脚本:
- README.md:项目概述和使用说明(本文件)
- docs/api.md:API 接口文档和模块间调用规约
- docs/testplan.md:测试计划和用户故事
- docs/progress.md:项目进度跟踪
系统需要配置以下参数以支持不同网络环境(测试网/主网):
- 发送端链的 RPC 地址
- 接收端链的 RPC 地址
- 发送端合约地址
- 接收端合约地址
- 质押金库地址:
- SVM端:PDA 金库地址(发送端和接收端共享同一个金库)
- EVM端(v2.0):合约本身作为金库,不需要单独配置
- 管理员钱包地址(SVM 和 EVM 各自独立,但在SVM中发送端和接收端共享同一个管理员)
- USDC代币地址:
- SVM端:USDC mint account地址(通过
configure_usdc配置) - EVM端:USDC ERC20合约地址(通过
configure_usdc配置)
- SVM端:USDC mint account地址(通过
- Relayer 私钥列表(最多18个relayer)
- Chain ID(Arbitrum Sepolia/Mainnet,1024chain Testnet/Mainnet)
- ✅ 合约即金库:合约地址直接持有 USDC,不需要外部 vault
- ✅ 简化部署:不需要配置 vault 地址或进行 approve 操作
- ✅ 流动性管理:直接向合约地址转入 USDC 即可增加流动性