ADR-0006 · three layers · one choke
Riddler actor model
Decision expresses constraints. Execution never asks. Oracle never initiates. The only on-chain
door is ExecutionFabric.submit/3 . Xochi is a venue, not a wallet inside the fabric.
OTP · Elixir · Rust NIF
flags default off
Anvil recovery: hash persisted, then respawn
Ingress · venues
who may ask · not who may broadcast
Primary · cash-positive
Xochi
/xochi/quote · execute · claim. Stealth 4337 dest. 0.10–0.30% + solver margin.
outside Fabric · own HTTP path
Open intents · fill profit
Li.Fi
ERC-7683 order server. Exclusive window, then anyone. Landlord of wallet expression, not of settlement.
ENABLE_LIFI
SpokePool fills
Across
Deposit events → fill. Refund claimer + executor monitor when armed.
ENABLE_ACROSS
B2B loss-leader
Commerce
CCTP / Mercury. Coinbase flat often misses gas. Do not route public traffic here.
machine deferred
Decision · lifecycle machines
:transient · checkpoint · never RPC
per deposit
IntentMachine
Profitable? Fill? What gas budget? Six parallel regions. Monitors Transaction {:finalized,_}.
deposit
fill
evaluation
settlement
confirmation
finalization
per operation
RebalancingMachine
Which bridge, what amount, retry which route. Spawned by PositionManager at broadcast time.
execution
confirmation
bridge adapter
per order · deferred
CommerceMachine
Quote, address, settle, sweep, refund. Same CCTPBridge module. Not on the live path.
per token · reactive
PositionManager
Shadow ledger. Subscribes to projected/confirmed balances, prices, fills. Spawns RM before confirmation.
USDC
USDT
WETH
▼
▼
▼
▼
the gate
ExecutionFabric.submit(chain_id, tx_params, constraints)
typed errors · no questions
role · max_gas · max_total_cost_usd · timeout · finality · mev · idempotency_key
→ {:ok, %{nonce, tx_pid}} | {:error, atom}
Execution · resource actors
permanent · serialize access · only this layer touches RPC for state-changing ops
per chain
WalletPool
Select by role, capability, available balance, pending count. Emits wallet:available .
per chain × address · nonce owner
Wallet
chain × 0x…
owns the nonce
Redis session lock
WAL before broadcast
Broadcast choke
three views
balance
confirmedon-chain
projectedat send
availablefor next
fail-closed
if lock dies
local-only opt-in
else :locked_out
no silent fallback
per nonce slot · :temporary
Transaction
One actor, every confirmation path. Parent machines monitor the pid.
broadcast → persist hash to RecoveryStore
included → {:tx_included, nonce, receipt}
finalized → {:DOWN, …, {:finalized, receipt}}
Oracle · feeds upward
never initiate · PubSub is best-effort · watchdog catches misses
singleton
PriceOracle
Axol → Llama → Chainlink → Pyth → CoinGecko → cache.
{:gradient_invalidated, token}
per chain
GasOracle
L1 / OP-stack / Arbitrum strategies. Live-fetch on stale.
{:gas_price_changed, chain}
ETS
EventBus
subscribe(topic, pid). Store publish notifies Price/Gas.
direct send when consumer known
per chain
BalanceReconciler
Chain-state vs shadow ledger. Drift is accusation, not authority.
accuses Wallet, does not replace it
singleton
BridgeHealth
Per bridge × route. Decision reads; this layer never routes.
health only
infrastructure
RecoveryStore
Checkpoint journal for lifecycle machines and in-flight Transaction. After broadcast, hash is written before
any crash hook. Local-only bootstrap scans prefix and respawns; :already_started counts as
recovered. Anvil 31337: 3/3 twice.
reactive cascade
Broadcast, not confirm
IntentMachine fills on Base
Wallet projects USDC down now
PositionManager evaluates immediately
RebalancingMachine starts before the receipt
canary · all default off
Flags
ENABLE_EXECUTION_FABRIC =false
EXECUTION_FABRIC_CANARY_REBALANCING
INTENT_MACHINE_ENABLED + _SHADOW
POSITION_MANAGER_ENABLED =false
decision ↛ chain · execution ↛ policy · oracle ↛ action
live law · CCTPBridge independent · AcrossRefundProcessor not remounted · Tron
NoncePool out of scope
https://claude.ai/share/daecaabc-9177-4c6f-b908-c53386303697