diff --git a/pallets/admin-utils/src/lib.rs b/pallets/admin-utils/src/lib.rs index 8d1d735052..64dd918763 100644 --- a/pallets/admin-utils/src/lib.rs +++ b/pallets/admin-utils/src/lib.rs @@ -147,6 +147,8 @@ pub mod pallet { AddressMapping, /// Voting power precompile VotingPower, + /// Neuron registration cost precompile + NeuronRegistrationCost, } #[pallet::type_value] diff --git a/precompiles/src/lib.rs b/precompiles/src/lib.rs index ca86d3f9b3..dbe8539ac3 100644 --- a/precompiles/src/lib.rs +++ b/precompiles/src/lib.rs @@ -35,6 +35,7 @@ use crate::extensions::*; use crate::leasing::*; use crate::metagraph::*; use crate::neuron::*; +use crate::neuron_registration_cost::*; use crate::proxy::*; use crate::sr25519::*; use crate::staking::*; @@ -52,6 +53,7 @@ mod extensions; mod leasing; mod metagraph; mod neuron; +mod neuron_registration_cost; mod proxy; mod sr25519; mod staking; @@ -135,7 +137,7 @@ where Self(Default::default()) } - pub fn used_addresses() -> [H160; 27] { + pub fn used_addresses() -> [H160; 28] { [ hash(1), hash(2), @@ -164,6 +166,7 @@ where hash(VotingPowerPrecompile::::INDEX), hash(ProxyPrecompile::::INDEX), hash(AddressMappingPrecompile::::INDEX), + hash(NeuronRegistrationCostPrecompile::::INDEX), ] } } @@ -272,6 +275,12 @@ where PrecompileEnum::AddressMapping, ) } + a if a == hash(NeuronRegistrationCostPrecompile::::INDEX) => { + NeuronRegistrationCostPrecompile::::try_execute::( + handle, + PrecompileEnum::NeuronRegistrationCost, + ) + } _ => None, } } diff --git a/precompiles/src/neuron_registration_cost.rs b/precompiles/src/neuron_registration_cost.rs new file mode 100644 index 0000000000..01ea4311b3 --- /dev/null +++ b/precompiles/src/neuron_registration_cost.rs @@ -0,0 +1,88 @@ +use core::marker::PhantomData; + +use fp_evm::PrecompileHandle; +use precompile_utils::EvmResult; +use sp_core::U256; +use subtensor_runtime_common::{Currency, NetUid}; + +use crate::PrecompileExt; + +/// NeuronRegistrationCost precompile for smart contract access to neuron registration cost. +/// +/// This precompile allows smart contracts to query the current burn cost +/// required to register a neuron on a subnet. +pub struct NeuronRegistrationCostPrecompile(PhantomData); + +impl PrecompileExt for NeuronRegistrationCostPrecompile +where + R: frame_system::Config + pallet_subtensor::Config, + R::AccountId: From<[u8; 32]>, +{ + // Using 2062 as the next available index after VotingPower (2061) + const INDEX: u64 = 2062; +} + +#[precompile_utils::precompile] +impl NeuronRegistrationCostPrecompile +where + R: frame_system::Config + pallet_subtensor::Config, + R::AccountId: From<[u8; 32]>, +{ + /// Get the current burn cost to register a neuron on a subnet. + /// + /// This is the amount of TAO (in RAO) that will be burned when registering. + /// The cost can change dynamically based on network activity. + /// + /// # Arguments + /// * `netuid` - The subnet identifier (u16) + /// + /// # Returns + /// * `u256` - The burn cost in RAO (1 TAO = 10^9 RAO) + #[precompile::public("getBurn(uint16)")] + #[precompile::view] + fn get_burn(_: &mut impl PrecompileHandle, netuid: u16) -> EvmResult { + let burn = pallet_subtensor::Pallet::::get_burn(NetUid::from(netuid)); + Ok(U256::from(burn.to_u64())) + } + + /// Get the minimum burn cost for a subnet. + /// + /// # Arguments + /// * `netuid` - The subnet identifier (u16) + /// + /// # Returns + /// * `u256` - The minimum burn cost in RAO + #[precompile::public("getMinBurn(uint16)")] + #[precompile::view] + fn get_min_burn(_: &mut impl PrecompileHandle, netuid: u16) -> EvmResult { + let min_burn = pallet_subtensor::Pallet::::get_min_burn(NetUid::from(netuid)); + Ok(U256::from(min_burn.to_u64())) + } + + /// Get the maximum burn cost for a subnet. + /// + /// # Arguments + /// * `netuid` - The subnet identifier (u16) + /// + /// # Returns + /// * `u256` - The maximum burn cost in RAO + #[precompile::public("getMaxBurn(uint16)")] + #[precompile::view] + fn get_max_burn(_: &mut impl PrecompileHandle, netuid: u16) -> EvmResult { + let max_burn = pallet_subtensor::Pallet::::get_max_burn(NetUid::from(netuid)); + Ok(U256::from(max_burn.to_u64())) + } + + /// Check if registration is allowed on a subnet. + /// + /// # Arguments + /// * `netuid` - The subnet identifier (u16) + /// + /// # Returns + /// * `bool` - True if registration is allowed + #[precompile::public("isRegistrationAllowed(uint16)")] + #[precompile::view] + fn is_registration_allowed(_: &mut impl PrecompileHandle, netuid: u16) -> EvmResult { + Ok(pallet_subtensor::Pallet::::get_network_registration_allowed(NetUid::from(netuid))) + } +} diff --git a/precompiles/src/solidity/neuronRegistrationCost.sol b/precompiles/src/solidity/neuronRegistrationCost.sol new file mode 100644 index 0000000000..27e4c41f3e --- /dev/null +++ b/precompiles/src/solidity/neuronRegistrationCost.sol @@ -0,0 +1,28 @@ +// SPDX-License-Identifier: GPL-3.0-only +pragma solidity >=0.8.0; + +/// @title INeuronRegistrationCost +/// @notice Interface for querying neuron registration costs on Bittensor subnets +/// @dev Accessible at address 0x0000000000000000000000000000000000000806 +interface INeuronRegistrationCost { + /// @notice Get the current burn cost to register a neuron on a subnet + /// @dev The cost can change dynamically based on network activity + /// @param netuid The subnet identifier + /// @return The burn cost in RAO (1 TAO = 10^9 RAO) + function getBurn(uint16 netuid) external view returns (uint256); + + /// @notice Get the minimum burn cost for a subnet + /// @param netuid The subnet identifier + /// @return The minimum burn cost in RAO + function getMinBurn(uint16 netuid) external view returns (uint256); + + /// @notice Get the maximum burn cost for a subnet + /// @param netuid The subnet identifier + /// @return The maximum burn cost in RAO + function getMaxBurn(uint16 netuid) external view returns (uint256); + + /// @notice Check if registration is allowed on a subnet + /// @param netuid The subnet identifier + /// @return True if registration is allowed + function isRegistrationAllowed(uint16 netuid) external view returns (bool); +}