Introduction

Limit and stop orders for SaucerSwap V2 on Hedera, with no keeper bot. A Scaffold-HBAR template: Foundry contracts and a Next.js frontend for Hedera testnet.

Placing a stop-loss in the UI and watching the Hedera Schedule Service fill it, with the order's mirror-node trail

Live on testnet: a 0.1 DAI stop-loss placed in the browser, filled by the Schedule Service with no bot, and its trail on the order page — every step links to HashScan.

You escrow tokens in OrderVault together with a small HBAR budget. The vault mints you an HTS NFT that is the order, and asks the Hedera Schedule Service to call it back. From then on the network itself runs a sweep over each market. Each sweep waits as long as the price needs to reach the nearest trigger, and fills orders whose trigger is met, but only while a guard confirms the pool's TWAP agrees with Chainlink. Nothing off-chain has to stay online.

Sequence diagram between Maker, OrderVault, Schedule Service, Chainlink + pool TWAP, SaucerSwap V2.
Hedera serviceWhat it does here
Schedule Service, 0x16b (HIP-1215)The vault schedules each market's next sweep itself and pays for it from order budgets. No bot, no cron.
Token Service, 0x167Each order is an NFT in a collection the vault controls. Whoever holds the NFT can cancel and receives the fill; the vault wipes it at settlement.
Exchange rate, 0x168Converts gas priced in USD cents to tinybar, so budgets follow the live HBAR rate.
Mirror nodeThe frontend reads order history, NFT holdings and associations from it; no indexer to run.

See it work on testnet

The vault is 0.0.10792085 (0xba9c496d229b9868a804c2bcfbeac97e2bad1b1d) and its order NFTs are 0.0.10792086. Every row below was executed on testnet and is checked on the mirror node by node scripts/gate-check.mjs --proofs-only. "Scheduled" means the transaction was run by the Schedule Service, not sent by anyone.

What happenedTransaction
Stop-loss filled by the Schedule Service. Order #5 (sell 0.015 DAI at or below 1.0000) placed, then filled on the next scheduled sweep: 0.015026 USDC out against a 0.014849 minimum, Chainlink 0.99999, pool TWAP 1.00230placed 1790771452.123758104, filled (scheduled) 1790771751.009135530
The same through the frontend. Order #7 placed on the Trade page with a browser wallet (0.1 DAI stop-loss), filled by the next scheduled sweep: 0.100175 USDC out against a 0.099498 minimumplaced 1790772299.588606025, filled (scheduled) 1790772599.101466208
Guard refuses a manipulated-looking pool. Order #6's trigger was met, but the HBAR/USDC pool TWAP (2.0179) was ~18x Chainlink (0.1087), so the fill was held; the retry backed off from 5 to 10 minheld (scheduled) 1790771913.055173208 and 1790772511.027870104
Orders share a sweep. One scheduled sweep charged three open orders (#1, #2 and #5) in a single run, filling #5 and checking #1 and #2, so each paid a fraction of the fixed scheduling cost(scheduled) 1790771751.009135530
Budget runs out, top-up resumes checks. Order #8 was checked until its budget reached the reserve; a scheduled sweep parked it and scheduled nothing further. A 5 HBAR top-up revived it, and the next scheduled sweep charged it againparked (scheduled) 1790775946.023710208, top-up 1790776029.788091104, resumed (scheduled) 1790776544.055239569
Cancel by the NFT holder. Order #6 cancelled by its holder; 1 HBAR of escrow and 9.24 HBAR of unused budget refunded1790772562.437845316
The order follows its NFT. Order #4's NFT was transferred to another account; the original owner's cancel would revert with NotHolder, and the new holder cancels and receives the refundtransfer 1790771563.811651187, cancel by the new holder 1790771572.723588640
Keeperless recovery when the network is congested. A third party saturated the Schedule Service's per-second gas capacity, so a scheduled sweep could not rebook and the market stalled; anyone can heal it, and a third account's permissionless restartSweep resumed the chainstalled (scheduled) 1790777291.060748804, restarted by a third account 1790777389.880901398

The frontend ships pointed at this vault, so yarn next:dev works without deploying anything. It runs the exact contracts in this repo — every fix included — and was endowed with a payer float so its keeper stays funded; a residual stall is recoverable by anyone with restartSweep.

From README.md at v1.1 (6ddd9a3) · View source

On this page