Skip to content

Orderbook merge#17

Merged
danvaneijck merged 22 commits into
mainfrom
orderbook-merge
Jun 11, 2026
Merged

Orderbook merge#17
danvaneijck merged 22 commits into
mainfrom
orderbook-merge

Conversation

@danvaneijck

Copy link
Copy Markdown
Member
  • merge the orderbook atomic swap contract into the aggregation contract
  • enable flash loan support from new choice clmm pools (whitelisted wallets)
  • gas optimizations and message shape optimizations

danvaneijck and others added 22 commits February 13, 2026 23:43
…ive 0.3.6 stack

Dependency reconciliation + cosmwasm-std 2->3 migration on the unchanged
orderbook logic, as the de-risking foundation for folding the orderbook-swap
contract into dex_aggregator (see docs/orderbook_merge_plan.md).

Deps: cosmwasm-std 3.0.7, injective-cosmwasm/math 0.3.6, injective-std 1.19,
prost 0.13, cw2 3.0, cw-storage-plus 3.0. cosmwasm-schema pinned to 2.2.2
(3.0's cw_serde demands cw-schema Schemaifier, which injective's JsonSchema-only
types don't implement). cw20 vendored into src/cw20.rs (no cw20 v3 exists; 2.0.0
conflicts with cosmwasm-std 3 via cw_utils). serde_with=3.12.0 / darling=0.20.11
pinned in Cargo.lock so the Rust-1.86 optimizer image can build the graph
(latest serde_with/darling need rustc >=1.88).

API migration: generic_err->msg; dropped the removed `abort` feature;
Coin.amount Uint128->Uint256 boundary conversions; dropped PartialEq on
ContractError (StdError is now opaque).

Verified: ./build_release.sh produces reference-types-clean wasm for both
contracts (wasm-tools validate --features=-reference-types). Dev-deps still
pull cosmwasm-std 2; `cargo test` reconciliation deferred to Step 7.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
New module contracts/dex_aggregator/src/orderbook_exec.rs, ported from the
standalone inj-orderbook-swap-contract (queries.rs/helpers.rs/types.rs). Scope
per docs/orderbook_merge_plan.md: single-market, from-source input-quantity path
only.

Kept: estimate_single_swap_execution (single market), estimate_execution_buy/
sell_from_source, get_minimum_liquidity_levels, get_average/worst_price_from_orders,
get_effective_fee_discount_rate, round_up_to_min_tick, dec_scale_factor, Scaled,
FPCoin, StepExecutionEstimate.

Dropped: SwapRoute/steps_from, multi-step route loop, *_from_target estimators,
SwapQuantityMode/SwapEstimationAmount, CurrentSwap* + SWAP_* state, exact-output.

Adaptations: aggregator always self-relays (fee discount always applied, no Config
lookup); generic_err->msg; Coin.amount Uint256 (FPDecimal: From<Uint256> so balance
reads .into() cleanly); FPCoin/StepExecutionEstimate are plain derives (not cw_serde,
no schema needed). Compiles in isolation (not yet called by contract logic); 9 ported
unit tests pass via `cargo test -p dex_aggregator --lib orderbook_exec`.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Fold inj-orderbook-swap-contract execution into the aggregator so orderbook
hops place Injective atomic SpotOrders directly instead of calling an external
swap contract. Treated as a new contract version (no back-compat): the ABI takes
the full market-derived redesign, not the offer_denom fallback.

- ABI (msg.rs): OrderbookSwapOp { market_id, target_denom, quantity?, worst_price? };
  removed swap_contract/offer_asset_info/ask_asset_info/min_quantity_tick_size and
  the dead external-contract `orderbook` message module.
- orderbook_exec.rs: load_market, offer_denom_for, is_buy_for_target,
  build_swap_order_msg (direct vs estimation mode), parse_order_output (typed
  MsgCreateSpotMarketOrderResponse decode, descale 10^18).
- execute.rs: orderbook arm builds a native SpotOrder (self-relayer, contract
  default subaccount); validates offer denom vs market (InvalidOrderbookDenom);
  zero qty => AmountTooSmall.
- reply.rs: typed order-response decode for orderbook ops (event parse kept for
  AMM/CLMM); orderbook hops skip the FEE_MAP/addr_validate fee step; querier
  threaded into get_operation_input/plan_next_stage to derive the offer denom.
- query.rs + contract.rs: query entry point now Deps<InjectiveQueryWrapper>
  (into_empty for non-simulate handlers); sim orderbook arm shares
  estimate_single_swap_execution with execution (sim/exec parity).
- error.rs: AmountTooSmall, OrderResponseDecode, InvalidOrderbookDenom.

cargo build + clippy + 15 lib tests green. Step 7 (integration tests) pending.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Resolve the dev-dep conflict and convert the native (INJ/USDT) orderbook
integration tests to real test-tube spot markets. test-tube was already latest
(1.19.0) on cosmwasm-std 3; the sole cosmwasm-std-2 source was cw20-base 2.0.0
(dev-dep) — dropped from both crates, cw20 test message types vendored locally.

- tests/integration.rs: ported live-market scaffolding from the orderbook merge
  proof (gov min-notional registration, spot market launch, maker seeding, tob,
  scaling helpers). setup() now launches a seeded INJ/USDT market; all setup #1
  orderbook hops use the new ABI against it. Recalibrated assertions to real
  fills; fixed cosmwasm-std 2->3 Coin.amount (Uint256) fallout throughout.
  => 23 integration tests pass, 7 ignored.
- orderbook_exec.rs: BUG FIX — size BUY orders with the GROSS atomic taker fee.
  The chain reserves the gross fee as order margin, but sizing used the net fee
  (after the relayer-share discount), over-committing the held quote by ~0.1% and
  getting rejected ("insufficient funds"). Sells keep the net fee for output.
- 7 setup #2 (reconciliation) tests #[ignore]d: their markets use a runtime
  cw20-adapter tokenfactory denom; live spot markets for runtime denoms are an
  open item. ABI already converted; only the market wiring is pending.

artifacts rebuilt. cargo build + clippy + 15 lib tests + 23 integration tests green.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Convert the remaining 7 reconciliation tests to real spot markets and un-ignore
them. Their orderbook hops trade a runtime cw20-adapter tokenfactory denom
(factory/{adapter}/{shroom}).

Finding: test-tube spot markets launch + trade fine on a RUNTIME factory denom —
no genesis decimals registration needed (the launch base_decimals/quote_decimals
params suffice); only a gov min-notional for the denom is required, submitted
after the adapter creates it.

- setup_for_conversion_test: register inj/usdt decimals, wrap cw20->native SHROOM,
  register min-notionals (incl. the factory denom), launch INJ/USDT + INJ/SHROOM +
  USDT/SHROOM (orientations chosen for integer seed prices), seed each book from a
  funded maker. Removed the dead mock orderbook contracts.
- Recalibrated all setup #2 assertions to real fills (the mock's round-number
  outputs hid the orderbook taker fee).
- Lowered the validator proposal-deposit top-up in register_min_notionals so
  setup #2's 1M-INJ admin can afford it.

cargo test -p dex_aggregator: 15 lib + 30 integration tests pass, 0 ignored.
cargo clippy --tests clean.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The buy-side estimator's margin check guards real execution (the atomic order
debits the contract's subaccount, so it must hold enough quote). In simulation
(SimulateRoute) no funds are sent, so the check would force callers to pre-seed
the aggregator with the quote denom just to get a read-only quote — the residual
of the old standalone contract's "buffer funds" requirement.

Skip the check (and the balance query) when is_simulation. Execution behavior is
unchanged. Adds test_simulate_route_orderbook_buy_needs_no_buffer: SimulateRoute
on a buy orderbook hop returns a real quote with the aggregator holding 0 usdt.

15 lib + 31 integration tests pass, 0 ignored; clippy clean.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@danvaneijck danvaneijck merged commit 1f70a26 into main Jun 11, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant