Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
ac4d035
Add pallet-derivatives: 30-day longs and shorts on subnet alpha (spec…
unarbos Sep 2, 2026
14136ed
Derive the derivatives pallet hotkey at upgrade time; make open its o…
unarbos Sep 2, 2026
53380b8
Regenerate SDK metadata bindings for spec 453 and classify the deriva…
unarbos Sep 2, 2026
186ebc3
Run roll in one storage layer so a failed reopen restores the old pos…
unarbos Sep 2, 2026
3529274
Regenerate close-derivative doc anchor after the roll layer shift.
unarbos Sep 2, 2026
7e0b626
Derivatives: TAO-only cushions.
unarbos Sep 3, 2026
2c69d15
CI: accept RUSTSEC-2026-0269 and patch fast-uri in the docs-preview l…
unarbos Sep 4, 2026
231706f
Rebase on main: spec_version 454, release page v454.
unarbos Sep 4, 2026
a7bc0a7
Derivatives: per-side leverage, size-scaled fees, per-subnet overrides.
unarbos Sep 4, 2026
703b135
Rebase on main: spec_version 455, release page v455, regenerated docs.
unarbos Sep 4, 2026
4da9a6e
Derivatives: owner-chosen leverage under a per-side ceiling.
unarbos Sep 7, 2026
46ac22a
Derivatives: one position per subnet, one `add` call.
unarbos Sep 7, 2026
af6f62f
Emission price ignores open longs.
unarbos Sep 7, 2026
49294a0
Dissolution settles positions at the dissolution price, seniors first
unarbos Sep 7, 2026
9b1ed42
Dissolution closes every position as one net swap at one price
unarbos Sep 7, 2026
edbb179
Derivatives: one fee rate on exposure, a 90-day term, and rolls
unarbos Sep 8, 2026
7cfca5f
Merge main (release 455): spec_version 456, release page v456, regene…
unarbos Sep 8, 2026
560f1b0
derivatives: no expiry; one yearly rent on both sides
unarbos Sep 9, 2026
fe5133b
derivatives: two parameters, weekly interest as buy pressure, owner-o…
unarbos Sep 10, 2026
5bd9563
derivatives docs: spell out how positions close, weekly interest, and…
unarbos Sep 12, 2026
f121680
derivatives: document the dissolution settlement contract in rustdoc
unarbos Sep 12, 2026
5293172
derivatives docs: what happens when the subnet is deregistered
unarbos Sep 12, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions .github/docs-preview-vercel/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions .github/docs-preview-vercel/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
},
"ajv": "8.18.0",
"brace-expansion": "5.0.9",
"fast-uri": "3.1.7",
"js-yaml": "4.3.1",
"minimatch": "10.2.5",
"path-to-regexp": "8.4.2",
Expand Down
6 changes: 5 additions & 1 deletion .github/workflows/cargo-audit.yml
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,9 @@ jobs:
# RUSTSEC-2026-0258: h2 unbounded empty DATA frames. Fix is
# >=0.4.16; we still carry 0.3.27 (no 0.3 patch) via hyper in the
# fork tree — revisit when that stack moves off h2 0.3.
# RUSTSEC-2026-0269: wasmtime 8.0.1 filesystem sandbox escape via
# trailing slashes in WASI paths. We never expose a filesystem to
# the runtime WASM; same pin as the wasmtime entries above.
cargo audit --ignore RUSTSEC-2023-0091 \
--ignore RUSTSEC-2024-0438 \
--ignore RUSTSEC-2025-0009 \
Expand Down Expand Up @@ -103,4 +106,5 @@ jobs:
--ignore RUSTSEC-2025-0020 \
--ignore RUSTSEC-2026-0177 \
--ignore RUSTSEC-2026-0235 \
--ignore RUSTSEC-2026-0258
--ignore RUSTSEC-2026-0258 \
--ignore RUSTSEC-2026-0269
36 changes: 36 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ useless_conversion = "allow" # until polkadot is patched
pallet-alpha-assets = { path = "pallets/alpha-assets", default-features = false }
node-subtensor-runtime = { path = "runtime", default-features = false }
pallet-admin-utils = { path = "pallets/admin-utils", default-features = false }
pallet-derivatives = { path = "pallets/derivatives", default-features = false }
pallet-limit-orders = { path = "pallets/limit-orders", default-features = false }
pallet-commitments = { path = "pallets/commitments", default-features = false }
pallet-crowdloan = { path = "pallets/crowdloan", default-features = false }
Expand Down
12 changes: 8 additions & 4 deletions chain-extensions/src/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,9 @@ use sp_runtime::{
traits::{BlakeTwo256, Convert, IdentityLookup},
};
use sp_std::{cell::RefCell, cmp::Ordering, sync::OnceLock};
use subtensor_runtime_common::{AlphaBalance, AuthorshipInfo, NetUid, Saturating, TaoBalance};
use subtensor_runtime_common::{
AlphaBalance, AuthorshipInfo, NetUid, Saturating, SubnetDissolveHook, TaoBalance,
};

type Block = frame_system::mocking::MockBlock<Test>;

Expand Down Expand Up @@ -425,6 +427,7 @@ impl pallet_subtensor::Config for Test {
type Yuma3On = InitialYuma3On;
type Preimages = Preimage;
type AlphaAssets = AlphaAssets;
type Derivatives = ();
type InitialColdkeySwapAnnouncementDelay = InitialColdkeySwapAnnouncementDelay;
type InitialColdkeySwapReannouncementDelay = InitialColdkeySwapReannouncementDelay;
type InitialDissolveNetworkScheduleDuration = InitialDissolveNetworkScheduleDuration;
Expand Down Expand Up @@ -478,14 +481,15 @@ impl PrivilegeCmp<OriginCaller> for OriginPrivilegeCmp {
}

pub struct CommitmentsI;
impl CommitmentsInterface<AccountId> for CommitmentsI {
fn purge_netuid(
impl SubnetDissolveHook for CommitmentsI {
fn on_subnet_dissolve(
_netuid: NetUid,
_weight_meter: &mut frame_support::weights::WeightMeter,
) -> bool {
true
}

}
impl CommitmentsInterface<AccountId> for CommitmentsI {
fn purge_neuron(_netuid: NetUid, _account: &AccountId) {}
}

Expand Down
35 changes: 35 additions & 0 deletions common/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,41 @@ pub trait AuthorshipInfo<AccountId> {
fn author() -> Option<AccountId>;
}

/// Metered, resumable cleanup of a pallet's per-subnet state while that subnet is dissolved.
/// Each implementer runs in its own `pallet-subtensor` dissolution phase, so the order between
/// hooks is fixed there, not here.
pub trait SubnetDissolveHook {
/// Clean up everything held on `netuid`, consuming weight from `meter`.
///
/// Returns `true` once nothing remains for this subnet, `false` when the caller must call
/// again in a later block because the weight budget ran out.
fn on_subnet_dissolve(netuid: NetUid, meter: &mut WeightMeter) -> bool;
}

impl SubnetDissolveHook for () {
fn on_subnet_dissolve(_netuid: NetUid, _meter: &mut WeightMeter) -> bool {
true
}
}

/// What a derivatives pallet holds against a subnet's pool, as `pallet-subtensor` needs to see
/// it. Use `()` when no such pallet is wired.
pub trait DerivativesHook: SubnetDissolveHook {
/// Alpha the pool on `netuid` would hold if every open long handed its slice back in kind.
///
/// A long lifts a slice of both reserves and spends the lifted TAO on alpha, so the pool
/// keeps its TAO and is short exactly this much alpha while the long is open. Emission
/// weights add it back before pricing the subnet, so a long cannot buy emission for its
/// own subnet. Shorts are not adjusted for: a short lowers the price on purpose.
fn long_alpha_outstanding(netuid: NetUid) -> AlphaBalance;
}

impl DerivativesHook for () {
fn long_alpha_outstanding(_netuid: NetUid) -> AlphaBalance {
AlphaBalance::ZERO
}
}

pub mod time {
use super::*;

Expand Down
18 changes: 18 additions & 0 deletions docs/errors/chain/BasketDepositPending.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
---
title: "BasketDepositPending"
description: "The required window has not opened yet; wait some blocks and retry"
---

{/* GENERATED by scripts/generate.py from the SDK registries — do not edit. */}

The validator has a queued root-dividend deposit that could not be settled yet, and the call would change the hotkey's root claimant base before it does. Check the pending basket deposits for the hotkey and retry once the deposit becomes executable.

Declared by the `SubtensorModule` pallet; it classifies to the semantic code [`too_early`](/docs/errors/too-early).

Declared at [`pallets/subtensor/src/macros/errors.rs#L377`](/code/pallets/subtensor/src/macros/errors.rs#L377).

## Remediation

The required window has not opened yet; wait some blocks and retry

The same explanation is available in the terminal: `btcli explain BasketDepositPending`.
4 changes: 2 additions & 2 deletions docs/errors/chain/DepositTooLow.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@ description: "Check the argument values against the operation schema"

The `deposit` argument to `create` is below the pallet's required minimum. Check the `MinimumDeposit` pallet constant and create the crowdloan with at least that initial deposit.

Declared by the `Crowdloan` pallet; it classifies to the semantic code [`invalid_argument`](/docs/errors/invalid-argument).
Declared by the `Crowdloan`, `Derivatives` pallets; it classifies to the semantic code [`invalid_argument`](/docs/errors/invalid-argument).

Declared at [`pallets/crowdloan/src/lib.rs#L241`](/code/pallets/crowdloan/src/lib.rs#L241).
Declared at [`pallets/crowdloan/src/lib.rs#L241`](/code/pallets/crowdloan/src/lib.rs#L241), [`pallets/derivatives/src/lib.rs#L233`](/code/pallets/derivatives/src/lib.rs#L233).

## Remediation

Expand Down
18 changes: 18 additions & 0 deletions docs/errors/chain/LeverageOutOfRange.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
---
title: "LeverageOutOfRange"
description: "Check the argument values against the operation schema"
---

{/* GENERATED by scripts/generate.py from the SDK registries — do not edit. */}

The requested leverage is zero or above the side's maximum: 1x for shorts, 2x for longs (`max_short_leverage` / `max_long_leverage` in `deriv params`). Pass a `--leverage` at or below it.

Declared by the `Derivatives` pallet; it classifies to the semantic code [`invalid_argument`](/docs/errors/invalid-argument).

Declared at [`pallets/derivatives/src/lib.rs#L236`](/code/pallets/derivatives/src/lib.rs#L236).

## Remediation

Check the argument values against the operation schema

The same explanation is available in the terminal: `btcli explain LeverageOutOfRange`.
18 changes: 18 additions & 0 deletions docs/errors/chain/NoPosition.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
---
title: "NoPosition"
description: "The referenced object is not on-chain; check the identifier"
---

{/* GENERATED by scripts/generate.py from the SDK registries — do not edit. */}

That owner has no position on that subnet. Check the owner and netuid against `derivative-positions`; it may already have been closed, or forfeited once its cushion could no longer pay its interest.

Declared by the `Derivatives` pallet; it classifies to the semantic code [`not_found`](/docs/errors/not-found).

Declared at [`pallets/derivatives/src/lib.rs#L231`](/code/pallets/derivatives/src/lib.rs#L231).

## Remediation

The referenced object is not on-chain; check the identifier

The same explanation is available in the terminal: `btcli explain NoPosition`.
18 changes: 18 additions & 0 deletions docs/errors/chain/PalletHotkeyUnset.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
---
title: "PalletHotkeyUnset"
description: "The required window has not opened yet; wait some blocks and retry"
---

{/* GENERATED by scripts/generate.py from the SDK registries — do not edit. */}

The pallet has not claimed its custody hotkey yet, so nothing can be added. Check `Derivatives.PalletHotkey`; it is set by `on_runtime_upgrade` in the upgrade block.

Declared by the `Derivatives` pallet; it classifies to the semantic code [`too_early`](/docs/errors/too-early).

Declared at [`pallets/derivatives/src/lib.rs#L243`](/code/pallets/derivatives/src/lib.rs#L243).

## Remediation

The required window has not opened yet; wait some blocks and retry

The same explanation is available in the terminal: `btcli explain PalletHotkeyUnset`.
18 changes: 18 additions & 0 deletions docs/errors/chain/PoolCapExceeded.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
---
title: "PoolCapExceeded"
description: "A chain-side capacity limit was hit; reduce the size or count of the request"
---

{/* GENERATED by scripts/generate.py from the SDK registries — do not edit. */}

Open positions of this side would together borrow more than `pool_share` of the lent reserve, or the deposit alone would take the whole pool. A `pool_share` of zero means root has paused new positions. Check `deriv params`; try a smaller deposit or wait for other positions to close.

Declared by the `Derivatives` pallet; it classifies to the semantic code [`limit_exceeded`](/docs/errors/limit-exceeded).

Declared at [`pallets/derivatives/src/lib.rs#L241`](/code/pallets/derivatives/src/lib.rs#L241).

## Remediation

A chain-side capacity limit was hit; reduce the size or count of the request

The same explanation is available in the terminal: `btcli explain PoolCapExceeded`.
2 changes: 1 addition & 1 deletion docs/errors/chain/RootClaimTooHeavy.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ description: "A chain-side capacity limit was hit; reduce the size or count of t

{/* GENERATED by scripts/generate.py from the SDK registries — do not edit. */}

A root claim would walk more work than the fixed pre-dispatch weight envelope can admit. For coldkey-wide `claim_root`, hotkeys times existing networks or total basket rows can exceed `MAX_ROOT_CLAIM_WORK`; a single validator basket with too many rows can also make `claim_root_with_hotkey` fail. Split a coldkey-wide claim by validator where that fits, and investigate or consolidate an individually oversized basket.
A root claim would process more than the fixed 256-unit admission envelope. Only root-relevant validator hotkeys and their stored basket rows count as claim work; classifying the staking-hotkey relationship vector is separately capped at 256. Unrelated subnet stakes are not multiplied by the total network count. Split a coldkey-wide claim by validator where that fits, and investigate or consolidate an individually oversized basket.

Declared by the `SubtensorModule` pallet; it classifies to the semantic code [`limit_exceeded`](/docs/errors/limit-exceeded).

Expand Down
18 changes: 18 additions & 0 deletions docs/errors/chain/SubnetNotDynamic.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
---
title: "SubnetNotDynamic"
description: "The subnet is not active yet; wait for start_call"
---

{/* GENERATED by scripts/generate.py from the SDK registries — do not edit. */}

The subnet does not exist, is not AMM-priced, has its subtoken disabled, or has an empty reserve. Check the subnet exists and that `subnets show` reports a live pool.

Declared by the `Derivatives` pallet; it classifies to the semantic code [`subtoken_disabled`](/docs/errors/subtoken-disabled).

Declared at [`pallets/derivatives/src/lib.rs#L229`](/code/pallets/derivatives/src/lib.rs#L229).

## Remediation

The subnet is not active yet; wait for start_call

The same explanation is available in the terminal: `btcli explain SubnetNotDynamic`.
18 changes: 18 additions & 0 deletions docs/errors/chain/ZeroExposure.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
---
title: "ZeroExposure"
description: "Check the argument values against the operation schema"
---

{/* GENERATED by scripts/generate.py from the SDK registries — do not edit. */}

Leverage times the deposit rounds to nothing against the pool reserve, or the pool would swap the lifted slice for nothing. Use a larger deposit relative to the pool.

Declared by the `Derivatives` pallet; it classifies to the semantic code [`invalid_argument`](/docs/errors/invalid-argument).

Declared at [`pallets/derivatives/src/lib.rs#L238`](/code/pallets/derivatives/src/lib.rs#L238).

## Remediation

Check the argument values against the operation schema

The same explanation is available in the terminal: `btcli explain ZeroExposure`.
Loading
Loading