OTC for any ERC-20 pair, wallet to wallet: a single call moves both sides, and you read every parameter first. Open the board

Settlement

Two wallets can swap any pair of ERC-20 tokens on Robinhood Chain without a pool between them. The maker signs. The taker sends a single call, which carries both sides or is undone.

Four steps

Allowthe maker approves the sell token
Signan EIP-712 message, gas free
Publishthe board, or a link you send
Settlea single call for both sides

Until someone fills it, an order is only a signature and every token sits with its owner. No contract holds them and no curve sets the rate, so what was signed is what settles. When either side is short at that moment, the call reverts.

The order

EIP-712, domain Orbu Settlement Desk / 1 / chain 4663
Order(
  address maker,       // the signer, who gives sellToken for buyToken
  address taker,       // zero = open to all; else that wallet alone
  address sellToken,
  address buyToken,
  uint128 sellAmount,  // the whole order
  uint128 buyAmount,   // the price of all of sellAmount
  uint128 minFill,     // equal to sellAmount = all or nothing
  uint64  expiry,      // unix seconds, always set
  uint256 nonce,       // raising your minimum nonce ends it
  Policy  policy       // the modules, each off when zero
)
Policy(
  uint64  startsAt,    // window: no fill before this
  uint128 maxFill,     // cap: most one fill can take
  address feeRecipient,// fee: the wallet that gets it
  uint16  feeBps,      // fee: share of the maker's proceeds, 1000 at most
  address feed,        // band: the feed the maker names
  int256  bandLow,
  int256  bandHigh,
  uint32  maxFeedAge,
  bytes32 takerRoot    // allowlist: Merkle root of taker addresses
)

A maker can also be a contract account: the desk checks a key signature first, then ERC-1271. Or a maker can skip the signature by calling post(order), which also lists the order on the public board through an event.

Pre-fill checks

This is the point of the product. Before a wallet prompt, the order page shows, line by line:

  • a settlement simulation of your exact fill by eth_call on the latest block, from your own address
  • balance and allowance for both sides, read from each token
  • an expiry countdown and the decoded parameters
  • token identity. On this chain a ticker is not an identity: official stock tokens are recognised from the issuer's beacon in their code, and a token using a known ticker from another address is flagged
  • pause and blocklist status, where the token answers. Official stock tokens have the functions, but a blocklist read can refuse to answer, which shows as unread

You get readings, never a verdict. A token can pass every line and still be a bad trade.

Filling

fill(order, signature, sellWanted, proof) moves sold from maker to taker and ceil(sold × buyAmount / sellAmount) the other way. The rounding goes the maker's way by design. The largest uint256 means as much as one fill allows. After the transfers the desk compares balances: a token that skims on transfer or rebases during the call fails the whole fill with ExactAmountNotDelivered.

Ending an order

cancel(order) ends one order. bumpNonce(newMin) ends every order with a nonce below newMin, and your desk shows that number before you sign. The desk sets it 24 hours past your clock, because site nonces come from the signing device's clock. An order with a higher nonce survives: one signed on a device whose clock runs further ahead, or a hand-made one. Use cancel or revoke your allowance for those. New orders always start above your minimum. Both are one click on your desk. Forgetting a signed link in your browser does not end it.

Tokens

Amounts are uint128. Skimming and rebasing tokens are refused by the exact-amount check. Stock tokens settle like any ERC-20; a fork test on 3 Nov 2026 filled an official NVDA token against USDG. A dedicated stock-token product is planned, not promised, and the issuer can block or pause at any time.

The OTC deskA signature, a link, then one call that moves both sides.