Skip to content

Pallet advanced limit orders#2554

Draft
girazoki wants to merge 31 commits intoopentensor:devnet-readyfrom
girazoki:girazoki-palle-advanced-orders
Draft

Pallet advanced limit orders#2554
girazoki wants to merge 31 commits intoopentensor:devnet-readyfrom
girazoki:girazoki-palle-advanced-orders

Conversation

@girazoki
Copy link
Copy Markdown

@girazoki girazoki commented Apr 1, 2026

Description

Introduces pallet-limit-orders, a new FRAME pallet that allows users to sign limit orders off-chain and have relayers submit them on-chain. Orders are executed against subnet AMM pools, supporting three order types: LimitBuy, TakeProfit, and StopLoss.

Two execution paths:

  • execute_orders — processes orders individually, best-effort. Invalid/expired/price-unmet orders are silently skipped; the call always returns Ok.
  • execute_batched_orders(netuid, orders) — atomic batch for a single subnet. Nets buy and sell sides before touching the AMM pool (reduced price impact). Fails the entire call if any order
    is invalid.

Validation enforced on both paths:

  • Sr25519-only signatures (Ed25519|ECDSA rejected for now, there is a possibility to add in the future)
  • Expiry checks against wall-clock time (pallet_timestamp).
  • Price condition checks against current AMM spot price.
  • Minimum stake enforcement (delegated to pallet_subtensor) per order, but not applicable for inner-pallet operations
  • Hotkey–coldkey association required for order creators, but not for the inner pallet for now (although can be added).
  • SubtokenEnabled must be true for the target subnet.
  • Root netuid (0) explicitly blocked.

Fee model: per-order fee_rate: Perbill + fee_recipient: AccountId fields on the order struct. No global protocol fee. Fees are batched per unique recipient and transferred in a single call per recipient at the end of each batch. Enables flexibility of fee-percentage and fee-account per order.

Replay protection: executed and cancelled orders are written to Orders: StorageMap<H256, OrderStatus> by their blake2_256 hash.


Open questions / TODOs

  • LastColdkeyHotkeyStakeBlock on pallet intermediary account — when execute_batched_orders transfers alpha from sellers into the pallet intermediary account, should LastColdkeyHotkeyStakeBlock be updated for the pallet account? If the block tracking is used for rate-limiting or cooldown enforcement, intermediate transfers through the pallet account could trigger unintended restrictions on subsequent operations in the same block.

  • Hotkey ownership verification for the pallet intermediary — the pallet intermediary account stakes/unstakes via PalletHotkey without going through the normal hotkey–coldkey association checks. Should we add an explicit ownership or registration check, or is the pallet account's privileged position sufficient justification to bypass it?

  • Auto-associate PalletHotkey with the pallet coldkey on first use — if the pallet hotkey is not yet registered/associated with the pallet's derived coldkey, another cold-key could potentially claim the hotkey being used by the pallet.

  • TypeScript / e2e tests — no TypeScript integration tests yet. These should cover: order signing, relayer submission flow, fee collection, and the batched netting path against a live node.

  • Since it's a complex feature, I would like to add isPalletEnabled storage item, initially set to false, so that it can be enabled in testnet but not in mainnet

  • Benchmarks

Type of Change

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • Documentation update
  • Other (please describe):

Checklist

  • I have performed a self-review of my own code
  • I have commented my code, particularly in hard-to-understand areas
  • I have run ./scripts/fix_rust.sh to ensure my code is formatted and linted correctly
  • I have made corresponding changes to the documentation
  • My changes generate no new warnings
  • I have added tests that prove my fix is effective or that my feature works
  • New and existing unit tests pass locally with my changes
  • Any dependent changes have been merged and published in downstream modules

Additional Notes

I moved pallets/swap-interface to primitives/swap-interface. it was not a pallet, so I thought it belonged more there

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.

2 participants