Internals

WASM smart contracts

Deploy ink! smart contracts on subtensor via pallet-contracts and the custom chain extension.

View as Markdown

Subtensor supports WebAssembly (WASM) smart contract functionality through the integration of pallet-contracts, enabling developers to deploy and execute WASM smart contracts on the network. Contracts are written in ink!, a Rust-based embedded domain-specific language (eDSL) for writing smart contracts on Substrate-based chains. For compatibility, WASM contracts can also be compiled from Solidity using Solang.

Getting Started

For general smart contract development on Subtensor, please refer to the official ink! documentation:

Subtensor-Specific Features

Chain Extension

Subtensor provides a custom chain extension that allows smart contracts to interact with Subtensor-specific functionality:

Available Functions

Function IDNameDescriptionParametersReturns
0get_stake_info_for_hotkey_coldkey_netuidQuery stake information(AccountId, AccountId, NetUid)Option<StakeInfo>
1add_stakeDelegate stake from coldkey to hotkey(AccountId, NetUid, TaoBalance)Error code
2remove_stakeWithdraw stake from hotkey back to coldkey(AccountId, NetUid, AlphaBalance)Error code
3unstake_allUnstake all TAO from a hotkey(AccountId)Error code
4unstake_all_alphaUnstake all Alpha from a hotkey(AccountId)Error code
5move_stakeMove stake between hotkeys(AccountId, AccountId, NetUid, NetUid, AlphaBalance)Error code
6transfer_stakeTransfer stake between coldkeys(AccountId, AccountId, NetUid, NetUid, AlphaBalance)Error code
7swap_stakeSwap stake allocations between subnets(AccountId, NetUid, NetUid, AlphaBalance)Error code
8add_stake_limitDelegate stake with a price limit(AccountId, NetUid, TaoBalance, TaoBalance, bool)Error code
9remove_stake_limitWithdraw stake with a price limit(AccountId, NetUid, AlphaBalance, TaoBalance, bool)Error code
10swap_stake_limitSwap stake between subnets with price limit(AccountId, NetUid, NetUid, AlphaBalance, TaoBalance, bool)Error code
11remove_stake_full_limitFully withdraw stake with optional price limit(AccountId, NetUid, Option<TaoBalance>)Error code
12set_coldkey_auto_stake_hotkeyConfigure automatic stake destination(NetUid, AccountId)Error code
13add_proxyAdd a staking proxy for the caller(AccountId)Error code
14remove_proxyRemove a staking proxy for the caller(AccountId)Error code
15get_alpha_priceQuery the current alpha price for a subnet(NetUid)u64 (price × 10⁹)
16recycle_alphaRecycle alpha stake, reducing SubnetAlphaOut (supply reduction)(AccountId, NetUid, AlphaBalance)u64 (actual amount recycled)
17burn_alphaBurn alpha stake without reducing SubnetAlphaOut (supply neutral)(AccountId, NetUid, AlphaBalance)u64 (actual amount burned)
18add_stake_recycleAtomically add stake then recycle the resulting alpha(AccountId, NetUid, TaoBalance)u64 (alpha amount recycled)
19add_stake_burnAtomically add stake then burn the resulting alpha(AccountId, NetUid, TaoBalance)u64 (alpha amount burned)
20caller_add_stakeCaller-origin variant of add_stake (ID 1)(AccountId, NetUid, TaoBalance)Error code
21caller_remove_stakeCaller-origin variant of remove_stake (ID 2)(AccountId, NetUid, AlphaBalance)Error code
22caller_unstake_allCaller-origin variant of unstake_all (ID 3)(AccountId)Error code
23caller_unstake_all_alphaCaller-origin variant of unstake_all_alpha (ID 4)(AccountId)Error code
24caller_move_stakeCaller-origin variant of move_stake (ID 5)(AccountId, AccountId, NetUid, NetUid, AlphaBalance)Error code
25caller_transfer_stakeCaller-origin variant of transfer_stake (ID 6)(AccountId, AccountId, NetUid, NetUid, AlphaBalance)Error code
26caller_swap_stakeCaller-origin variant of swap_stake (ID 7)(AccountId, NetUid, NetUid, AlphaBalance)Error code
27caller_add_stake_limitCaller-origin variant of add_stake_limit (ID 8)(AccountId, NetUid, TaoBalance, TaoBalance, bool)Error code
28caller_remove_stake_limitCaller-origin variant of remove_stake_limit (ID 9)(AccountId, NetUid, AlphaBalance, TaoBalance, bool)Error code
29caller_swap_stake_limitCaller-origin variant of swap_stake_limit (ID 10)(AccountId, NetUid, NetUid, AlphaBalance, TaoBalance, bool)Error code
30caller_remove_stake_full_limitCaller-origin variant of remove_stake_full_limit (ID 11)(AccountId, NetUid, Option<TaoBalance>)Error code
31caller_set_coldkey_auto_stake_hotkeyCaller-origin variant of set_coldkey_auto_stake_hotkey (ID 12)(NetUid, AccountId)Error code
32caller_add_proxyCaller-origin variant of add_proxy (ID 13)(AccountId)Error code
33caller_remove_proxyCaller-origin variant of remove_proxy (ID 14)(AccountId)Error code
34get_subnet_registration_stateQuery whether a subnet exists and which registration generation currently owns the netuid(NetUid)SubnetRegistrationState { netuid, exists, registered_subnet_counter }
35get_coldkey_lockQuery the current rolled-forward lock state for a coldkey on a subnet(AccountId, NetUid)Option<ColdkeyLock { locked_mass: AlphaBalance, conviction_bits: u128, last_update: u64 }>
36get_stake_availabilityQuery total, locked, and currently available alpha for a coldkey on a subnet(AccountId, NetUid)StakeAvailability { netuid: NetUid, total: AlphaBalance, locked: AlphaBalance, available: AlphaBalance }

Example usage in your ink! contract:

#[ink::chain_extension(extension = 0)]
pub trait SubtensorExtension {
    type ErrorCode = SubtensorError;

    #[ink(function = 0)]
    fn get_stake_info(
        hotkey: AccountId,
        coldkey: AccountId,
        netuid: u16,
    ) -> Result<Option<StakeInfo>, SubtensorError>;
}

Error Codes

Chain extension functions that modify state return error codes as u32 values. The following codes are defined:

CodeNameDescription
0SuccessOperation completed successfully
1RuntimeErrorUnknown runtime error occurred
2NotEnoughBalanceToStakeInsufficient balance to complete stake operation
3NonAssociatedColdKeyColdkey is not associated with the hotkey
4BalanceWithdrawalErrorError occurred during balance withdrawal
5NotRegisteredHotkey is not registered in the subnet
6NotEnoughStakeToWithdrawInsufficient stake available for withdrawal
7TxRateLimitExceededTransaction rate limit has been exceeded
8SlippageTooHighPrice slippage exceeds acceptable threshold
9SubnetNotExistsSpecified subnet does not exist
10HotKeyNotRegisteredInSubNetHotkey is not registered in the specified subnet
11SameAutoStakeHotkeyAlreadySetAuto-stake hotkey is already configured
12InsufficientBalanceAccount has insufficient balance
13AmountTooLowTransaction amount is below minimum threshold
14InsufficientLiquidityInsufficient liquidity for swap operation
15SameNetuidSource and destination subnets are the same
16ProxyTooManyToo many proxies registered
17ProxyDuplicateProxy already exists
18ProxyNoSelfProxyCannot add self as proxy
19ProxyNotFoundProxy relationship not found
20CannotUseSystemAccountA system account cannot be used in this operation
21CannotBurnOrRecycleOnRootSubnetCannot burn or recycle on the root subnet
22SubtokenDisabledSubtoken is not enabled for the specified subnet

Call Filter

For security, contracts can only directly dispatch a limited set of runtime calls:

Whitelisted Calls:

  • Proxy::proxy - Execute proxy calls

All other runtime calls are restricted and cannot be dispatched from contracts.

Configuration Parameters

ParameterValueDescription
Maximum code size128 KBMaximum size of contract WASM code
Call stack depth5 framesMaximum nested contract call depth
Runtime memory1 GBMemory available during contract execution
Validator runtime memory2 GBMemory available for validators
Transient storage1 MBMaximum transient storage size

Additional Resources