Saga Pattern¶
The execution module implements a saga pattern for handling multi-leg arbitrage transactions with compensation logic.
Why Saga?¶
True atomicity is impossible between:
- Polymarket - Blockchain-based (Polygon)
- Kalshi - Web2 exchange (REST API)
The saga pattern provides:
- Explicit state management for distributed transactions
- Compensation logic for partial failures
- Audit trail of execution steps
State Machine¶
Location: arbiter-engine/src/execution/state_machine.rs
stateDiagram-v2
[*] --> Pending
Pending --> Leg1Initiated: Leg1Submitted
Leg1Initiated --> Leg1Filled: Leg1Confirmed
Leg1Initiated --> Failed: Leg1Failed
Leg1Filled --> Leg2Initiated: Leg2Submitted
Leg2Initiated --> Completed: Leg2Confirmed
Leg2Initiated --> Failed: Leg2Failed
Failed --> Compensating: CompensationStarted
Compensating --> Compensated: CompensationFinished
States¶
| State | Description |
|---|---|
Pending |
Initial state, no orders placed |
Leg1Initiated(Uuid) |
First leg order submitted |
Leg1Filled(FillDetails) |
First leg order filled |
Leg2Initiated(Uuid, FillDetails) |
Second leg order submitted, preserves Leg1 fill |
Completed(FillDetails, FillDetails) |
Both legs filled successfully |
Failed(FailureReason) |
Execution failed |
Compensating(HedgeStrategy, FillDetails) |
Hedge in progress |
Compensated(FillDetails, FillDetails) |
Hedge completed |
Events¶
pub enum ArbEvent {
Leg1Submitted(Uuid),
Leg1Confirmed(FillDetails),
Leg1Failed(String),
Leg2Submitted(Uuid),
Leg2Confirmed(FillDetails),
Leg2Failed(String),
CompensationStarted(HedgeStrategy),
CompensationFinished(FillDetails),
}
Failure Handling¶
Leg 1 Failure¶
If the first leg fails before filling:
- No capital is at risk
- Transition directly to
Failedstate - No compensation needed
Leg 2 Failure¶
If the second leg fails after Leg 1 fills:
- Position exists on first exchange
FillDetailspreserved in failure state- Hedge strategy triggered
- Compensation order placed to exit position
Hedge Strategies¶
Location: arbiter-engine/src/execution/hedge.rs
| Strategy | Description |
|---|---|
DumpLeg1 |
Market order to exit Leg 1 position immediately |
RetryLeg2 |
Retry the failed leg (planned) |
LimitChaseLeg2 |
Aggressive limit order chase (planned) |
Hold |
Hold position for manual intervention (planned) |
Key Safety Feature¶
The Leg2RejectedWithPosition failure reason preserves the Leg 1 FillDetails:
pub enum FailureReason {
Leg1Rejected(String),
Leg2RejectedWithPosition(String, FillDetails), // Preserves fill!
}
This ensures the hedge logic has all information needed for compensation.