Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
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
458 changes: 458 additions & 0 deletions docs/guides/evm/precompile-design.mdx

Large diffs are not rendered by default.

33 changes: 33 additions & 0 deletions docs/guides/evm/precompiles/account-balance.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
---
title: Account balance
description: Reference for the deployed BalancePrecompile.
---

| Property | Value |
|---|---|
| Rust implementation | `BalancePrecompile` |
| Solidity interface | `IBalance` |
| Address | `0x000000000000000000000000000000000000080e` |
| Status | Deployed |

## Functions

| Function | Mutability |
|---|---|
| `getFreeBalance(bytes32)` | `view` |
| `getTotalIssuance()` | `view` |

## Added operations

| Function | Source extrinsic |
|---|---|
| `burnBalance` | `Balances.burn` |
| `upgradeAccounts` | `Balances.upgrade_accounts` |

`upgradeAccounts` has an explicit input bound of 64 accounts. Both operations
dispatch the highest-level Balances call as the mapped signer and preserve all
runtime authorization and issuance invariants. Force operations require Root
and are not exposed.


Source: [`balance.sol`](https://github.com/RaoFoundation/subtensor/blob/main/precompiles/src/solidity/balance.sol)
65 changes: 65 additions & 0 deletions docs/guides/evm/precompiles/alpha.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
---
title: Alpha
description: Reference for the deployed AlphaPrecompile.
---

| Property | Value |
|---|---|
| Rust implementation | `AlphaPrecompile` |
| Solidity interface | `IAlpha` |
| Address | `0x0000000000000000000000000000000000000808` |
| Status | Deployed |

Provides typed views of subnet pools, prices, issuance, emissions, and simulated
swaps. All functions are `view`.

## Functions

```text
getAlphaPrice(uint16)
getMovingAlphaPrice(uint16)
getTaoInPool(uint16)
getAlphaInPool(uint16)
getAlphaOutPool(uint16)
getAlphaIssuance(uint16)
getTaoWeight()
simSwapTaoForAlpha(uint16,uint64)
simSwapAlphaForTao(uint16,uint64)
getSubnetMechanism(uint16)
getRootNetuid()
getEMAPriceHalvingBlocks(uint16)
getSubnetVolume(uint16)
getTaoInEmission(uint16)
getAlphaInEmission(uint16)
getAlphaOutEmission(uint16)
getSumAlphaPrice()
getCKBurn()
getEmissionAccounting(uint16,bytes32)
getSubnetEconomicState(uint16)
getSubnetFlowState(uint16)
getEmissionGateConfig()
getSwapState(uint16)
hasSwapMigrationRun(bytes)
```

Flow values use signed Solidity integers. Fixed-point economic values are
returned as their raw runtime bits. `getSwapState` includes the fee,
initialization status, balancer quote weight, and both protocol reservoirs;
the initialization flag is the generic swap-initialization view.

## Added operations

| Function | Source extrinsic |
|---|---|
| `setRecycleOrBurn` | `AdminUtils.sudo_set_recycle_or_burn` |
| `setBurnHalfLife` | `AdminUtils.sudo_set_burn_half_life` |
| `setBurnIncreaseMultiplier` | `AdminUtils.sudo_set_burn_increase_mult` |

The five deprecated `Swap` liquidity extrinsics are intentionally not proposed;
they always return the pallet's `Deprecated` error. `Swap.set_fee_rate` and the
remaining Alpha-related AdminUtils calls require Root and are not exposed.
The three listed AdminUtils calls accept a signed subnet owner; only that
signed path is exposed and runtime authorization remains in force.


Source: [`alpha.sol`](https://github.com/RaoFoundation/subtensor/blob/main/precompiles/src/solidity/alpha.sol)
37 changes: 37 additions & 0 deletions docs/guides/evm/precompiles/balance-transfer.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
---
title: Balance transfer
description: Reference for the deployed BalanceTransferPrecompile.
---

| Property | Value |
|---|---|
| Rust implementation | `BalanceTransferPrecompile` |
| Solidity interface | `ISubtensorBalanceTransfer` |
| Address | `0x0000000000000000000000000000000000000800` |
| Status | Deployed |

Transfers the EVM call value to the Substrate account supplied as a 32-byte
public key.

## Functions

| Function | Mutability |
|---|---|
| `transfer(bytes32)` | `payable` |

## Added operations

| Function | Source extrinsic |
|---|---|
| `transferKeepAlive` | `Balances.transfer_keep_alive` |
| `transferAll` | `Balances.transfer_all` |

The existing `transfer(bytes32)` semantically covers
`Balances.transfer_allow_death` by taking the amount from attached EVM value.
The added functions use explicit typed arguments where attached value does
not express the complete source operation. They dispatch the highest-level
Balances call as the mapped signer. `force_transfer` requires Root and the
feature-gated development faucet is not part of the production interface.


Source: [`balanceTransfer.sol`](https://github.com/RaoFoundation/subtensor/blob/main/precompiles/src/solidity/balanceTransfer.sol)
46 changes: 46 additions & 0 deletions docs/guides/evm/precompiles/crowdloan.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
---
title: Crowdloan
description: Reference for the deployed CrowdloanPrecompile.
---

| Property | Value |
|---|---|
| Rust implementation | `CrowdloanPrecompile` |
| Solidity interface | `ICrowdloan` |
| Address | `0x0000000000000000000000000000000000000809` |
| Status | Deployed |

## Views

```text
getCrowdloan(uint32)
getContribution(uint32,bytes32)
```

## Operations

All operations are `payable`:

```text
create(uint64,uint64,uint64,uint32,address)
contribute(uint32,uint64)
withdraw(uint32)
finalize(uint32)
refund(uint32)
dissolve(uint32)
updateMinContribution(uint32,uint64)
updateEnd(uint32,uint32)
updateCap(uint32,uint64)
```

## Added operation

| Function | Source extrinsic |
|---|---|
| `setMaxContribution` | `Crowdloan.set_max_contribution` |

The typed interface preserves the source call's optional value so the creator
can either set or clear the per-contributor maximum.


Source: [`crowdloan.sol`](https://github.com/RaoFoundation/subtensor/blob/main/precompiles/src/solidity/crowdloan.sol)
38 changes: 38 additions & 0 deletions docs/guides/evm/precompiles/drand.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
---
title: Drand
description: Typed EVM interface for stored Drand randomness.
---

| Property | Value |
|---|---|
| Implementation | `DrandPrecompile` |
| Solidity interface | `IDrand` |
| Address | `0x0000000000000000000000000000000000000810` |
| Status | Deployed |

This precompile exposes typed beacon configuration and pulse data instead
of requiring callers to construct Drand storage keys and decode SCALE values.
Contracts can use the runtime's stored randomness state deterministically
without receiving permission to configure the beacon or submit pulses.

## Views

| Function | Replaces |
|---|---|
| `getBeaconConfig()` | `Drand.BeaconConfig` |
| `getPulse(uint64 round)` | `Drand.Pulses` |
| `getStoredRoundRange()` | `Drand.OldestStoredRound` and `Drand.LastStoredRound` |
| `getNextUnsignedAt()` | `Drand.NextUnsignedAt` |
| `hasMigrationRun(bytes key)` | `Drand.HasMigrationRun` |

## State-changing operations

`Drand.set_beacon_config` and `Drand.set_oldest_stored_round` require Root, and
`Drand.write_pulse` requires `None` origin as an unsigned offchain-worker
submission. None is exposed as a typed EVM operation because doing so would
bypass the pallet's top-level origin checks.

`hasMigrationRun(bytes)` bounds the supplied key to 128 bytes before reading
storage.

Source: [`drand.sol`](https://github.com/RaoFoundation/subtensor/blob/main/precompiles/src/solidity/drand.sol)
86 changes: 86 additions & 0 deletions docs/guides/evm/precompiles/extrinsic-coverage.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
---
title: Extrinsic coverage
description: Audit of typed EVM coverage for every extrinsic in the authorized runtime pallets.
---

This audit covers the runtime's `SubtensorModule`, `AdminUtils`, `Balances`,
`Proxy`, `Scheduler`, `Drand`, `Crowdloan`, `Timestamp`, and `Swap` pallets.
Sudo and Multisig extrinsics are intentionally outside typed precompile
coverage.

Generic SCALE dispatch through the Frontier `Dispatch` precompile does not
count as typed coverage. A covered operation must have a stable Solidity
interface or an explicit proposed typed replacement.

## Coverage summary

| Pallet | Runtime extrinsics | Typed today | Proposed signed additions | Not exposed |
|---|---:|---:|---:|---:|
| `SubtensorModule` | 82 | 68 | 0 | 14 |
| `AdminUtils` | 86 | 40 | 0 | 46 |
| `Balances` | 9 | 5 | 0 | 4 |
| `Proxy` | 12 | 11 | 1 | 0 |
| `Scheduler` | 10 | 0 | 0 | 10 |
| `Drand` | 3 | 0 | 0 | 3 |
| `Crowdloan` | 10 | 10 | 0 | 0 |
| `Timestamp` | 1 | 0 | 0 | 1 |
| `Swap` | 6 | 0 | 0 | 6 |
| **Total** | **219** | **134** | **1** | **84** |

`Typed today` counts semantic coverage, not only direct dispatch to the same
Rust call. For example, `registerNetwork(bytes32)` covers basic subnet
registration by dispatching `register_network_with_identity` with empty
identity fields.

`Proposed signed additions` includes extrinsics whose highest-level pallet call
accepts a non-Root signed origin. If a call also accepts Root, only its signed
path is exposed: the mapped EVM caller is dispatched as `Signed`, and the
pallet performs its normal authorization checks.

## Signed additions

Each implemented operation is listed on the page of its target precompile:

| Target precompile | Missing extrinsics assigned |
|---|---:|
| [Subnet](/docs/guides/evm/precompiles/subnet) | 13 |
| [Staking V2](/docs/guides/evm/precompiles/staking-v2) | 20 |
| [Neuron](/docs/guides/evm/precompiles/neuron) | 21 |
| [Alpha](/docs/guides/evm/precompiles/alpha) | 3 |
| [Account balance](/docs/guides/evm/precompiles/account-balance) | 2 |
| [Proxy](/docs/guides/evm/precompiles/proxy) | 4 |
| [Balance transfer](/docs/guides/evm/precompiles/balance-transfer) | 2 |
| [Voting power](/docs/guides/evm/precompiles/voting-power) | 2 |
| [Leasing](/docs/guides/evm/precompiles/leasing) | 1 |
| [Crowdloan](/docs/guides/evm/precompiles/crowdloan) | 1 |

The only remaining proposed signed operation is `Proxy.proxy_announced`. It
requires a stable, versioned EVM description of the proxied runtime call and
must not add another SCALE-encoded `RuntimeCall` interface.

## Extrinsics not exposed as EVM calls

| Pallet extrinsic | Reason |
|---|---|
| Root-only `SubtensorModule` extrinsics | `dissolve_network`, `root_dissolve_network`, `swap_coldkey`, `sudo_set_tx_childkey_take_rate_limit`, `sudo_set_min_childkey_take`, `sudo_set_max_childkey_take`, `set_pending_childkey_cooldown`, `reset_coldkey_swap`, `sudo_set_num_root_claims`, and `sudo_set_voting_power_ema_alpha` require Root. |
| `SubtensorModule.schedule_swap_coldkey` | Deprecated compatibility call that always returns `Deprecated`. |
| `SubtensorModule.faucet` | Build-feature-only development call; it is not part of the production runtime interface. |
| `SubtensorModule.set_tempo` | Retained call-index compatibility entry point that succeeds without changing state. The real setting is exposed as `SubnetPrecompile.setTempo` through `AdminUtils.sudo_set_tempo`. |
| `SubtensorModule.set_activity_cutoff_factor` | Retained call-index compatibility entry point that succeeds without changing state. The active AdminUtils operation is already covered by `SubnetPrecompile.setActivityCutoffFactor`. |
| Root-only `AdminUtils` extrinsics | Root-only administration is not delegated to EVM callers. For calls that also accept a signed subnet owner, the domain precompile dispatches the highest-level call as the mapped EVM signer and preserves its authorization checks. |
| `AdminUtils.sudo_set_total_issuance` | Deprecated call that always returns `Deprecated`. |
| Root-only `Balances` extrinsics | `force_unreserve`, `force_transfer`, `force_set_balance`, and `force_adjust_total_issuance` require Root. |
| All `Scheduler` extrinsics | `Scheduler.ScheduleOrigin` is configured as Root in the runtime. |
| `Drand.write_pulse` | Unsigned offchain-worker submission requiring `None` origin. An EVM caller cannot satisfy that origin without changing its security model. |
| Drand configuration extrinsics | `set_beacon_config` and `set_oldest_stored_round` require Root. |
| `Timestamp.set` | Block-production inherent requiring `None` origin. Contracts already receive the same time through `block.timestamp`. |
| `Swap.set_fee_rate` | Requires Root. |
| `Swap.add_liquidity` | Permanently disabled pallet call that always returns `Deprecated`. |
| `Swap.remove_liquidity` | Permanently disabled pallet call that always returns `Deprecated`. |
| `Swap.modify_position` | Permanently disabled pallet call that always returns `Deprecated`. |
| `Swap.toggle_user_liquidity` | Permanently disabled pallet call that always returns `Deprecated`. |
| `Swap.disable_lp` | Permanently disabled pallet call that always returns `Deprecated`. |

These exclusions preserve the existing runtime origin and lifecycle semantics.
A typed precompile must not manufacture Root or `None`, call an internal helper,
or write storage directly to make one of these operations callable.
66 changes: 66 additions & 0 deletions docs/guides/evm/precompiles/index.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
---
title: Precompiles
description: Addresses, implementations, and reference pages for Bittensor EVM precompiles.
---

Bittensor precompiles are fixed-address contracts implemented by the Subtensor
runtime. `Deployed` means that the address is registered in the current runtime;
it does not imply complete coverage of the underlying runtime domain.
`Proposed` precompiles are not callable. Their documented addresses are
reserved for those domains, while their function selectors remain provisional
until the interfaces are implemented and released.

The [extrinsic coverage audit](/docs/guides/evm/precompiles/extrinsic-coverage)
tracks every runtime extrinsic in scope and identifies its deployed, proposed,
or intentionally non-callable EVM treatment.

## Ethereum and Frontier precompiles

| Precompile | Address | Status |
|---|---|---|
| `ECRecover` | <EvmAddress address="0x0000000000000000000000000000000000000001" /> | Deployed |
| `Sha256` | <EvmAddress address="0x0000000000000000000000000000000000000002" /> | Deployed |
| `Ripemd160` | <EvmAddress address="0x0000000000000000000000000000000000000003" /> | Deployed |
| `Identity` | <EvmAddress address="0x0000000000000000000000000000000000000004" /> | Deployed |
| `Modexp` | <EvmAddress address="0x0000000000000000000000000000000000000005" /> | Deployed |
| `Dispatch` | <EvmAddress address="0x0000000000000000000000000000000000000006" /> | Deployed |
| `Bn128Mul` | <EvmAddress address="0x0000000000000000000000000000000000000007" /> | Deployed |
| `Bn128Pairing` | <EvmAddress address="0x0000000000000000000000000000000000000008" /> | Deployed |
| `Bn128Add` | <EvmAddress address="0x0000000000000000000000000000000000000009" /> | Deployed |
| `Sha3FIPS256` | <EvmAddress address="0x0000000000000000000000000000000000000400" /> | Deployed |
| `ECRecoverPublicKey` | <EvmAddress address="0x0000000000000000000000000000000000000401" /> | Deployed |
| `Ed25519Verify` | <EvmAddress address="0x0000000000000000000000000000000000000402" /> | Deployed |
| `Sr25519Verify` | <EvmAddress address="0x0000000000000000000000000000000000000403" /> | Deployed |

## Bittensor precompiles

| Precompile | Solidity interface | Details |
|---|---|---|
| [`BalanceTransferPrecompile`](/docs/guides/evm/precompiles/balance-transfer) | `ISubtensorBalanceTransfer` | <EvmAddress address="0x0000000000000000000000000000000000000800" /><br />Deployed |
| [`StakingPrecompile`](/docs/guides/evm/precompiles/staking-v1) | `IStaking` V1 | <EvmAddress address="0x0000000000000000000000000000000000000801" /><br />Deployed |
| [`MetagraphPrecompile`](/docs/guides/evm/precompiles/metagraph) | `IMetagraph` | <EvmAddress address="0x0000000000000000000000000000000000000802" /><br />Deployed |
| [`SubnetPrecompile`](/docs/guides/evm/precompiles/subnet) | `ISubnet` | <EvmAddress address="0x0000000000000000000000000000000000000803" /><br />Deployed |
| [`NeuronPrecompile`](/docs/guides/evm/precompiles/neuron) | `INeuron` | <EvmAddress address="0x0000000000000000000000000000000000000804" /><br />Deployed |
| [`StakingPrecompileV2`](/docs/guides/evm/precompiles/staking-v2) | `IStaking` V2 | <EvmAddress address="0x0000000000000000000000000000000000000805" /><br />Deployed |
| [`UidLookupPrecompile`](/docs/guides/evm/precompiles/uid-lookup) | `IUidLookup` | <EvmAddress address="0x0000000000000000000000000000000000000806" /><br />Deployed |
| [`StorageQueryPrecompile`](/docs/guides/evm/precompiles/storage-query) | Selectorless | <EvmAddress address="0x0000000000000000000000000000000000000807" /><br />Deployed · deprecation planned |
| [`AlphaPrecompile`](/docs/guides/evm/precompiles/alpha) | `IAlpha` | <EvmAddress address="0x0000000000000000000000000000000000000808" /><br />Deployed |
| [`CrowdloanPrecompile`](/docs/guides/evm/precompiles/crowdloan) | `ICrowdloan` | <EvmAddress address="0x0000000000000000000000000000000000000809" /><br />Deployed |
| [`LeasingPrecompile`](/docs/guides/evm/precompiles/leasing) | `ILeasing` | <EvmAddress address="0x000000000000000000000000000000000000080a" /><br />Deployed |
| [`ProxyPrecompile`](/docs/guides/evm/precompiles/proxy) | `IProxy` | <EvmAddress address="0x000000000000000000000000000000000000080b" /><br />Deployed |
| [`AddressMappingPrecompile`](/docs/guides/evm/precompiles/address-mapping) | `IAddressMapping` | <EvmAddress address="0x000000000000000000000000000000000000080c" /><br />Deployed |
| [`VotingPowerPrecompile`](/docs/guides/evm/precompiles/voting-power) | `IVotingPower` | <EvmAddress address="0x000000000000000000000000000000000000080d" /><br />Deployed |
| [`BalancePrecompile`](/docs/guides/evm/precompiles/account-balance) | `IBalance` | <EvmAddress address="0x000000000000000000000000000000000000080e" /><br />Deployed |
| [`SchedulerPrecompile`](/docs/guides/evm/precompiles/scheduler) | `IScheduler` | <EvmAddress address="0x000000000000000000000000000000000000080f" /><br />Deployed |
| [`DrandPrecompile`](/docs/guides/evm/precompiles/drand) | `IDrand` | <EvmAddress address="0x0000000000000000000000000000000000000810" /><br />Deployed |
| [`TimestampPrecompile`](/docs/guides/evm/precompiles/timestamp) | `ITimestamp` | <EvmAddress address="0x0000000000000000000000000000000000000811" /><br />Deployed |
| [`RuntimeConfigurationPrecompile`](/docs/guides/evm/precompiles/runtime-configuration) | `IRuntimeConfiguration` | <EvmAddress address="0x0000000000000000000000000000000000000812" /><br />Deployed |
| [`PrecompileRegistry`](/docs/guides/evm/precompiles/registry) | `IPrecompileRegistry` | <EvmAddress address="0x0000000000000000000000000000000000000813" /><br />Deployed |

Projects that need proactive event delivery should use
[project-scoped event relays](/docs/guides/evm/precompile-design#project-scoped-event-relays)
instead of protocol-level event-reporting precompiles.

Released addresses and selectors remain reserved permanently. The compatibility
and lifecycle rules are documented in
[Precompile design and lifecycle](/docs/guides/evm/precompile-design).
Loading
Loading