1Do App

Dex

A maker fixes assets, amounts, expiry, and nonce offchain; a buyer settles the entire order through a transient token pull or exact native value.

7 sectionsonedo-dex
01

Trading model

Dex is a signed-order exchange. The maker does not deposit into a pool or post an onchain order; the quote is distributed offchain, and the maker wallet writes consumed state only when the order fills or is cancelled.

Price is expressed directly by the signed amounts. The current contract has no AMM curve, liquidity pool, partial fill, matching priority, or protocol trading fee.

  • Maker assets remain in the maker wallet until settlement.
  • A buyer's ERC-20 payment is pullable by the maker wallet only during the current transaction.
  • Orders fill in full; a successful fill or cancellation permanently consumes that exact order.
  • Any address may submit a valid fill, but cannot change the maker-signed assets or amounts.
02

Three order types

  • TokenForTokenOrder: the maker sends tokenIn / amountIn and the buyer pays tokenOut / amountOut.
  • NativeForTokenOrder: the maker sends nativeAmount and the buyer pays erc20 / tokenAmount.
  • TokenForNativeOrder: the maker sends erc20 / tokenAmount and the buyer pays exact nativeAmount.
  • expiry = 0 has no contract-level expiry; otherwise the order fails only after the timestamp. Production orders should use an explicit expiry.
  • nonce is a signed salt for distinguishing quotes, not an auto-incrementing account nonce. Replay protection comes from exact consumed-order state.
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

Settlement flow

Step 1

Construct and sign

The maker signs with the EIP-712 domain Dex Order on 1Do / 1 and the maker wallet as verifyingContract.

Step 2

Choose the payment entry

ERC-20 payment opens a buyer-wallet token pull; native payment attaches exact msg.value to the maker-wallet Runtime call.

Step 3

Execute in the maker wallet

The Runtime gates and delegatecalls Dex, which validates fields, expiry, consumed state, and the maker ERC-1271 signature.

Step 4

Exchange atomically

The app marks the order consumed, moves both assets, and emits the fill event. Any failed check or transfer reverts all changes.

04

Asset paths by order type

  • Token → Token: buyer.executeWithTokenPull targets the maker wallet; Dex pulls tokenOut from the buyer and sends maker tokenIn to the buyer.
  • Native → Token: the buyer again pays ERC-20 through a token pull; Dex sends native currency from the maker wallet to the buyer.
  • Token → Native: no pull is used. The buyer calls the maker wallet's executeRuntimeApp with msg.value exactly equal to nativeAmount, then Dex sends the maker token to the buyer.
  • The first two paths require token-pull support in the buyer wallet but do not require the buyer to enable Dex. The native-payment path can call the maker Runtime directly. The maker must enable the current Dex logic and Registry must still allow it.
  • ERC-20 transfers use SafeERC20. A native recipient rejection reverts the settlement, and nonstandard token balance mechanics receive no special handling.
05

Signature, cancellation, and replay protection

  • The EIP-712 domain binds chainId and the maker wallet; the shared Dex logic address is not verifyingContract.
  • The maker signature is checked through ERC-1271 on the maker wallet and covers every field in that order type.
  • The order binds neither a designated buyer nor the app logic address. Any buyer may fill it, and integrations should assess old-signature compatibility before switching to another compatible logic version.
  • Consumed state lives in the maker wallet's ERC-7201 namespace, isolated from every other maker.
  • Each cancelSigned... function requires a maker-wallet self-call. Cancellation and fill both consume the exact order; there is no nonce floor or batch cancellation.
  • The contract exposes no public consumedOrders getter. Clients should combine offchain orders, simulations, and Filled / Cancelled events.
  • TokenForToken uses the full EIP-712 digest as its event hash and consumed key, while both native order types use the struct hash. Indexers must not compute all three identically.
  • Removing an offchain quote is not an onchain cancellation. Disabling the app does not erase the order, and an unexpired, unconsumed signature may become fillable again after re-enablement.
06

Events and primary failure cases

  • Each order type has its own ...Filled(orderHash, buyer) and ...Cancelled(orderHash) events. In Runtime execution, the emitter is the maker wallet.
  • Zero token addresses, zero amounts, expired or consumed orders, and invalid maker signatures fail.
  • TokenForNativeOrder fails unless msg.value exactly matches nativeAmount.
  • A token or native transfer failure reverts consumed state, so settlement cannot remain partially completed.
07

Current scope

Not an AMM or onchain order book

Dex currently handles only three full-fill signed-order types. It does not provide partial fills, batch matching, pool pricing, onchain price discovery, or an order-status getter. Frontends and indexers retain offchain orders and track fills and cancellations.