Invariants
The guarantees Lorenz enforces: what each guarantees, where it is enforced, and how it is verified, both on-chain (I1–I5) and off-chain (O1–O5).
These are the guarantees Lorenz enforces. Each lists what it guarantees, where it is enforced, and how it is verified. The point of writing them down is that a reviewer can check each one against the code.
On-chain invariants (programs/executor/src/lib.rs)
These hold at runtime regardless of the off-chain bot's behaviour. This is the core of the auditability story: the chain refuses violations.
I1: Atomic-or-revert
The full arbitrage (borrow, swap route, repay, profit check, fee) runs inside a single instruction. If any step or the profit check fails, the whole transaction reverts. The maximum loss on a failed attempt is therefore the network/priority fees and any Jito tip, never the notional.
- Enforced by: single-instruction design of
execute_arbitrage+ Solana transaction atomicity.
I2: No loss (profit floor)
Settlement requires balance_after >= balance_before + min_profit, with
min_profit >= 0.
- Enforced by: the
profit = balance_after.checked_sub(balance_before)/require!(profit >= min_profit, ...)block inexecute_arbitrage.
I3: Bounded spend
notional <= vault.spend_cap.
- Enforced by:
require!(notional <= vault.spend_cap, SpendCapExceeded).
I4: Scoped authority
The bot authority can invoke execute_arbitrage but can never withdraw funds.
Only the vault owner can call withdraw.
- Enforced by: separate
ExecuteArbitrage(signed bybot_authority) andWithdraw(signed byowner, withhas_one = owner) account contexts.
I5: Transparent, capped fee
The protocol fee is exactly fee_bps of realized profit, fee_bps <= 1000
(10% hard ceiling), paid on-chain to a fixed account recorded at vault init.
- Enforced by:
require!(fee_bps <= MAX_FEE_BPS, ...)at init and the fee transfer inexecute_arbitrage.
Off-chain invariants (crates/)
These keep the engine honest and reproducible even though they are not trust-critical (the chain is the backstop).
O1: Integer settlement math
Output amounts are computed in integer arithmetic; floating point is used only for analytics/edge-weights, never for amounts that settle.
- Verified by:
lorenz-ammproperty tests (output_bounded_by_reserve,monotonic_in_input,no_free_money_single_hop).
O2: Strict config
Unknown configuration keys are rejected, so a typo cannot silently disable a feature.
- Verified by:
lorenz_core::configdeny_unknown_fields+ theunknown_key_is_rejectedtest. (This is a direct fix for a real failure mode observed in a prior project.)
O3: Agent can only tighten, and LLM output is clamped
The control plane can lower limits but never raise them above the configured ceiling. An LLM may only return one action from a closed set, and the orchestrator clamps every value before applying it: a hallucinated request to widen a cap or raise a fee is clamped to the ceiling, not honored.
- Verified by:
RuleBasedRiskManager::tighten_capclamping (agent_cannot_widen_cap_beyond_ceiling),HeuristicTunerceiling tests, and the orchestrator tests (agent_cap_request_is_clamped_to_ceiling,agent_params_are_clamped_to_ceiling).
O4: Shared cost model
The backtester and the live engine use the same cost model and config types, so simulated economics cannot be quietly more optimistic than production.
- Verified by: both consuming
lorenz_core::config::CostConfig.
O5: Auditable decisions
Every control-plane action is recorded append-only with a rationale.
- Verified by:
DecisionLedgerhas no mutate/delete API;ledgertests.
11. Glossary
Terms used throughout the Lorenz codebase and docs: domain & finance, Solana / on-chain concepts, Lorenz architecture vocabulary, and a quick reference for invariant IDs.
Security
Lorenz threat model, key handling practices, and how to report a vulnerability. The software is experimental and unaudited; not for use with real funds.