Sera.sol¶
用于订单撮合、存款和提款的核心结算合约。
主网: 0xB5C50C5D5f038404F85970b7f5B7259C4AC0E198 源代码: src/Sera.sol
常量¶
string public constant NAME = "Sera";
string public constant VERSION = "1";
uint32 public constant WITHDRAW_DELAY_BLOCKS = 7200; // ~24 hours
uint32 public constant WITHDRAW_EXPIRATION_BLOCKS = 14400; // ~48 hours
uint256 public constant MAX_EXPIRATION = 365 days;
数据结构¶
Order¶
struct Order {
address user; // Order originator
uint48 expiration; // Expiration timestamp
uint48 feeBps; // Fee in basis points
address recipient; // External recipient (address(0) = vault swap)
address fromToken; // Input token
address toToken; // Output token
uint256 fromAmount; // Input amount
uint256 toAmount; // Minimum output amount (price protection)
uint256 initialDepositAmount; // Wallet funding for SOR legs
uint256 uuid; // Unique identifier for replay protection
}
MatchData¶
struct MatchData {
Order order0; // First order
bytes signature0; // EIP-712 signature for order0
uint256 matchAmount0; // Amount of order0.fromToken to fill
Order order1; // Second order
bytes signature1; // EIP-712 signature for order1
uint256 matchAmount1; // Amount of order1.fromToken to fill
}
WithdrawIntent¶
struct WithdrawIntent {
address user; // Withdrawing user
address[] tokens; // Tokens to withdraw (1-20)
uint256[] amounts; // Amounts per token
address recipient; // Withdrawal destination
uint256 deadline; // Signature deadline
uint256 uuid; // Replay protection
}
存款函数¶
depositFund¶
将代币从您的钱包存入 Vault。
| 参数 | 类型 | 说明 |
|---|---|---|
_token | address | 要存入的 ERC-20 代币 |
_owner | address | 必须为 msg.sender |
_value | uint256 | 存入金额 |
要求:
- 调用者必须为
_owner - 代币必须在白名单中
- 合约不能处于暂停状态
depositFundWithPermit¶
使用 ERC-2612 permit 存款(在一笔交易中完成授权 + 存款)。
function depositFundWithPermit(
address _token,
address _owner,
uint256 _permitAmount,
uint256 _depositAmount,
uint256 _deadline,
bytes calldata _sig
) public
| 参数 | 类型 | 说明 |
|---|---|---|
_token | address | ERC-20 代币 |
_owner | address | 存款人(必须为 msg.sender) |
_permitAmount | uint256 | permit 签名中的金额 |
_depositAmount | uint256 | 实际存款金额(必须 ≤ _permitAmount) |
_deadline | uint256 | Permit 截止时间 |
_sig | bytes | ERC-2612 permit 签名(64 或 65 字节) |
提款函数¶
emergencyWithdraw¶
当 API 不可用时的两步延迟提款。
流程:
- 第一次调用 — 发起提款请求,记录区块号
- 等待 — 必须经过至少 7,200 个区块(约 24 小时)
- 第二次调用 — 使用相同参数执行提款
要求:
- 金额必须 > 0
- 执行必须在请求后 14,400 个区块(约 48 小时)内完成
- 执行金额必须与请求金额匹配
事件:
event WithdrawRequested(address indexed user, address indexed token, uint256 amount, uint256 indexed requestBlock);
event Withdraw(address indexed token, address indexed to, uint256 amount);
Note
被冻结的用户可以使用紧急提款。这确保资金始终可以取回。
executeInstantWithdrawDualSig¶
使用用户和执行者双重签名的即时提款。
function executeInstantWithdrawDualSig(
WithdrawIntent calldata intent,
bytes calldata userSignature,
address executor,
bytes calldata executorSignature
) external
| 参数 | 类型 | 说明 |
|---|---|---|
intent | WithdrawIntent | 提款参数 |
userSignature | bytes | 用户的 EIP-712 WithdrawIntent 签名 |
executor | address | 协同签名的执行者地址;必须持有 EXECUTOR_ROLE |
executorSignature | bytes | 执行者的 EIP-712 WithdrawIntent 签名 |
要求:
- 截止时间未过期
- UUID 未被使用过
- 每次提款 1-20 种代币
executor必须持有EXECUTOR_ROLE- 两个签名都必须有效(EOA 或 ERC-1271)
支持在单笔交易中进行多代币提款。
事件:
event InstantWithdraw(address indexed user, uint256 indexed uuid, address indexed token, uint256 amount, address recipient);
订单撮合¶
matchOrders¶
结算已匹配的订单对。由授权的执行者调用。
| 参数 | 类型 | 说明 |
|---|---|---|
_match | MatchData | 两个订单及其签名和成交金额 |
deadline | uint256 | Unix 时间戳;过期则交易回退 |
验证:
- 代币对称性:
order0.fromToken == order1.toToken,反之亦然 - 不能自我撮合(不同的订单哈希)
- 不能同币种撮合
- 两个订单都未过期
- 两个签名都有效
- Vault 余额充足
- 成交金额在订单限额范围内
事件:
event OrderMatched(
bytes32 indexed orderHash0, address indexed user0, address token0, uint256 amount0, uint256 protocolTake0,
bytes32 indexed orderHash1, address user1, address token1, uint256 amount1, uint256 protocolTake1
);
event OrderFullyFilled(bytes32 indexed orderHash, address indexed user);
状态变量¶
mapping(bytes32 => uint256) public filledAmount; // Partial fill tracking per order hash
mapping(address => mapping(uint256 => bool)) public isUuidExecuted; // Replay protection
mapping(address => mapping(address => WithdrawRequest)) public withdrawRequests; // Pending withdrawals
EIP-712 类型哈希¶
// Order signing
bytes32 constant ORDER_TYPEHASH = keccak256(
"Order(address user,uint48 expiration,uint48 feeBps,address recipient,address fromToken,address toToken,uint256 fromAmount,uint256 toAmount,uint256 initialDepositAmount,uint256 uuid)"
);
// Withdrawal signing
bytes32 constant WITHDRAW_INTENT_TYPEHASH = keccak256(
"WithdrawIntent(address user,address[] tokens,uint256[] amounts,address recipient,uint256 deadline,uint256 uuid)"
);
SOR Digest 辅助函数¶
Sera 同时暴露 getIntentDigest(...),返回 SeraSOR 用于路由兑换 Intent 的 EIP-712 摘要。
管理员函数¶
| 函数 | 角色 | 说明 |
|---|---|---|
setTreasury(address) | Admin | 设置金库地址 |
setSlippageShares(...) | Admin | 配置链上滑点分配参数 |
batchModifyWhitelistedTokens(...) | Admin | 白名单/取消白名单代币 |
setTrustedRouter(address) | Admin | 设置 SeraSOR 地址 |
rescueToken(address, address) | Admin | 救回误发的代币 |
pause() / unpause() | Pauser | 紧急暂停/恢复 |
错误¶
| 错误 | 原因 |
|---|---|
UserFrozen | 用户账户被冻结 |
AmountBelowMinimum | 订单低于代币最低金额 |
WithdrawNotReady | 提款延迟期未满 |
WithdrawExpired | 提款请求已过期 |
IntentExpired | 签名截止时间已过 |
UuidAlreadyUsed | 检测到 UUID 重放 |
TokenMismatch | 订单代币对不匹配 |
SelfMatch | 尝试将订单与自身撮合 |
OrderExpired | 订单过期时间戳已过 |
OrderFilledAmountExceeded | 成交将超过订单剩余金额 |
InvalidSignature | 签名验证失败 |
InsufficientVaultBalance | 用户存款不足 |