1Do App

Dex

maker 链下固定资产、数量、期限和 nonce;buyer 按订单类型用一次性 Token Pull 或原生币完成全额结算。

7 个章节onedo-dex
01

交易模型

Dex 是签名订单式交换应用。maker 不需要把资产存入池子或链上订单簿,而是在链下签署一份完整报价;只有 buyer 成交或 maker 取消时,maker 钱包才写入 consumed 状态。

价格直接由 amountIn / amountOut 或 nativeAmount / tokenAmount 表达。当前合约没有 AMM 曲线、流动性池、部分成交、撮合优先级或协议交易费。

  • maker 资产在成交前始终留在 maker 钱包。
  • buyer 的 ERC-20 支付只在当前结算交易中开放给 maker 钱包拉取。
  • 订单必须一次性全额成交;成交与取消都会永久消费同一订单。
  • 任何地址都可以提交有效成交,但不能改写 maker 已签署的资产与数量。
02

三类订单

  • TokenForTokenOrder:maker 从钱包转出 tokenIn / amountIn,buyer 支付 tokenOut / amountOut。
  • NativeForTokenOrder:maker 从钱包转出 nativeAmount,buyer 支付 erc20 / tokenAmount。
  • TokenForNativeOrder:maker 从钱包转出 erc20 / tokenAmount,buyer 支付精确的 nativeAmount。
  • expiry 为 0 时没有合约级到期限制;非零时,超过该时间戳的订单会失败。生产订单应使用明确期限。
  • nonce 是签名订单的一部分,用于区分报价,但不是合约自动递增的账户 nonce;真正的防重放状态是订单被标记 consumed。
Signed order fields
struct TokenForTokenOrder {
  address tokenIn;
  address tokenOut;
  uint256 amountIn;
  uint256 amountOut;
  uint256 expiry;
  uint256 nonce;
}

struct NativeForTokenOrder {
  address erc20;
  uint256 nativeAmount;
  uint256 tokenAmount;
  uint256 expiry;
  uint256 nonce;
}

struct TokenForNativeOrder {
  address erc20;
  uint256 nativeAmount;
  uint256 tokenAmount;
  uint256 expiry;
  uint256 nonce;
}
03

通用结算流程

步骤 1

构造并签署订单

maker 使用 EIP-712 域 Dex Order on 1Do / 1 签名,verifyingContract 是 maker 钱包地址。

步骤 2

选择正确付款入口

ERC-20 付款由 buyer 钱包建立 Token Pull;原生币付款则把精确 msg.value 直接发送到 maker 钱包的 Runtime 调用。

步骤 3

在 maker 钱包执行

Runtime 检查应用状态后 delegatecall Dex;应用验证参数、expiry、consumed 状态与 maker 的 ERC-1271 签名。

步骤 4

完成原子交换

应用锁定订单消费状态,移动双方资产并发出 Filled 事件;任一校验或转账失败都会回滚全部变化。

04

不同订单的资产路径

  • Token → Token:buyer.executeWithTokenPull 以 maker 钱包为 target;Dex 从 buyer 拉取 tokenOut,再把 maker 的 tokenIn 转给 buyer。
  • 原生币 → Token:buyer 同样用 Token Pull 支付 erc20;Dex 从 maker 钱包把原生币发送给 buyer。
  • Token → 原生币:不使用 Pull。buyer 向 maker 钱包的 executeRuntimeApp 附带 msg.value,且金额必须与 nativeAmount 完全一致;随后 Dex 把 maker 的 Token 转给 buyer。
  • 前两条 Pull 路径要求 buyer 钱包支持 Token Pull,但不要求 buyer 自己启用 Dex;原生币付款路径可直接调用 maker Runtime。maker 钱包必须启用当前 Dex logic,且 Registry 仍允许该地址。
  • ERC-20 转账使用 SafeERC20;原生币收款方拒收时整笔结算失败。当前实现按常规 ERC-20 余额语义设计。
05

签名、取消与重放保护

  • EIP-712 domain 绑定当前 chainId 与 maker 钱包。共享 Dex logic 地址不是 verifyingContract。
  • maker 签名通过 maker 钱包的 ERC-1271 校验;签名覆盖订单类型中的全部字段。
  • 订单不绑定指定 buyer,也不把 app logic 地址放入签名结构;任何 buyer 都可成交,切换兼容 logic 版本前应评估旧签名是否仍可使用。
  • 成交状态保存在 maker 钱包的 ERC-7201 命名空间中,因此不同 maker 的订单状态彼此隔离。
  • 三类 cancelSigned... 函数只能由 maker 钱包 self-call;取消与成交都把订单标记为 consumed。
  • 合约当前没有公开 consumedOrders getter。前端应结合订单、模拟调用和 Filled / Cancelled 事件维护状态。
  • TokenForToken 的事件与 consumed key 使用完整 EIP-712 digest;两类原生币订单使用 struct hash。索引方不应把三类 orderHash 按同一种算法计算。
  • 从链下订单服务删除报价不等于链上取消;禁用应用也不会抹除订单,未来重新启用后,未过期且未消费的签名仍可能有效。
06

事件与主要失败条件

  • 每种订单都有独立的 ...Filled(orderHash, buyer) 与 ...Cancelled(orderHash) 事件;通过 Runtime 执行时,日志 emitter 是 maker 钱包地址。
  • 零 Token 地址、零数量、过期订单、已消费订单或错误 maker 签名都会失败。
  • TokenForNativeOrder 的 msg.value 不精确会返回 InvalidNativeValue。
  • Token 或原生币转账失败会回滚订单消费状态,不会留下半完成成交。
07

当前边界

不是 AMM 或链上订单簿

Dex 当前只处理三类 full-fill 签名订单,不提供部分成交、批量撮合、池内定价、链上报价发现或订单状态查询接口。前端和索引服务负责保存链下订单并跟踪成交与取消事件。