TWAP Order
TWAP Orders — Technical Specification
This document describes the TWAP (Time-Weighted Average Price) order system built into the Rigoblock Agentic Operator. It covers the data model, execution pipeline, safety controls, and API surface for integrators interested in building on top of or integrating with TWAP execution.
What Is a TWAP Order?
A TWAP order splits a large swap into N equal-sized slices executed at regular time intervals. The goal is to reduce price impact on the DEX by spreading the trade over time rather than executing it as a single atomic swap.
A TWAP order:
Executes deterministically — no LLM judgment in the execution loop
Runs autonomously on a cron schedule (minimum 5-minute intervals)
Has a defined total amount, slice size, and duration
Supports both buy-side (exact-output) and sell-side (exact-input) semantics
Example:
"Buy 100 GRG with ETH, 20 per slice, every 5 minutes"
→ 5 slices × 20 GRG (exact-output) × 5-minute interval = completes in 25 minutes
How TWAP Orders Work
Lifecycle
Data Model
swapMeta — Slice Fill Data
When a slice executes, the build_vault_swap tool returns an UnsignedTransaction that includes a swapMeta object. The TWAP executor reads this to update the order's accounting fields (amountSpent, totalBought):
If the TWAP executor cannot read swapMeta from the returned transaction (e.g., the tool returned an error), the slice failure is recorded but amountSpent and totalBought are not updated for that slice.
This is identical to the standard swap tool call path — it goes through the same safety stack as a manually triggered swap.
Safety Controls Applied on Every TWAP Slice
1. Swap Shield (Oracle Price Protection)
Before building swap calldata, the system compares the DEX quote against the vault's on-chain BackgeoOracle TWAP price:
Uses
vault.convertTokenAmount(tokenIn, amountIn, tokenOut)— a 5-minute TWAP oracleBlocks if DEX quote is >5% worse than oracle (bad fill for the vault)
Blocks if DEX quote is >10% better than oracle (stale oracle or manipulated route)
Gracefully allows the swap when the oracle has no price feed for a token (
NO_PRICE_FEED) within vaults, this case only allows selling non-tracked tokens (i.e. airdrops or direct transfers.
This prevents TWAP orders from executing at unfavorable prices due to poor liquidity, stale DEX state, or oracle manipulation.
Swap Shield and TWAP timing: The disable_swap_shield tool sets a 10-minute TTL opt-out window. TWAP slices fire at cron time (minimum 5-minute intervals), so a disabled shield can affect subsequent slices that fire within the TTL window. The shield auto-re-enables after the TTL expires — the operator must re-disable it if they want multiple consecutive slices to bypass it. Partial shield opt-out (one slice at a time) is not supported; the TTL applies globally to the vault.
2. NAV Shield Pre-Check
Before the slice transaction is built and returned, the system atomically simulates:
If the simulated post-swap NAV drops >10% versus the pre-swap NAV (or the 24-hour baseline, whichever is higher), the slice is blocked and an error is recorded.
3. NAV Shield at Broadcast Time (auto-execute mode)
For autoExecute: true, a second NAV shield check runs inside executeTxList() immediately before the CDP-signed transaction is broadcast. This is a belt-and-suspenders check in case market conditions changed between building and broadcasting the calldata.
4. Seven-Point Execution Validation
For autoExecute: true, executeTxList() runs the full 7-point validation:
Delegation config exists and is enabled in KV
Transaction target == vault address (prevents cross-contract attacks)
Function selector is in the allowed whitelist
Agent wallet identity matches stored config
eth_callsimulation passes (pre-broadcast revert check)Agent wallet has sufficient ETH for gas - unless sponsored transaction
Gas fees within per-chain hard caps
5. Slippage Protection
Default slippage: 1% (100 bps). Configurable by the operator via:
set_default_slippagetool (persisted per operator in KV)slippageBpsfield in the chat request body
Clamped to [10, 500] bps (0.1%–5%). The LLM cannot set slippage directly.
6. Auto-Pause on Failure
After 3 consecutive slice failures, the order is automatically paused (active = false). The operator is notified via Telegram on every failure (not just on auto-pause).
Execution Context
When a TWAP slice fires at cron time, the request context is:
isBrowserRequest: false bypasses the browser auth gate (which requires a connected wallet), since TWAP slices run server-side without a browser session. Security is maintained via delegation verification in the execution pipeline.
Manual vs Autonomous Mode
Mode
autoExecute
Behavior
Manual
false (default)
LLM analyzes + builds tx, sends Telegram notification. No on-chain execution.
Autonomous
true
Builds tx + broadcasts via CDP agent wallet. Operator notified after execution.
Both modes apply the Swap Shield and NAV pre-check when building the transaction. Only autonomous mode applies the broadcast-time NAV check and 7-point validation.
For autonomous mode, the vault must have active delegation to the agent wallet on the target chain, with the execute() selector included.
KV Storage Schema
twap:{vault}
JSON array of TwapOrder[] (active + up to 20 closed)
none
twap-hwm:{vault}
Highest ID ever assigned (integer string)
none
twap-events:{vault}
JSON array of TwapEvent[] (last 20 events)
24h
TwapEvent Schema
Events are served via GET /api/strategy-events?vault=0x…&since={timestamp} and polled by the frontend to show slice history.
API Tools
TWAP orders are created and managed via the /api/chat endpoint using the following tools:
create_twap_order
create_twap_orderReturns: Confirmation message with order ID, duration, and mode.
cancel_twap_order
cancel_twap_orderlist_twap_orders
list_twap_ordersNo parameters. Returns formatted list of all orders (active and closed) with progress, amounts spent, and status.
Alias: list_strategies maps to the same handler — both names work interchangeably in the chat interface.
Fast-Path Processing
The chat agent includes a regex-based fast path for commonly phrased TWAP commands. When a message matches the fast path, the TWAP order is created directly without invoking the LLM — reducing latency and cost.
The fast path activates when the message contains both:
"every N minutes"— setsintervalMinutes"X at a time"— setssliceAmount
Examples that hit the fast path:
If neither pattern is present, the full inference path handles the request. The LLM is always invoked for ambiguous phrasing, multi-step requests, or when the user asks follow-up questions about an order.
The fast path also handles:
"list twap orders"/"list strategies"→list_twap_orders"cancel twap {id}"/"cancel all twap orders"→cancel_twap_order"enable/disable swap shield"→enable_swap_shield/disable_swap_shield
Constraints
Max active orders per vault
3
Max stored closed orders per vault
20
Minimum interval
5 minutes
Max consecutive failures before auto-pause
3
Max stored events
20 (per vault, 24h TTL)
Delegation Requirements (Autonomous Mode)
For autoExecute: true, the vault must have active on-chain delegation to the agent wallet for each function selector the TWAP executor will call.
How Rigoblock Delegation Works
Rigoblock vaults implement a granular per-selector delegation system. The vault contract maintains a permission mapping:
When a call arrives at the vault's fallback, the contract checks this mapping before forwarding the call to the appropriate adapter. If the calling address is not delegated for that selector, the call reverts.
The operator grants permissions by sending an updateDelegation(Delegation[]) transaction from their EOA (the vault owner address):
Revocation is atomic: revokeAllDelegations(agentAddress) removes all selectors for the agent in a single call.
Setting Up Delegation
Via the chat interface (browser or API):
Or programmatically:
The operator can revoke all permissions instantly at any time:
Or on-chain: pool.revokeAllDelegations(agentAddress).
EIP-7702 — Code Delegation (Pectra)
EIP-7702, introduced in Ethereum's Pectra upgrade, allows an EOA to temporarily adopt smart contract code within a single transaction. It is designed for smart-wallet use cases: a user's EOA can batch calls, pay gas in ERC-20 tokens, or execute sponsored transactions by delegating to a chosen implementation contract for the duration of one transaction.
TWAP does not use EIP-7702. The agent wallet is a CDP-managed EOA with its own signing capability — it does not need to adopt smart contract code. The delegation problem TWAP solves is different: it is not "allow this EOA to batch-call during one transaction" but rather "allow this external EOA to call specific vault functions indefinitely, until the operator revokes." That is a persistent, contract-level permission that EIP-7702 (which is transaction-scoped and EOA-level) cannot express.
EIP-7715 — Scoped Wallet Permissions (wallet_grantPermissions)
wallet_grantPermissions)EIP-7715 proposes a wallet RPC method (wallet_grantPermissions) for granting scoped permissions to dApps or agents — specifying which functions they may call, with which parameters, and under which conditions (spend limits, expiry, allowed contracts). This is the EIP that most closely resembles Rigoblock's delegation model.
Conceptual alignment:
Both are selector-scoped (specific
bytes4function signatures)Both are address-bound (permission granted to a specific agent address)
Both support revocation
Key difference in layer:
EIP-7715 operates at the wallet level — the permission is enforced by the user's wallet before it signs any transaction.
Rigoblock delegation operates at the vault contract level — the permission is enforced on-chain inside the vault's fallback function, independent of who signs or how.
As EIP-7715 matures, an operator could use it to further constrain what the agent's wallet is permitted to sign (e.g., only transactions targeting this specific vault), complementing the existing on-chain vault delegation. The two layers are not mutually exclusive — vault-level delegation remains the primary enforcement layer.
EIPs and Standards Used
EIP-191: Signed Data Standard
Used for operator authentication. When setting up TWAP orders via the chat or API, the operator must sign:
The signature is verified server-side via viem.verifyMessage(). Valid for 24 hours. Purpose: proves the caller owns the vault operator wallet, not just the x402 payer wallet.
EIP-712: Typed Structured Data Hashing (implicit)
The Rigoblock vault's updateDelegation() function uses typed structs:
When the operator sets up delegation, they sign and send updateDelegation(Delegation[]) from their EOA. This grants the agent wallet selector-level permissions.
EIP-1193: Ethereum Provider JavaScript API
The TWAP creation flow runs inside the chat agent. Actual slice execution (for autonomous mode) uses the CDP Server Wallet (Coinbase Developer Platform). CDP manages the agent's private key server-side in a TEE (Trusted Execution Environment) — the key never appears in Worker code or KV storage. The CDP account is wrapped into a viem-compatible EvmServerAccount / LocalAccount interface for signing.
For manual mode, the slice transaction is returned as unsigned calldata (same as all other vault transactions) and the operator signs it via their connected wallet using the standard eth_sendTransaction call.
x402: HTTP Micropayments (RFC Draft)
TWAP orders are created via the /api/chat endpoint, which is x402-gated at $0.015 USDC per request (paid on Base mainnet). The x402 payment is an API access fee — it does NOT authorize vault operations. Vault authorization requires a separate operator signature (EIP-191) AND active on-chain delegation. These are completely independent layers: a request may have x402 payment without operator auth (anonymous mode, receives unsigned calldata only) or both (full access including delegated execution).
See AGENTS.md for full x402 setup instructions.
Observability
Telegram Notifications
If Telegram is paired (/api/telegram/pair), the operator receives:
Per-slice execution (autonomous mode): swap amounts, progress fraction, tx link
Order completion: total spent/bought summary
Slice failure: error message + Tenderly debug calldata (to/from/value/data)
Auto-pause: notification when 3 consecutive failures occur
Strategy Events Polling
Returns:
Security Properties
TWAP orders cannot:
Execute without delegation
Agent wallet only has whitelisted selectors
Execute a swap that drops NAV >10%
NAV shield blocked at build AND broadcast time
Execute at an unfavorable price
Swap Shield compares against on-chain TWAP oracle
Call arbitrary contracts
Transaction target must equal vault address
Exceed gas caps
Hard-coded per-chain gas limits
The vault contract enforces these constraints on-chain, independently of the agent or TWAP scheduler code. Even a compromised Worker cannot bypass the on-chain delegation mapping.
Example: Creating a TWAP Order via x402
Direct Tool API (x402)
You can also call the create_twap_order tool directly without going through the LLM, using POST /api/tools/create_twap_order:
Comparison with Strategy System
The Rigoblock Agentic Operator also has a general strategy system (LLM-driven) where an LLM evaluates market conditions and decides whether to execute a trade. TWAP orders differ fundamentally:
Execution logic
Deterministic (always executes on schedule)
LLM judgment (may skip if conditions unfavorable)
Tool calls
Direct tool dispatch (no LLM involved)
LLM decides what to call
Latency
Low (sub-second build time)
Higher (LLM inference)
Cost
Lower (no LLM tokens on execution)
Higher (LLM tokens per run)
Flexibility
Fixed: swap at regular intervals
Flexible: any supported operation
Monitoring
Per-slice events + Telegram
Per-run recommendations + Telegram
Failure handling
Auto-pause at 3 failures
Auto-pause at 3 failures
TWAP orders are the right choice for mechanical, scheduled execution. LLM strategies are better for adaptive, market-condition-sensitive execution.
Last updated