跳到主要内容

Auroran Bridge 充提对接指南

本文档说明如何通过 EVM 侧 Auroran Bridge 合约Auroran Chain API 完成跨链充提对接。合约 ABI 见 合约接口参考,链上 Action 见 Chain API — Bridge 充提


1. 架构概览

Auroran Bridge 是部署在 EVM 链(如 BSC)上的充提桥接合约。合约不托管资金

  • 充值:用户调用 deposit,代币从用户钱包直接转入 projectAddress;合约仅记录账本并发出事件。
  • 提款:结算操作员调用 settleWithdraw,代币从操作员钱包转入用户收款地址;合约记录放款并发出事件。

链下程序监听 EVM 事件,并通过 Chain API 与 Auroran 链账本同步。

1.1 角色分工

角色职责
用户EVM 侧 approve + deposit;Auroran 链侧 EIP-712 签名 WithdrawRequest
结算操作员(SettlementOperator)监听 EVM / Auroran 链事件,调用 Chain API RecordDeposit / CreditDeposit / WithdrawSettle;EVM 侧 approve + settleWithdraw 放款
合约 Owner管理 projectAddress、暂停开关、blockConfirmations
Operator仅可调用 pauseDeposits 紧急暂停充值

1.2 关键标识映射

EVM 合约与 Auroran 链 Bridge API 通过以下字段对齐:

EVM(Auroran Bridge)Auroran 链(Chain API)说明
chainTag(如 "bsc"external_ref.chain外部链标识,小写
deposit() 返回的 seqexternal_ref.seq充值去重键,1-based
DepositRecorded 事件RecordDeposit 参数链下据此构造登记请求
WithdrawSettled 事件的 zeptoRequestIdWithdrawSettle.request_id提款请求 ID(合约字段名 zeptoRequestId
代币 decimals()amount SCALE_6 换算§4 金额换算

用户交互地址为 TransparentUpgradeableProxy 地址(非 implementation)。部署说明见合约仓库 scripts/deploy-bridge.sh


2. 接入准备

2.1 所需信息

获取方式
Bridge Proxy 地址部署输出 / 运维配置
桥接 ERC20 地址bridge.token()bridgeChainInfo().tokenAddr
chainTagbridge.chainTag()(须与 WithdrawRequest.chain 一致)
blockConfirmationsbridge.blockConfirmations()bridgeChainInfo().confirmations
Chain API 端点{node}/api/v1/query · {node}/api/v1/action — 见 Chain API
SettlementOperator 凭证SettlementOperator 角色的 Agent 或 Master — 见 签名与鉴权

2.2 ABI 下载

合约 ABI:

/abi/AuroranBridge.abi.json

完整 URL:https://docs.auroran.io/abi/AuroranBridge.abi.json

2.3 推荐依赖

语言
TypeScriptviem 或 ethers v6
Gogo-ethereum bind
Rustalloy

下文示例使用 viem


3. 充值流程

3.1 用户侧(EVM)

  1. 读取 token() 获取 ERC20 地址。
  2. 对 Bridge Proxy 地址执行 token.approve(bridge, amount)
  3. 调用 deposit(amount),获得返回值 seq
  4. 等待交易确认;可从 DepositRecorded 事件校验 seqowneramount
import { createPublicClient, createWalletClient, http, parseUnits } from 'viem';
import { bsc } from 'viem/chains';
import bridgeAbi from './AuroranBridge.abi.json';

const BRIDGE = '0x...' as const; // Proxy 地址
const amount = parseUnits('100', 18); // 按 token.decimals() 换算

const wallet = createWalletClient({ chain: bsc, transport: http(), account });
const publicClient = createPublicClient({ chain: bsc, transport: http() });

// 1. approve
await wallet.writeContract({
address: tokenAddress,
abi: erc20Abi,
functionName: 'approve',
args: [BRIDGE, amount],
});

// 2. deposit
const hash = await wallet.writeContract({
address: BRIDGE,
abi: bridgeAbi,
functionName: 'deposit',
args: [amount],
});

const receipt = await publicClient.waitForTransactionReceipt({ hash });
// 从 receipt.logs 解析 DepositRecorded,或调用 depositCount() / getDeposit(seq)

注意

  • amount 为代币原生精度(如 XUSDT 为 18 位)。
  • depositsPaused == truedeposit 会 revert DepositsPausedError
  • 代币直达 projectAddress,Bridge 合约余额始终为 0。

3.2 结算侧(链下 → Auroran 链)

结算服务监听 DepositRecorded,在达到 blockConfirmations 后向 Chain API 提交两笔 Action:

Step 1 — RecordDeposit

signer 须持 SettlementOperator 角色。参数见 write-actions §11.1

字段来源
external_ref.chainbridge.chainTag()
external_ref.seqDepositRecorded.seq
tx_hash充值交易的 32 字节 hash(JSON 字节数组)
accountDepositRecorded.owner
amount§4 转为 SCALE_6 字符串
bsc_blockDepositRecorded.blockNumber
bsc_tsDepositRecorded.timestamp

提交前可用 getBridgeDepositByExternalRef 检查是否已登记,避免重复:

{ "method": "getBridgeDepositByExternalRef", "params": { "chain": "bsc", "seq": 50001 } }

Step 2 — CreditDeposit

RecordDeposit 成功后,用返回的 Auroran 侧 seq 调用 CreditDeposit

{ "method": "CreditDeposit", "params": { "seq": 101 } }

3.3 充值状态机

阶段EVMAuroran 链
用户已转账DepositRecorded 已发出
已登记status: "Recorded"
已入账status: "Credited",用户余额增加

4. 金额换算

格式示例
EVM deposit / settleWithdrawuint256,代币 decimals()100000000000000000000(18 位 = 100 代币)
Chain API amountSCALE_6 decimal string"100.000000"

换算公式(tokenDecimals 来自 bridgeChainInfo().tokenDecimals):

auroran_amount = evm_amount / 10^tokenDecimals → 格式化为 6 位小数的 canonical string
evm_amount = parseUnits(auroran_amount, tokenDecimals)

tokenDecimals == 6,数值一一对应;若为 18,须除以 10^12


5. 提款流程

5.1 用户侧(Auroran 链)

用户通过钱包 EIP-712 签名提交 WithdrawRequest(User-Signed 通道)。chain 字段须与 Bridge 的 chainTag 一致(如 "bsc")。

详见 write-actions §11.3write-actions §3.2(EIP-712 typed data)。

5.2 结算侧(Auroran 链 → EVM → Auroran 链)

Step 1 — 监听提现请求

通过 Chain API WebSocket bridge 主题或轮询 listBridgeWithdrawalsstatus: "pending")获取待处理提款。

Step 2 — EVM 放款

  1. 确认 isZeptoRequestIdUsed(requestId) == false
  2. 操作员钱包 approve(bridge, amount)
  3. 调用 settleWithdraw(zeptoRequestId, amount, recipient)
    • zeptoRequestId = Auroran 链 request_id
    • amount = 按 §4 转为 EVM 原生精度
    • recipient = 用户指定的 EVM 收款地址(与 WithdrawRequest.owner 对应)
const requestId = 2001n;
const amount = parseUnits('500', 18);
const recipient = '0x1111...0000' as const;

await wallet.writeContract({
address: tokenAddress,
abi: erc20Abi,
functionName: 'approve',
args: [BRIDGE, amount],
});

await wallet.writeContract({
address: BRIDGE,
abi: bridgeAbi,
functionName: 'settleWithdraw',
args: [requestId, amount, recipient],
});

注意

  • 无链上权限限制——谁付款谁调用;代币从 msg.sender 转出。
  • zeptoRequestId 为去重键,重复调用 revert ZeptoRequestIdAlreadyUsed
  • withdrawalsPaused == true 时 revert WithdrawalsPausedError

Step 3 — WithdrawSettle

EVM 交易确认后,向 Chain API 提交 WithdrawSettle

字段来源
request_idAuroran 链提现请求 ID
external_tx.tx_hashsettleWithdraw 交易的 32 字节 hash
external_tx.bsc_block放款区块号
external_tx.bsc_ts放款区块时间戳(秒)

5.3 提款状态机

阶段Auroran 链EVM
用户发起status: "Pending"
EVM 已放款WithdrawSettled 已发出
结算完成status: "Settled"isZeptoRequestIdUsed == true

若 EVM 放款失败,可调用 WithdrawRefund 将资金退回用户 Auroran 链余额。


6. 事件监听

结算服务须订阅以下 EVM 事件(完整字段见 合约接口 — 事件):

事件监听方用途
DepositRecorded充值结算触发 RecordDeposit
WithdrawSettled提款对账确认 EVM 放款,触发 WithdrawSettle
DepositsPaused / DepositsUnpaused运维暂停/恢复充值入口
WithdrawalsPaused / WithdrawalsUnpaused运维暂停/恢复提款结算

6.1 DepositRecorded 过滤示例(viem)

const logs = await publicClient.getLogs({
address: BRIDGE,
event: {
type: 'event',
name: 'DepositRecorded',
inputs: [
{ name: 'seq', type: 'uint64', indexed: true },
{ name: 'owner', type: 'address', indexed: true },
{ name: 'amount', type: 'uint256', indexed: false },
{ name: 'blockNumber', type: 'uint64', indexed: false },
{ name: 'timestamp', type: 'uint64', indexed: false },
],
},
fromBlock: lastProcessedBlock,
});

6.2 断点续传

  • 充值:以 depositCount() 或最大已处理 seq 为游标;漏扫时按 seq 调用 getDeposit(seq) 补全。
  • 提款:以 isZeptoRequestIdUsed + listBridgeWithdrawals 交叉校验。

7. 对账与查询

需求EVMAuroran 链
单笔充值getDeposit(seq)getBridgeDeposit / getBridgeDepositByExternalRef
充值列表getDeposits(offset, limit)listBridgeDeposits
单笔提款getWithdraw(withdrawId)getBridgeWithdrawal
提款列表getWithdrawals(offset, limit)listBridgeWithdrawals
去重检查isZeptoRequestIdUsed(requestId)getBridgeDepositByExternalRef
全局闸门depositsPaused / withdrawalsPausedgetBridgeSettlement

历史对账可结合 历史与审计 — bridge-flows


8. 错误处理

8.1 EVM revert

错误场景处理建议
DepositsPausedError充值已暂停通知用户,等待 DepositsUnpaused
WithdrawalsPausedError提款已暂停暂停 EVM 放款,等待恢复
ZeptoRequestIdAlreadyUsed重复结算getWithdraw 确认已放款,补发 WithdrawSettle
TransferAmountMismatch代币转账异常(fee-on-transfer 等)检查代币合约兼容性
ZeroAmount金额为 0校验换算逻辑

完整列表见 合约接口 — 错误

8.2 Auroran 链拒绝

场景处理
external_ref 重复已登记,跳过 RecordDeposit,检查是否需 CreditDeposit
settlement_paused调用 getBridgeSettlement,等待 Admin 恢复
WithdrawAvailableInsufficient用户余额不足,拒绝或等待

9. 安全检查清单

  • 使用 Proxy 地址 而非 implementation 地址
  • chainTagWithdrawRequest.chainRecordDeposit.external_ref.chain 一致
  • 充值监听等待 blockConfirmations 后再提交 RecordDeposit
  • RecordDeposit 前先查 getBridgeDepositByExternalRef 防重
  • settleWithdraw 前查 isZeptoRequestIdUsed 防重
  • 金额换算使用 bridgeChainInfo().tokenDecimals,勿硬编码
  • SettlementOperator 私钥安全存储,建议使用 Agent 委托
  • 监控 depositsPaused / withdrawalsPaused / settlement_paused

10. 相关文档

文档内容
合约接口参考全部函数、事件、错误、数据结构
Chain API — Bridge 写操作RecordDeposit / CreditDeposit / WithdrawSettle
Chain API — Bridge 读方法getBridgeDeposit / listBridgeWithdrawals 等
Chain API — 事件Auroran 链 Bridge 事件域
签名与鉴权SettlementOperator Agent 配置