Skip to main content

Keeper System

Keepers are off-chain agents that monitor the OrderManager for executable orders and submit transactions to execute them. They are the engine that drives automated TWAP and VWAP execution.

Keeper Role and Incentives

What Keepers Do

Keepers watch for active orders, check execution conditions, and submit execute_order() or execute_vwap_order() transactions when conditions are met.

How Keepers Earn

Each successful execution earns the keeper a fee paid from the order’s fee reserve. The fee per execution is fee_reserve_amount / num_chunks.

Fee Mechanism

The fee system ensures keepers are compensated for gas costs and operational overhead.
1

Fee Reserve Deposit

When creating an order, the vault owner deposits a fee reserve in the fee token (typically native XLM). The minimum reserve is min_fee_per_execution * num_chunks.
2

Per-Execution Payment

After each successful chunk execution, the OrderManager transfers fee_per_execution from its balance to the keeper’s address.
3

Refund on Completion

When an order completes or is cancelled, any unused portion of the fee reserve is refunded to the order owner. For completed orders: refund = fee_reserve - (fee_per_execution * executed_chunks).

Authorization Flow

The keeper system uses a layered authorization model to ensure security.
Keeper (require_auth)
  └─▶ OrderManager.execute_order()
        ├─ Updates order state (reentrancy protection)
        ├─ authorize_as_current_contract() for vault call
        └─▶ Vault.execute_keeper_swap()
              ├─ Verifies OrderManager is configured trader
              ├─ authorize_as_current_contract() for token transfer
              └─▶ Soroswap Router (swap execution)
Key security properties:
  • Keeper authentication: require_auth() on the keeper address prevents unauthorized execution and fee theft via front-running.
  • OrderManager as trader: The OrderManager must be configured as the vault’s trader to call execute_keeper_swap().
  • Pre-authorization: authorize_as_current_contract() enables nested contract calls without requiring additional user signatures.

Execution Checks

Before submitting a transaction, keepers should verify execution conditions.

TWAP: can_execute(order_id) -> bool

Returns true when:
  • Order is Active
  • Remaining amount > 0
  • Sufficient time has elapsed since the last execution (interval_seconds)

VWAP: can_execute_vwap(order_id) -> bool

Returns true when:
  • Order is Active with VWAP type
  • Remaining amount > 0
  • Sufficient time has elapsed since the last execution (min_interval_seconds)
can_execute() returns false for VWAP orders. Always use the type-specific check function.

Discovery

Keepers can discover active orders using:
  • get_active_order_ids(): Returns up to 100 active order IDs, enabling efficient polling.
  • get_order(order_id): Retrieves full order details including token pair, amounts, timing, and status.

Security Considerations

The keeper system incorporates several security patterns:
Order state (executed amount, chunk count, status) is updated before any external contract calls. This prevents reentrancy attacks where a malicious contract could re-enter the OrderManager mid-execution.
Every keeper swap enforces a min_amount_out derived from the order’s min_price parameter. The vault’s execute_keeper_swap additionally requires amount_out_min > 0.
When an execution fails, the contract emits an ExecutionFailedEvent with the order ID, keeper address, failure reason, and timestamp — providing an audit trail for debugging and monitoring.
An admin can pause all execution via set_paused(true). This blocks both order creation and execution while still allowing cancellations.