diff --git a/Cargo.lock b/Cargo.lock index ed3b5ae451..bf63b9aea5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1068,6 +1068,12 @@ dependencies = [ "thiserror 1.0.69", ] +[[package]] +name = "case" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd6c0e7b807d60291f42f33f58480c0bfafe28ed08286446f45e463728cf9c1c" + [[package]] name = "cc" version = "1.2.10" @@ -5854,6 +5860,7 @@ dependencies = [ "pallet-transaction-payment-rpc-runtime-api", "pallet-utility", "parity-scale-codec", + "precompile-utils", "rand_chacha", "scale-info", "serde_json", @@ -7226,6 +7233,44 @@ dependencies = [ "zerocopy", ] +[[package]] +name = "precompile-utils" +version = "0.1.0" +source = "git+https://github.com/opentensor/frontier?rev=635bdac882#635bdac882333afed827053f31ef56ab739f7a2e" +dependencies = [ + "environmental", + "evm", + "fp-evm", + "frame-support", + "frame-system", + "hex", + "impl-trait-for-tuples", + "log", + "num_enum", + "pallet-evm", + "parity-scale-codec", + "precompile-utils-macro", + "sp-core", + "sp-io", + "sp-runtime", + "sp-weights", + "staging-xcm", +] + +[[package]] +name = "precompile-utils-macro" +version = "0.1.0" +source = "git+https://github.com/opentensor/frontier?rev=635bdac882#635bdac882333afed827053f31ef56ab739f7a2e" +dependencies = [ + "case", + "num_enum", + "prettyplease 0.2.29", + "proc-macro2", + "quote", + "sp-crypto-hashing 0.1.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-stable2409)", + "syn 1.0.109", +] + [[package]] name = "predicates" version = "2.1.5" diff --git a/runtime/Cargo.toml b/runtime/Cargo.toml index 2e6eda522c..831debfa6b 100644 --- a/runtime/Cargo.toml +++ b/runtime/Cargo.toml @@ -100,6 +100,7 @@ pallet-commitments = { default-features = false, path = "../pallets/commitments" fp-evm = { workspace = true } fp-rpc = { workspace = true } fp-self-contained = { workspace = true } +precompile-utils = { workspace = true } # Frontier FRAME pallet-base-fee = { workspace = true } @@ -163,6 +164,7 @@ std = [ "pallet-scheduler/std", "pallet-preimage/std", "pallet-commitments/std", + "precompile-utils/std", "sp-api/std", "sp-block-builder/std", "sp-consensus-aura/std", diff --git a/runtime/src/lib.rs b/runtime/src/lib.rs index 8dcce09b1e..0320e89983 100644 --- a/runtime/src/lib.rs +++ b/runtime/src/lib.rs @@ -229,7 +229,7 @@ pub const VERSION: RuntimeVersion = RuntimeVersion { // `spec_version`, and `authoring_version` are the same between Wasm and native. // This value is set to 100 to notify Polkadot-JS App (https://polkadot.js.org/apps) to use // the compatible custom types. - spec_version: 239, + spec_version: 240, impl_version: 1, apis: RUNTIME_API_VERSIONS, transaction_version: 1, diff --git a/runtime/src/precompiles/balance_transfer.rs b/runtime/src/precompiles/balance_transfer.rs index 6154cf8a52..3b326bca28 100644 --- a/runtime/src/precompiles/balance_transfer.rs +++ b/runtime/src/precompiles/balance_transfer.rs @@ -1,60 +1,40 @@ -use pallet_evm::{ - BalanceConverter, ExitError, ExitSucceed, PrecompileHandle, PrecompileOutput, PrecompileResult, -}; +use pallet_evm::PrecompileHandle; +use precompile_utils::EvmResult; +use sp_core::H256; use sp_runtime::traits::UniqueSaturatedInto; -use sp_std::vec; -use crate::precompiles::{ - contract_to_origin, get_method_id, get_pubkey, get_slice, try_dispatch_runtime_call, -}; +use crate::precompiles::{contract_to_origin, parse_pubkey, PrecompileExt, PrecompileHandleExt}; use crate::Runtime; -pub const BALANCE_TRANSFER_INDEX: u64 = 2048; -// ss58 public key i.e., the contract sends funds it received to the destination address from the -// method parameter. -const CONTRACT_ADDRESS_SS58: [u8; 32] = [ - 0x07, 0xec, 0x71, 0x2a, 0x5d, 0x38, 0x43, 0x4d, 0xdd, 0x03, 0x3f, 0x8f, 0x02, 0x4e, 0xcd, 0xfc, - 0x4b, 0xb5, 0x95, 0x1c, 0x13, 0xc3, 0x08, 0x5c, 0x39, 0x9c, 0x8a, 0x5f, 0x62, 0x93, 0x70, 0x5d, -]; - pub struct BalanceTransferPrecompile; -impl BalanceTransferPrecompile { - pub fn execute(handle: &mut impl PrecompileHandle) -> PrecompileResult { - let txdata = handle.input(); - - // Match method ID: keccak256("transfer(bytes32)") - let method = get_slice(txdata, 0, 4)?; - if get_method_id("transfer(bytes32)") != method { - return Ok(PrecompileOutput { - exit_status: ExitSucceed::Returned, - output: vec![], - }); - } - - // Forward all received value to the destination address - let amount = handle.context().apparent_value; +impl PrecompileExt for BalanceTransferPrecompile { + const INDEX: u64 = 2048; + const ADDRESS_SS58: [u8; 32] = [ + 0x07, 0xec, 0x71, 0x2a, 0x5d, 0x38, 0x43, 0x4d, 0xdd, 0x03, 0x3f, 0x8f, 0x02, 0x4e, 0xcd, + 0xfc, 0x4b, 0xb5, 0x95, 0x1c, 0x13, 0xc3, 0x08, 0x5c, 0x39, 0x9c, 0x8a, 0x5f, 0x62, 0x93, + 0x70, 0x5d, + ]; +} - // Use BalanceConverter to convert EVM amount to Substrate balance - let amount_sub = - ::BalanceConverter::into_substrate_balance(amount) - .ok_or(ExitError::OutOfFund)?; +#[precompile_utils::precompile] +impl BalanceTransferPrecompile { + #[precompile::public("transfer(bytes32)")] + #[precompile::payable] + fn transfer(handle: &mut impl PrecompileHandle, address: H256) -> EvmResult<()> { + let amount_sub = handle.try_convert_apparent_value()?; if amount_sub.is_zero() { - return Ok(PrecompileOutput { - exit_status: ExitSucceed::Returned, - output: vec![], - }); + return Ok(()); } - let address_bytes_dst = get_slice(txdata, 4, 36)?; - let (account_id_dst, _) = get_pubkey(address_bytes_dst)?; + let dest = parse_pubkey(address.as_bytes())?.0.into(); let call = pallet_balances::Call::::transfer_allow_death { - dest: account_id_dst.into(), + dest, value: amount_sub.unique_saturated_into(), }; - try_dispatch_runtime_call(handle, call, contract_to_origin(&CONTRACT_ADDRESS_SS58)?) + handle.try_dispatch_runtime_call(call, contract_to_origin(&Self::ADDRESS_SS58)?) } } diff --git a/runtime/src/precompiles/ed25519.rs b/runtime/src/precompiles/ed25519.rs index 83be4ca774..1a629df523 100644 --- a/runtime/src/precompiles/ed25519.rs +++ b/runtime/src/precompiles/ed25519.rs @@ -2,14 +2,18 @@ extern crate alloc; use alloc::vec::Vec; -use crate::precompiles::get_slice; use ed25519_dalek::{Signature, Verifier, VerifyingKey}; use fp_evm::{ExitError, ExitSucceed, LinearCostPrecompile, PrecompileFailure}; -pub const EDVERIFY_PRECOMPILE_INDEX: u64 = 1026; +use crate::precompiles::{parse_slice, PrecompileExt}; pub struct Ed25519Verify; +impl PrecompileExt for Ed25519Verify { + const INDEX: u64 = 1026; + const ADDRESS_SS58: [u8; 32] = [0; 32]; +} + impl LinearCostPrecompile for Ed25519Verify { const BASE: u64 = 15; const WORD: u64 = 3; @@ -23,13 +27,13 @@ impl LinearCostPrecompile for Ed25519Verify { let mut buf = [0u8; 32]; - let msg = get_slice(input, 4, 36)?; - let pk = VerifyingKey::try_from(get_slice(input, 36, 68)?).map_err(|_| { + let msg = parse_slice(input, 4, 36)?; + let pk = VerifyingKey::try_from(parse_slice(input, 36, 68)?).map_err(|_| { PrecompileFailure::Error { exit_status: ExitError::Other("Public key recover failed".into()), } })?; - let sig = Signature::try_from(get_slice(input, 68, 132)?).map_err(|_| { + let sig = Signature::try_from(parse_slice(input, 68, 132)?).map_err(|_| { PrecompileFailure::Error { exit_status: ExitError::Other("Signature recover failed".into()), } diff --git a/runtime/src/precompiles/metagraph.rs b/runtime/src/precompiles/metagraph.rs index ffc4cbed79..f74812cc09 100644 --- a/runtime/src/precompiles/metagraph.rs +++ b/runtime/src/precompiles/metagraph.rs @@ -1,360 +1,171 @@ extern crate alloc; -use crate::precompiles::{get_method_id, get_slice}; -use crate::Runtime; -use fp_evm::{ - ExitError, ExitSucceed, PrecompileFailure, PrecompileHandle, PrecompileOutput, PrecompileResult, -}; -use sp_core::{ByteArray, U256}; -use sp_std::vec; -pub const METAGRAPH_PRECOMPILE_INDEX: u64 = 2050; -pub struct MetagraphPrecompile; - -const NO_HOTKEY: &str = "no hotkey"; - -impl MetagraphPrecompile { - pub fn execute(handle: &mut impl PrecompileHandle) -> PrecompileResult { - let txdata = handle.input(); - let method_id = get_slice(txdata, 0, 4)?; - let method_input = txdata - .get(4..) - .map_or_else(vec::Vec::new, |slice| slice.to_vec()); // Avoiding borrowing conflicts +use alloc::string::String; - match method_id { - id if id == get_method_id("getUidCount(uint16)") => Self::get_uid_count(&method_input), - id if id == get_method_id("getStake(uint16,uint16)") => Self::get_stake(&method_input), - id if id == get_method_id("getRank(uint16,uint16)") => Self::get_rank(&method_input), - id if id == get_method_id("getTrust(uint16,uint16)") => Self::get_trust(&method_input), - id if id == get_method_id("getConsensus(uint16,uint16)") => { - Self::get_consensus(&method_input) - } - id if id == get_method_id("getIncentive(uint16,uint16)") => { - Self::get_incentive(&method_input) - } - id if id == get_method_id("getDividends(uint16,uint16)") => { - Self::get_dividends(&method_input) - } - id if id == get_method_id("getEmission(uint16,uint16)") => { - Self::get_emission(&method_input) - } - id if id == get_method_id("getVtrust(uint16,uint16)") => { - Self::get_vtrust(&method_input) - } - id if id == get_method_id("getValidatorStatus(uint16,uint16)") => { - Self::get_validator_status(&method_input) - } - id if id == get_method_id("getLastUpdate(uint16,uint16)") => { - Self::get_last_update(&method_input) - } - id if id == get_method_id("getIsActive(uint16,uint16)") => { - Self::get_is_active(&method_input) - } - id if id == get_method_id("getAxon(uint16,uint16)") => Self::get_axon(&method_input), - id if id == get_method_id("getHotkey(uint16,uint16)") => { - Self::get_hotkey(&method_input) - } - id if id == get_method_id("getColdkey(uint16,uint16)") => { - Self::get_coldkey(&method_input) - } +use fp_evm::{ExitError, PrecompileFailure, PrecompileHandle}; +use pallet_subtensor::AxonInfo as SubtensorModuleAxonInfo; +use precompile_utils::{solidity::Codec, EvmResult}; +use sp_core::{ByteArray, H256}; - _ => Err(PrecompileFailure::Error { - exit_status: ExitError::InvalidRange, - }), - } - } +use crate::precompiles::PrecompileExt; +use crate::Runtime; - fn get_uid_count(data: &[u8]) -> PrecompileResult { - let netuid = Self::parse_netuid(data)?; - let uid_count = pallet_subtensor::SubnetworkN::::get(netuid); +pub struct MetagraphPrecompile; - let uid_count_u256 = U256::from(uid_count); - let mut result = [0_u8; 32]; - U256::to_big_endian(&uid_count_u256, &mut result); +impl PrecompileExt for MetagraphPrecompile { + const INDEX: u64 = 2050; + const ADDRESS_SS58: [u8; 32] = [0; 32]; +} - Ok(PrecompileOutput { - exit_status: ExitSucceed::Returned, - output: result.into(), - }) +#[precompile_utils::precompile] +impl MetagraphPrecompile { + #[precompile::public("getUidCount(uint16)")] + #[precompile::view] + fn get_uid_count(_: &mut impl PrecompileHandle, netuid: u16) -> EvmResult { + Ok(pallet_subtensor::SubnetworkN::::get(netuid)) } - fn get_stake(data: &[u8]) -> PrecompileResult { - let netuid = Self::parse_netuid(data)?; - let uid = Self::parse_uid(get_slice(data, 32, 64)?)?; + #[precompile::public("getStake(uint16,uint16)")] + #[precompile::view] + fn get_stake(_: &mut impl PrecompileHandle, netuid: u16, uid: u16) -> EvmResult { let hotkey = pallet_subtensor::Pallet::::get_hotkey_for_net_and_uid(netuid, uid) .map_err(|_| PrecompileFailure::Error { exit_status: ExitError::InvalidRange, })?; - let stake = pallet_subtensor::Pallet::::get_total_stake_for_hotkey(&hotkey); - let result_u256 = U256::from(stake); - let mut result = [0_u8; 32]; - U256::to_big_endian(&result_u256, &mut result); - - Ok(PrecompileOutput { - exit_status: ExitSucceed::Returned, - output: result.into(), - }) + Ok(pallet_subtensor::Pallet::::get_total_stake_for_hotkey(&hotkey)) } - fn get_rank(data: &[u8]) -> PrecompileResult { - let netuid = Self::parse_netuid(data)?; - let uid = Self::parse_uid(get_slice(data, 32, 64)?)?; - let rank = pallet_subtensor::Pallet::::get_rank_for_uid(netuid, uid); - - let result_u256 = U256::from(rank); - let mut result = [0_u8; 32]; - U256::to_big_endian(&result_u256, &mut result); - - Ok(PrecompileOutput { - exit_status: ExitSucceed::Returned, - output: result.into(), - }) + #[precompile::public("getRank(uint16,uint16)")] + #[precompile::view] + fn get_rank(_: &mut impl PrecompileHandle, netuid: u16, uid: u16) -> EvmResult { + Ok(pallet_subtensor::Pallet::::get_rank_for_uid( + netuid, uid, + )) } - fn get_trust(data: &[u8]) -> PrecompileResult { - let netuid = Self::parse_netuid(data)?; - let uid = Self::parse_uid(get_slice(data, 32, 64)?)?; - - let trust = pallet_subtensor::Pallet::::get_trust_for_uid(netuid, uid); - - let result_u256 = U256::from(trust); - let mut result = [0_u8; 32]; - U256::to_big_endian(&result_u256, &mut result); - - Ok(PrecompileOutput { - exit_status: ExitSucceed::Returned, - output: result.into(), - }) + #[precompile::public("getTrust(uint16,uint16)")] + #[precompile::view] + fn get_trust(_: &mut impl PrecompileHandle, netuid: u16, uid: u16) -> EvmResult { + Ok(pallet_subtensor::Pallet::::get_trust_for_uid( + netuid, uid, + )) } - fn get_consensus(data: &[u8]) -> PrecompileResult { - let netuid = Self::parse_netuid(data)?; - let uid = Self::parse_uid(get_slice(data, 32, 64)?)?; - - let consensus = pallet_subtensor::Pallet::::get_consensus_for_uid(netuid, uid); - - let result_u256 = U256::from(consensus); - let mut result = [0_u8; 32]; - U256::to_big_endian(&result_u256, &mut result); - - Ok(PrecompileOutput { - exit_status: ExitSucceed::Returned, - output: result.into(), - }) + #[precompile::public("getConsensus(uint16,uint16)")] + #[precompile::view] + fn get_consensus(_: &mut impl PrecompileHandle, netuid: u16, uid: u16) -> EvmResult { + Ok(pallet_subtensor::Pallet::::get_consensus_for_uid( + netuid, uid, + )) } - fn get_incentive(data: &[u8]) -> PrecompileResult { - let netuid = Self::parse_netuid(data)?; - let uid = Self::parse_uid(get_slice(data, 32, 64)?)?; - - let incentive = pallet_subtensor::Pallet::::get_incentive_for_uid(netuid, uid); - - let result_u256 = U256::from(incentive); - let mut result = [0_u8; 32]; - U256::to_big_endian(&result_u256, &mut result); - - Ok(PrecompileOutput { - exit_status: ExitSucceed::Returned, - output: result.into(), - }) + #[precompile::public("getIncentive(uint16,uint16)")] + #[precompile::view] + fn get_incentive(_: &mut impl PrecompileHandle, netuid: u16, uid: u16) -> EvmResult { + Ok(pallet_subtensor::Pallet::::get_incentive_for_uid( + netuid, uid, + )) } - fn get_dividends(data: &[u8]) -> PrecompileResult { - let netuid = Self::parse_netuid(data)?; - let uid = Self::parse_uid(get_slice(data, 32, 64)?)?; - - let dividends = pallet_subtensor::Pallet::::get_dividends_for_uid(netuid, uid); - - let result_u256 = U256::from(dividends); - let mut result = [0_u8; 32]; - U256::to_big_endian(&result_u256, &mut result); - - Ok(PrecompileOutput { - exit_status: ExitSucceed::Returned, - output: result.into(), - }) + #[precompile::public("getDividends(uint16,uint16)")] + #[precompile::view] + fn get_dividends(_: &mut impl PrecompileHandle, netuid: u16, uid: u16) -> EvmResult { + Ok(pallet_subtensor::Pallet::::get_dividends_for_uid( + netuid, uid, + )) } - fn get_emission(data: &[u8]) -> PrecompileResult { - let netuid = Self::parse_netuid(data)?; - let uid = Self::parse_uid(get_slice(data, 32, 64)?)?; - - let emission = pallet_subtensor::Pallet::::get_emission_for_uid(netuid, uid); - - let result_u256 = U256::from(emission); - let mut result = [0_u8; 32]; - U256::to_big_endian(&result_u256, &mut result); - - Ok(PrecompileOutput { - exit_status: ExitSucceed::Returned, - output: result.into(), - }) + #[precompile::public("getEmission(uint16,uint16)")] + #[precompile::view] + fn get_emission(_: &mut impl PrecompileHandle, netuid: u16, uid: u16) -> EvmResult { + Ok(pallet_subtensor::Pallet::::get_emission_for_uid( + netuid, uid, + )) } - fn get_vtrust(data: &[u8]) -> PrecompileResult { - let netuid = Self::parse_netuid(data)?; - let uid = Self::parse_uid(get_slice(data, 32, 64)?)?; - - let vtrust = pallet_subtensor::Pallet::::get_validator_trust_for_uid(netuid, uid); - - let result_u256 = U256::from(vtrust); - let mut result = [0_u8; 32]; - U256::to_big_endian(&result_u256, &mut result); - - Ok(PrecompileOutput { - exit_status: ExitSucceed::Returned, - output: result.into(), - }) + #[precompile::public("getVtrust(uint16,uint16)")] + #[precompile::view] + fn get_vtrust(_: &mut impl PrecompileHandle, netuid: u16, uid: u16) -> EvmResult { + Ok(pallet_subtensor::Pallet::::get_validator_trust_for_uid(netuid, uid)) } - fn get_validator_status(data: &[u8]) -> PrecompileResult { - let netuid = Self::parse_netuid(data)?; - let uid = Self::parse_uid(get_slice(data, 32, 64)?)?; - - let validator_permit = - pallet_subtensor::Pallet::::get_validator_permit_for_uid(netuid, uid); - - let result_u256 = if validator_permit { - U256::from(1) - } else { - U256::from(0) - }; - let mut result = [0_u8; 32]; - U256::to_big_endian(&result_u256, &mut result); - - Ok(PrecompileOutput { - exit_status: ExitSucceed::Returned, - output: result.into(), - }) + #[precompile::public("getValidatorStatus(uint16,uint16)")] + #[precompile::view] + fn get_validator_status( + _: &mut impl PrecompileHandle, + netuid: u16, + uid: u16, + ) -> EvmResult { + Ok(pallet_subtensor::Pallet::::get_validator_permit_for_uid(netuid, uid)) } - fn get_last_update(data: &[u8]) -> PrecompileResult { - let netuid = Self::parse_netuid(data)?; - let uid = Self::parse_uid(get_slice(data, 32, 64)?)?; - - let last_update = pallet_subtensor::Pallet::::get_last_update_for_uid(netuid, uid); - - let result_u256 = U256::from(last_update); - let mut result = [0_u8; 32]; - U256::to_big_endian(&result_u256, &mut result); - - Ok(PrecompileOutput { - exit_status: ExitSucceed::Returned, - output: result.into(), - }) + #[precompile::public("getLastUpdate(uint16,uint16)")] + #[precompile::view] + fn get_last_update(_: &mut impl PrecompileHandle, netuid: u16, uid: u16) -> EvmResult { + Ok(pallet_subtensor::Pallet::::get_last_update_for_uid(netuid, uid)) } - fn get_is_active(data: &[u8]) -> PrecompileResult { - let netuid = Self::parse_netuid(data)?; - let uid = Self::parse_uid(get_slice(data, 32, 64)?)?; - - let active = pallet_subtensor::Pallet::::get_active_for_uid(netuid, uid); - - let result_u256 = if active { U256::from(1) } else { U256::from(0) }; - let mut result = [0_u8; 32]; - U256::to_big_endian(&result_u256, &mut result); - - Ok(PrecompileOutput { - exit_status: ExitSucceed::Returned, - output: result.into(), - }) + #[precompile::public("getIsActive(uint16,uint16)")] + #[precompile::view] + fn get_is_active(_: &mut impl PrecompileHandle, netuid: u16, uid: u16) -> EvmResult { + Ok(pallet_subtensor::Pallet::::get_active_for_uid( + netuid, uid, + )) } - fn get_axon(data: &[u8]) -> PrecompileResult { - let netuid = Self::parse_netuid(data)?; - let uid = Self::parse_uid(get_slice(data, 32, 64)?)?; - + #[precompile::public("getAxon(uint16,uint16)")] + #[precompile::view] + fn get_axon(_: &mut impl PrecompileHandle, netuid: u16, uid: u16) -> EvmResult { let hotkey = pallet_subtensor::Pallet::::get_hotkey_for_net_and_uid(netuid, uid) .map_err(|_| PrecompileFailure::Error { - exit_status: ExitError::Other(sp_version::Cow::Borrowed(NO_HOTKEY)), + exit_status: ExitError::Other("hotkey not found".into()), })?; - let axon = pallet_subtensor::Pallet::::get_axon_info(netuid, &hotkey); - - let mut block_result = [0_u8; 32]; - U256::to_big_endian(&U256::from(axon.block), &mut block_result); - - let mut version_result = [0_u8; 32]; - U256::to_big_endian(&U256::from(axon.version), &mut version_result); - - let mut ip_result = [0_u8; 32]; - U256::to_big_endian(&U256::from(axon.ip), &mut ip_result); - - let mut port_result = [0_u8; 32]; - U256::to_big_endian(&U256::from(axon.port), &mut port_result); - - let mut ip_type_result = [0_u8; 32]; - U256::to_big_endian(&U256::from(axon.ip_type), &mut ip_type_result); - - let mut protocol_result = [0_u8; 32]; - U256::to_big_endian(&U256::from(axon.protocol), &mut protocol_result); - - let mut result = [0_u8; 192]; - result[..32].copy_from_slice(&block_result); - result[32..64].copy_from_slice(&version_result); - result[64..96].copy_from_slice(&ip_result); - result[96..128].copy_from_slice(&port_result); - result[128..160].copy_from_slice(&ip_type_result); - result[160..].copy_from_slice(&protocol_result); - - Ok(PrecompileOutput { - exit_status: ExitSucceed::Returned, - output: result.into(), - }) + Ok(pallet_subtensor::Pallet::::get_axon_info(netuid, &hotkey).into()) } - fn get_hotkey(data: &[u8]) -> PrecompileResult { - let netuid = Self::parse_netuid(data)?; - let uid = Self::parse_uid(get_slice(data, 32, 64)?)?; - - let hotkey = pallet_subtensor::Pallet::::get_hotkey_for_net_and_uid(netuid, uid) + #[precompile::public("getHotkey(uint16,uint16)")] + #[precompile::view] + fn get_hotkey(_: &mut impl PrecompileHandle, netuid: u16, uid: u16) -> EvmResult { + pallet_subtensor::Pallet::::get_hotkey_for_net_and_uid(netuid, uid) + .map(|acc| H256::from_slice(acc.as_slice())) .map_err(|_| PrecompileFailure::Error { - exit_status: ExitError::InvalidRange, - })?; - - Ok(PrecompileOutput { - exit_status: ExitSucceed::Returned, - output: hotkey.as_slice().into(), - }) + exit_status: ExitError::InvalidRange, + }) } - fn get_coldkey(data: &[u8]) -> PrecompileResult { - let netuid = Self::parse_netuid(data)?; - let uid = Self::parse_uid(get_slice(data, 32, 64)?)?; - + #[precompile::public("getColdkey(uint16,uint16)")] + #[precompile::view] + fn get_coldkey(_: &mut impl PrecompileHandle, netuid: u16, uid: u16) -> EvmResult { let hotkey = pallet_subtensor::Pallet::::get_hotkey_for_net_and_uid(netuid, uid) .map_err(|_| PrecompileFailure::Error { exit_status: ExitError::InvalidRange, })?; - let coldkey = pallet_subtensor::Owner::::get(&hotkey); - Ok(PrecompileOutput { - exit_status: ExitSucceed::Returned, - output: coldkey.as_slice().into(), - }) + Ok(H256::from_slice(coldkey.as_slice())) } +} - fn parse_netuid(data: &[u8]) -> Result { - if data.len() < 32 { - return Err(PrecompileFailure::Error { - exit_status: ExitError::InvalidRange, - }); - } - let mut netuid = [0u8; 2]; - netuid.copy_from_slice(get_slice(data, 30, 32)?); - let result = u16::from_be_bytes(netuid); - Ok(result) - } +#[derive(Codec)] +struct AxonInfo { + block: u64, + version: u32, + ip: u128, + port: u16, + ip_type: u8, + protocol: u8, +} - fn parse_uid(data: &[u8]) -> Result { - if data.len() < 32 { - return Err(PrecompileFailure::Error { - exit_status: ExitError::InvalidRange, - }); +impl From for AxonInfo { + fn from(value: SubtensorModuleAxonInfo) -> Self { + Self { + block: value.block, + version: value.version, + ip: value.ip, + port: value.port, + ip_type: value.ip_type, + protocol: value.protocol, } - let mut uid = [0u8; 2]; - uid.copy_from_slice(get_slice(data, 30, 32)?); - let result = u16::from_be_bytes(uid); - Ok(result) } } diff --git a/runtime/src/precompiles/mod.rs b/runtime/src/precompiles/mod.rs index 6bed2913cd..349d1ce455 100644 --- a/runtime/src/precompiles/mod.rs +++ b/runtime/src/precompiles/mod.rs @@ -3,24 +3,26 @@ extern crate alloc; use alloc::format; use core::marker::PhantomData; -use crate::{Runtime, RuntimeCall}; - +use frame_support::dispatch::{GetDispatchInfo, Pays}; +use frame_system::RawOrigin; use pallet_evm::{ - ExitError, ExitSucceed, GasWeightMapping, IsPrecompileResult, Precompile, PrecompileFailure, - PrecompileHandle, PrecompileOutput, PrecompileResult, PrecompileSet, + AddressMapping, BalanceConverter, ExitError, GasWeightMapping, HashedAddressMapping, + IsPrecompileResult, Precompile, PrecompileFailure, PrecompileHandle, PrecompileResult, + PrecompileSet, }; use pallet_evm_precompile_modexp::Modexp; use pallet_evm_precompile_sha3fips::Sha3FIPS256; use pallet_evm_precompile_simple::{ECRecover, ECRecoverPublicKey, Identity, Ripemd160, Sha256}; - -use frame_support::dispatch::{GetDispatchInfo, Pays}; -use frame_system::RawOrigin; -use sp_core::{hashing::keccak_256, H160}; +use precompile_utils::EvmResult; +use sp_core::{H160, U256}; +use sp_runtime::traits::BlakeTwo256; use sp_runtime::{traits::Dispatchable, AccountId32}; use pallet_admin_utils::{PrecompileEnable, PrecompileEnum}; use sp_std::vec; +use crate::{Runtime, RuntimeCall}; + // Include custom precompiles mod balance_transfer; mod ed25519; @@ -35,6 +37,7 @@ use metagraph::*; use neuron::*; use staking::*; use subnet::*; + pub struct FrontierPrecompiles(PhantomData); impl Default for FrontierPrecompiles where @@ -61,12 +64,12 @@ where hash(5), hash(1024), hash(1025), - hash(EDVERIFY_PRECOMPILE_INDEX), - hash(BALANCE_TRANSFER_INDEX), - hash(STAKING_PRECOMPILE_INDEX), - hash(SUBNET_PRECOMPILE_INDEX), - hash(METAGRAPH_PRECOMPILE_INDEX), - hash(NEURON_PRECOMPILE_INDEX), + hash(Ed25519Verify::INDEX), + hash(BalanceTransferPrecompile::INDEX), + hash(StakingPrecompile::INDEX), + hash(SubnetPrecompile::INDEX), + hash(MetagraphPrecompile::INDEX), + hash(NeuronPrecompile::INDEX), ] } } @@ -85,10 +88,9 @@ where // Non-Frontier specific nor Ethereum precompiles : a if a == hash(1024) => Some(Sha3FIPS256::execute(handle)), a if a == hash(1025) => Some(ECRecoverPublicKey::execute(handle)), - - a if a == hash(EDVERIFY_PRECOMPILE_INDEX) => Some(Ed25519Verify::execute(handle)), + a if a == hash(Ed25519Verify::INDEX) => Some(Ed25519Verify::execute(handle)), // Subtensor specific precompiles : - a if a == hash(BALANCE_TRANSFER_INDEX) => { + a if a == hash(BalanceTransferPrecompile::INDEX) => { if PrecompileEnable::::get(PrecompileEnum::BalanceTransfer) { Some(BalanceTransferPrecompile::execute(handle)) } else { @@ -99,7 +101,7 @@ where })) } } - a if a == hash(STAKING_PRECOMPILE_INDEX) => { + a if a == hash(StakingPrecompile::INDEX) => { if PrecompileEnable::::get(PrecompileEnum::Staking) { Some(StakingPrecompile::execute(handle)) } else { @@ -111,7 +113,7 @@ where } } - a if a == hash(SUBNET_PRECOMPILE_INDEX) => { + a if a == hash(SubnetPrecompile::INDEX) => { if PrecompileEnable::::get(PrecompileEnum::Subnet) { Some(SubnetPrecompile::execute(handle)) } else { @@ -120,7 +122,7 @@ where })) } } - a if a == hash(METAGRAPH_PRECOMPILE_INDEX) => { + a if a == hash(MetagraphPrecompile::INDEX) => { if PrecompileEnable::::get(PrecompileEnum::Metagraph) { Some(MetagraphPrecompile::execute(handle)) } else { @@ -129,7 +131,7 @@ where })) } } - a if a == hash(NEURON_PRECOMPILE_INDEX) => { + a if a == hash(NeuronPrecompile::INDEX) => { if PrecompileEnable::::get(PrecompileEnum::Neuron) { Some(NeuronPrecompile::execute(handle)) } else { @@ -155,19 +157,8 @@ fn hash(a: u64) -> H160 { H160::from_low_u64_be(a) } -/// Returns Ethereum method ID from an str method signature -/// -pub fn get_method_id(method_signature: &str) -> [u8; 4] { - // Calculate the full Keccak-256 hash of the method signature - let hash = keccak_256(method_signature.as_bytes()); - - // Extract the first 4 bytes to get the method ID - [hash[0], hash[1], hash[2], hash[3]] -} - /// Takes a slice from bytes with PrecompileFailure as Error -/// -pub fn get_slice(data: &[u8], from: usize, to: usize) -> Result<&[u8], PrecompileFailure> { +fn parse_slice(data: &[u8], from: usize, to: usize) -> Result<&[u8], PrecompileFailure> { let maybe_slice = data.get(from..to); if let Some(slice) = maybe_slice { Ok(slice) @@ -184,9 +175,9 @@ pub fn get_slice(data: &[u8], from: usize, to: usize) -> Result<&[u8], Precompil } } -pub fn get_pubkey(data: &[u8]) -> Result<(AccountId32, vec::Vec), PrecompileFailure> { +fn parse_pubkey(data: &[u8]) -> Result<(AccountId32, vec::Vec), PrecompileFailure> { let mut pubkey = [0u8; 32]; - pubkey.copy_from_slice(get_slice(data, 0, 32)?); + pubkey.copy_from_slice(parse_slice(data, 0, 32)?); Ok(( pubkey.into(), @@ -195,107 +186,107 @@ pub fn get_pubkey(data: &[u8]) -> Result<(AccountId32, vec::Vec), Precompile )) } -fn parse_netuid(data: &[u8], offset: usize) -> Result { - if data.len() < offset + 2 { - return Err(PrecompileFailure::Error { - exit_status: ExitError::InvalidRange, - }); - } - - let mut netuid_bytes = [0u8; 2]; - netuid_bytes.copy_from_slice(get_slice(data, offset, offset + 2)?); - let netuid: u16 = netuid_bytes[1] as u16 | ((netuid_bytes[0] as u16) << 8u16); - - Ok(netuid) +fn try_u16_from_u256(value: U256) -> Result { + value.try_into().map_err(|_| PrecompileFailure::Error { + exit_status: ExitError::Other("the value is outside of u16 bounds".into()), + }) } fn contract_to_origin(contract: &[u8; 32]) -> Result, PrecompileFailure> { - let (account_id, _) = get_pubkey(contract)?; + let (account_id, _) = parse_pubkey(contract)?; Ok(RawOrigin::Signed(account_id)) } -/// Dispatches a runtime call, but also checks and records the gas costs. -fn try_dispatch_runtime_call( - handle: &mut impl PrecompileHandle, - call: impl Into, - origin: RawOrigin, -) -> PrecompileResult { - let call = Into::::into(call); - let info = call.get_dispatch_info(); - - let target_gas = handle.gas_limit(); - if let Some(gas) = target_gas { - let valid_weight = - ::GasWeightMapping::gas_to_weight(gas, false).ref_time(); - if info.weight.ref_time() > valid_weight { - return Err(PrecompileFailure::Error { - exit_status: ExitError::OutOfGas, - }); - } +trait PrecompileHandleExt: PrecompileHandle { + fn caller_account_id(&self) -> AccountId32 { + as AddressMapping>::into_account_id( + self.context().caller, + ) } - handle.record_external_cost( - Some(info.weight.ref_time()), - Some(info.weight.proof_size()), - None, - )?; + fn try_convert_apparent_value(&self) -> EvmResult { + let amount = self.context().apparent_value; + ::BalanceConverter::into_substrate_balance(amount).ok_or( + PrecompileFailure::Error { + exit_status: ExitError::Other( + "error converting balance from ETH to subtensor".into(), + ), + }, + ) + } - match call.dispatch(origin.into()) { - Ok(post_info) => { - if post_info.pays_fee(&info) == Pays::Yes { - let actual_weight = post_info.actual_weight.unwrap_or(info.weight); - let cost = - ::GasWeightMapping::weight_to_gas(actual_weight); - handle.record_cost(cost)?; + /// Dispatches a runtime call, but also checks and records the gas costs. + fn try_dispatch_runtime_call( + &mut self, + call: impl Into, + origin: RawOrigin, + ) -> EvmResult<()> { + let call = Into::::into(call); + let info = call.get_dispatch_info(); - handle.refund_external_cost( - Some( - info.weight - .ref_time() - .saturating_sub(actual_weight.ref_time()), - ), - Some( - info.weight - .proof_size() - .saturating_sub(actual_weight.proof_size()), - ), - ); + let target_gas = self.gas_limit(); + if let Some(gas) = target_gas { + let valid_weight = + ::GasWeightMapping::gas_to_weight(gas, false) + .ref_time(); + if info.weight.ref_time() > valid_weight { + return Err(PrecompileFailure::Error { + exit_status: ExitError::OutOfGas, + }); } + } - log::info!("Dispatch succeeded. Post info: {:?}", post_info); + self.record_external_cost( + Some(info.weight.ref_time()), + Some(info.weight.proof_size()), + None, + )?; - Ok(PrecompileOutput { - exit_status: ExitSucceed::Returned, - output: Default::default(), - }) - } - Err(e) => { - log::error!("Dispatch failed. Error: {:?}", e); - log::warn!("Returning error PrecompileFailure::Error"); - Err(PrecompileFailure::Error { - exit_status: ExitError::Other( - format!("dispatch execution failed: {}", <&'static str>::from(e)).into(), - ), - }) + match call.dispatch(origin.into()) { + Ok(post_info) => { + if post_info.pays_fee(&info) == Pays::Yes { + let actual_weight = post_info.actual_weight.unwrap_or(info.weight); + let cost = ::GasWeightMapping::weight_to_gas( + actual_weight, + ); + self.record_cost(cost)?; + + self.refund_external_cost( + Some( + info.weight + .ref_time() + .saturating_sub(actual_weight.ref_time()), + ), + Some( + info.weight + .proof_size() + .saturating_sub(actual_weight.proof_size()), + ), + ); + } + + log::info!("Dispatch succeeded. Post info: {:?}", post_info); + + Ok(()) + } + Err(e) => { + log::error!("Dispatch failed. Error: {:?}", e); + log::warn!("Returning error PrecompileFailure::Error"); + Err(PrecompileFailure::Error { + exit_status: ExitError::Other( + format!("dispatch execution failed: {}", <&'static str>::from(e)).into(), + ), + }) + } } } } -/// Retrieves a single u8 value from the given data slice at the specified index. -/// -/// # Args -/// * `data`: The slice of bytes from which to retrieve the u8 value. -/// * `index`: The index within the `data` slice where the u8 value is located. -/// -/// # Returns -/// A `Result` containing the u8 value at the specified index if successful, or a `PrecompileFailure` if the index is out of range. -pub fn get_single_u8(data: &[u8], index: usize) -> Result { - if let Some(result) = data.get(index) { - Ok(*result) - } else { - log::error!("fail to get data from data, {:?}, at {}", &data, index); - Err(PrecompileFailure::Error { - exit_status: ExitError::InvalidRange, - }) - } +impl PrecompileHandleExt for T where T: PrecompileHandle {} + +trait PrecompileExt: Precompile { + const INDEX: u64; + // ss58 public key i.e., the contract sends funds it received to the destination address from + // the method parameter. + const ADDRESS_SS58: [u8; 32]; } diff --git a/runtime/src/precompiles/neuron.rs b/runtime/src/precompiles/neuron.rs index 38fb701fbe..f8fd1f1586 100644 --- a/runtime/src/precompiles/neuron.rs +++ b/runtime/src/precompiles/neuron.rs @@ -1,157 +1,109 @@ -use pallet_evm::{ - AddressMapping, ExitError, HashedAddressMapping, PrecompileFailure, PrecompileHandle, - PrecompileResult, -}; - -use crate::precompiles::{ - get_method_id, get_pubkey, get_single_u8, get_slice, parse_netuid, try_dispatch_runtime_call, -}; -use crate::{Runtime, RuntimeCall}; use frame_system::RawOrigin; +use pallet_evm::PrecompileHandle; +use precompile_utils::{prelude::UnboundedBytes, EvmResult}; use sp_core::H256; -use sp_runtime::traits::BlakeTwo256; -use sp_runtime::AccountId32; -use sp_std::vec; use sp_std::vec::Vec; -pub const NEURON_PRECOMPILE_INDEX: u64 = 2052; -// max paramter lenght 4K -pub const MAX_PARAMETER_SIZE: usize = 4 * 1024; -// ss58 public key i.e., the contract sends funds it received to the destination address from the -// method parameter. -#[allow(dead_code)] -const CONTRACT_ADDRESS_SS58: [u8; 32] = [ - 0xbc, 0x46, 0x35, 0x79, 0xbc, 0x99, 0xf9, 0xee, 0x7c, 0x59, 0xed, 0xee, 0x20, 0x61, 0xa3, 0x09, - 0xd2, 0x1e, 0x68, 0xd5, 0x39, 0xb6, 0x40, 0xec, 0x66, 0x46, 0x90, 0x30, 0xab, 0x74, 0xc1, 0xdb, -]; -pub struct NeuronPrecompile; - -impl NeuronPrecompile { - pub fn execute(handle: &mut impl PrecompileHandle) -> PrecompileResult { - let txdata = handle.input(); - let method_id = get_slice(txdata, 0, 4)?; - let method_input = txdata - .get(4..) - .map_or_else(vec::Vec::new, |slice| slice.to_vec()); // Avoiding borrowing conflicts - - if method_input.len() > MAX_PARAMETER_SIZE { - log::error!( - "method parameter data length as {} is too long", - method_input.len() - ); - return Err(PrecompileFailure::Error { - exit_status: ExitError::InvalidRange, - }); - } - - match method_id { - id if id == get_method_id("setWeights(uint16,uint16[],uint16[],uint64)") => { - Self::set_weights(handle, &method_input) - } - id if id == get_method_id("commitWeights(uint16,uint256)") => { - Self::commit_weights(handle, &method_input) - } - id if id - == get_method_id("revealWeights(uint16,uint16[],uint16[],uint16[],uint64)") => - { - Self::reveal_weights(handle, &method_input) - } +use crate::precompiles::{parse_pubkey, PrecompileExt, PrecompileHandleExt}; +use crate::Runtime; - id if id == get_method_id("burnedRegister(uint16,bytes32)") => { - Self::burned_register(handle, &method_input) - } - id if id - == get_method_id( - "serveAxon(uint16,uint32,uint128,uint16,uint8,uint8,uint8,uint8)", - ) => - { - Self::serve_axon(handle, &method_input) - } - id if id - == get_method_id( - "serveAxonTls(uint16,uint32,uint128,uint16,uint8,uint8,uint8,uint8,bytes)", - ) => - { - Self::serve_axon_tls(handle, &method_input) - } - id if id == get_method_id("servePrometheus(uint16,uint32,uint128,uint16,uint8)") => { - Self::serve_prometheus(handle, &method_input) - } +pub struct NeuronPrecompile; - _ => Err(PrecompileFailure::Error { - exit_status: ExitError::InvalidRange, - }), - } - } +impl PrecompileExt for NeuronPrecompile { + const INDEX: u64 = 2052; + const ADDRESS_SS58: [u8; 32] = [ + 0xbc, 0x46, 0x35, 0x79, 0xbc, 0x99, 0xf9, 0xee, 0x7c, 0x59, 0xed, 0xee, 0x20, 0x61, 0xa3, + 0x09, 0xd2, 0x1e, 0x68, 0xd5, 0x39, 0xb6, 0x40, 0xec, 0x66, 0x46, 0x90, 0x30, 0xab, 0x74, + 0xc1, 0xdb, + ]; +} - pub fn set_weights(handle: &mut impl PrecompileHandle, data: &[u8]) -> PrecompileResult { - let (netuid, dests, weights, version_key) = Self::parse_netuid_dests_weights(data)?; - let call = RuntimeCall::SubtensorModule(pallet_subtensor::Call::::set_weights { +#[precompile_utils::precompile] +impl NeuronPrecompile { + #[precompile::public("setWeights(uint16,uint16[],uint16[],uint64)")] + #[precompile::payable] + pub fn set_weights( + handle: &mut impl PrecompileHandle, + netuid: u16, + dests: Vec, + weights: Vec, + version_key: u64, + ) -> EvmResult<()> { + let call = pallet_subtensor::Call::::set_weights { netuid, dests, weights, version_key, - }); - let account_id = - as AddressMapping>::into_account_id( - handle.context().caller, - ); + }; - try_dispatch_runtime_call(handle, call, RawOrigin::Signed(account_id)) + handle.try_dispatch_runtime_call(call, RawOrigin::Signed(handle.caller_account_id())) } - pub fn commit_weights(handle: &mut impl PrecompileHandle, data: &[u8]) -> PrecompileResult { - let (netuid, commit_hash) = Self::parse_netuid_commit_hash(data)?; + #[precompile::public("commitWeights(uint16,bytes32)")] + #[precompile::payable] + pub fn commit_weights( + handle: &mut impl PrecompileHandle, + netuid: u16, + commit_hash: H256, + ) -> EvmResult<()> { + let call = pallet_subtensor::Call::::commit_weights { + netuid, + commit_hash, + }; - let call = - RuntimeCall::SubtensorModule(pallet_subtensor::Call::::commit_weights { - netuid, - commit_hash, - }); - let account_id = - as AddressMapping>::into_account_id( - handle.context().caller, - ); - try_dispatch_runtime_call(handle, call, RawOrigin::Signed(account_id)) + handle.try_dispatch_runtime_call(call, RawOrigin::Signed(handle.caller_account_id())) } - pub fn reveal_weights(handle: &mut impl PrecompileHandle, data: &[u8]) -> PrecompileResult { - let (netuid, uids, values, salt, version_key) = - Self::parse_netuid_dests_weights_salt(data)?; - let call = - RuntimeCall::SubtensorModule(pallet_subtensor::Call::::reveal_weights { - netuid, - uids, - values, - salt, - version_key, - }); - let account_id = - as AddressMapping>::into_account_id( - handle.context().caller, - ); - try_dispatch_runtime_call(handle, call, RawOrigin::Signed(account_id)) - } + #[precompile::public("revealWeights(uint16,uint16[],uint16[],uint16[],uint64)")] + #[precompile::payable] + pub fn reveal_weights( + handle: &mut impl PrecompileHandle, + netuid: u16, + uids: Vec, + values: Vec, + salt: Vec, + version_key: u64, + ) -> EvmResult<()> { + let call = pallet_subtensor::Call::::reveal_weights { + netuid, + uids, + values, + salt, + version_key, + }; - pub fn burned_register(handle: &mut impl PrecompileHandle, data: &[u8]) -> PrecompileResult { - let (netuid, hotkey) = Self::parse_netuid_hotkey_parameter(data)?; - let call = - RuntimeCall::SubtensorModule(pallet_subtensor::Call::::burned_register { - netuid, - hotkey, - }); - let account_id = - as AddressMapping>::into_account_id( - handle.context().caller, - ); + handle.try_dispatch_runtime_call(call, RawOrigin::Signed(handle.caller_account_id())) + } - try_dispatch_runtime_call(handle, call, RawOrigin::Signed(account_id)) + #[precompile::public("burnedRegister(uint16,bytes32)")] + #[precompile::payable] + fn burned_register( + handle: &mut impl PrecompileHandle, + netuid: u16, + hotkey: H256, + ) -> EvmResult<()> { + let coldkey = handle.caller_account_id(); + let (hotkey, _) = parse_pubkey(hotkey.as_bytes())?; + let call = pallet_subtensor::Call::::burned_register { netuid, hotkey }; + + handle.try_dispatch_runtime_call(call, RawOrigin::Signed(coldkey)) } - pub fn serve_axon(handle: &mut impl PrecompileHandle, data: &[u8]) -> PrecompileResult { - let (netuid, version, ip, port, ip_type, protocol, placeholder1, placeholder2) = - Self::parse_serve_axon_parameters(data)?; - let call = RuntimeCall::SubtensorModule(pallet_subtensor::Call::::serve_axon { + #[precompile::public("serveAxon(uint16,uint32,uint128,uint16,uint8,uint8,uint8,uint8)")] + #[precompile::payable] + #[allow(clippy::too_many_arguments)] + fn serve_axon( + handle: &mut impl PrecompileHandle, + netuid: u16, + version: u32, + ip: u128, + port: u16, + ip_type: u8, + protocol: u8, + placeholder1: u8, + placeholder2: u8, + ) -> EvmResult<()> { + let call = pallet_subtensor::Call::::serve_axon { netuid, version, ip, @@ -160,367 +112,29 @@ impl NeuronPrecompile { protocol, placeholder1, placeholder2, - }); - let account_id = - as AddressMapping>::into_account_id( - handle.context().caller, - ); - - try_dispatch_runtime_call(handle, call, RawOrigin::Signed(account_id)) - } - - pub fn serve_axon_tls(handle: &mut impl PrecompileHandle, data: &[u8]) -> PrecompileResult { - let (netuid, version, ip, port, ip_type, protocol, placeholder1, placeholder2, certificate) = - Self::parse_serve_axon_tls_parameters(data)?; - let call = - RuntimeCall::SubtensorModule(pallet_subtensor::Call::::serve_axon_tls { - netuid, - version, - ip, - port, - ip_type, - protocol, - placeholder1, - placeholder2, - certificate, - }); - let account_id = - as AddressMapping>::into_account_id( - handle.context().caller, - ); + }; - try_dispatch_runtime_call(handle, call, RawOrigin::Signed(account_id)) + handle.try_dispatch_runtime_call(call, RawOrigin::Signed(handle.caller_account_id())) } - pub fn serve_prometheus(handle: &mut impl PrecompileHandle, data: &[u8]) -> PrecompileResult { - let (netuid, version, ip, port, ip_type) = Self::parse_serve_prometheus_parameters(data)?; - let call = - RuntimeCall::SubtensorModule(pallet_subtensor::Call::::serve_prometheus { - netuid, - version, - ip, - port, - ip_type, - }); - let account_id = - as AddressMapping>::into_account_id( - handle.context().caller, - ); - - // Dispatch the register_network call - try_dispatch_runtime_call(handle, call, RawOrigin::Signed(account_id)) - } - - fn parse_netuid_hotkey_parameter(data: &[u8]) -> Result<(u16, AccountId32), PrecompileFailure> { - if data.len() < 64 { - return Err(PrecompileFailure::Error { - exit_status: ExitError::InvalidRange, - }); - } - - let netuid = parse_netuid(data, 30)?; - - let (hotkey, _) = get_pubkey(get_slice(data, 32, 64)?)?; - - Ok((netuid, hotkey)) - } - - fn parse_netuid_dests_weights( - data: &[u8], - ) -> Result<(u16, Vec, Vec, u64), PrecompileFailure> { - let data_len = data.len(); - if data_len < 4 * 32 { - return Err(PrecompileFailure::Error { - exit_status: ExitError::InvalidRange, - }); - } - let mut netuid_vec = [0u8; 2]; - netuid_vec.copy_from_slice(get_slice(data, 30, 32)?); - let netuid = u16::from_be_bytes(netuid_vec); - - // get the neuron amount in sebnet - let subnet_size = pallet_subtensor::Pallet::::get_subnetwork_n(netuid) as usize; - - let mut first_position_vec = [0u8; 2]; - first_position_vec.copy_from_slice(get_slice(data, 62, 64)?); - let first_position = u16::from_be_bytes(first_position_vec) as usize; - - if first_position > data_len { - log::error!("position for uids data as {} is too large", first_position); - return Err(PrecompileFailure::Error { - exit_status: ExitError::InvalidRange, - }); - } - - let mut second_position_vec = [0u8; 2]; - second_position_vec.copy_from_slice(get_slice(data, 94, 96)?); - let second_position = u16::from_be_bytes(second_position_vec) as usize; - - if second_position > data_len { - log::error!("position for uids data as {} is too large", first_position); - return Err(PrecompileFailure::Error { - exit_status: ExitError::InvalidRange, - }); - } - - let mut version_key_vec = [0u8; 8]; - version_key_vec.copy_from_slice(get_slice(data, 120, 128)?); - let version_key = u64::from_be_bytes(version_key_vec); - - let mut dests = vec![]; - let mut weights = vec![]; - - let mut dests_len_vec = [0u8; 2]; - dests_len_vec.copy_from_slice(get_slice(data, first_position + 30, first_position + 32)?); - let dests_len = u16::from_be_bytes(dests_len_vec) as usize; - - if dests_len > subnet_size { - log::error!( - "uids len as {} in set weight is more than neurons {} in subnet {}", - dests_len, - subnet_size, - netuid - ); - return Err(PrecompileFailure::Error { - exit_status: ExitError::InvalidRange, - }); - } - - for i in 0..dests_len { - let mut tmp_vec = [0u8; 2]; - let from = first_position - .saturating_add(62) - .saturating_add(i.saturating_mul(32)); - let to = from.saturating_add(2); - tmp_vec.copy_from_slice(get_slice(data, from, to)?); - let dest = u16::from_be_bytes(tmp_vec); - dests.push(dest); - } - - let mut weights_len_vec = [0u8; 2]; - weights_len_vec.copy_from_slice(get_slice( - data, - second_position + 30, - second_position + 32, - )?); - let weights_len = u16::from_be_bytes(weights_len_vec) as usize; - - if weights_len > subnet_size { - log::error!( - "weights len as {} in set weight is more than neurons {} in subnet {}", - weights_len, - subnet_size, - netuid - ); - return Err(PrecompileFailure::Error { - exit_status: ExitError::InvalidRange, - }); - } - - for i in 0..weights_len { - let mut tmp_vec = [0u8; 2]; - let from = second_position - .saturating_add(62) - .saturating_add(i.saturating_mul(32)); - let to = from.saturating_add(2); - tmp_vec.copy_from_slice(get_slice(data, from, to)?); - let weight = u16::from_be_bytes(tmp_vec); - weights.push(weight); - } - - Ok((netuid, dests, weights, version_key)) - } - - fn parse_netuid_commit_hash(data: &[u8]) -> Result<(u16, H256), PrecompileFailure> { - if data.len() < 2 * 32 { - return Err(PrecompileFailure::Error { - exit_status: ExitError::InvalidRange, - }); - } - - let mut netuid_vec = [0u8; 2]; - netuid_vec.copy_from_slice(get_slice(data, 30, 32)?); - let netuid = u16::from_be_bytes(netuid_vec); - let commit_hash = H256::from_slice(get_slice(data, 32, 64)?); - - Ok((netuid, commit_hash)) - } - - fn parse_netuid_dests_weights_salt( - data: &[u8], - ) -> Result<(u16, Vec, Vec, Vec, u64), PrecompileFailure> { - let data_len = data.len(); - if data_len < 5 * 32 { - return Err(PrecompileFailure::Error { - exit_status: ExitError::InvalidRange, - }); - } - - let netuid = parse_netuid(data, 30)?; - - // get the neuron amount in sebnet - let subnet_size = pallet_subtensor::Pallet::::get_subnetwork_n(netuid) as usize; - - let mut first_position_vec = [0u8; 2]; - first_position_vec.copy_from_slice(get_slice(data, 62, 64)?); - let first_position = u16::from_be_bytes(first_position_vec) as usize; - - if first_position > data_len { - log::error!("position for uids data as {} is too large", first_position); - return Err(PrecompileFailure::Error { - exit_status: ExitError::InvalidRange, - }); - } - - let mut second_position_vec = [0u8; 2]; - second_position_vec.copy_from_slice(get_slice(data, 94, 96)?); - let second_position = u16::from_be_bytes(second_position_vec) as usize; - - if second_position > data_len { - log::error!( - "position for values data as {} is too large", - first_position - ); - return Err(PrecompileFailure::Error { - exit_status: ExitError::InvalidRange, - }); - } - - let mut third_position_vec = [0u8; 2]; - third_position_vec.copy_from_slice(get_slice(data, 126, 128)?); - let third_position = u16::from_be_bytes(third_position_vec) as usize; - - if third_position > data_len { - log::error!("position for salt data as {} is too large", first_position); - return Err(PrecompileFailure::Error { - exit_status: ExitError::InvalidRange, - }); - } - - let mut version_key_vec = [0u8; 8]; - version_key_vec.copy_from_slice(get_slice(data, 152, 160)?); - let version_key = u64::from_be_bytes(version_key_vec); - - let mut uids = vec![]; - let mut values = vec![]; - let mut salt = vec![]; - - let mut uids_len_vec = [0u8; 2]; - uids_len_vec.copy_from_slice(get_slice(data, first_position + 30, first_position + 32)?); - let uids_len = u16::from_be_bytes(uids_len_vec) as usize; - - if uids_len > subnet_size { - log::error!( - "uids len as {} in reveal weight is more than neurons {} in subnet {}", - uids_len, - subnet_size, - netuid - ); - return Err(PrecompileFailure::Error { - exit_status: ExitError::InvalidRange, - }); - } - - for i in 0..uids_len { - let mut tmp_vec = [0u8; 2]; - let from = first_position - .saturating_add(62) - .saturating_add(i.saturating_mul(32)); - let to = from.saturating_add(2); - tmp_vec.copy_from_slice(get_slice(data, from, to)?); - let uid = u16::from_be_bytes(tmp_vec); - uids.push(uid); - } - - let mut values_len_vec = [0u8; 2]; - values_len_vec.copy_from_slice(get_slice( - data, - second_position + 30, - second_position + 32, - )?); - let values_len = u16::from_be_bytes(values_len_vec) as usize; - - if values_len > subnet_size { - log::error!( - "values len as {} in reveal weight is more than neurons {} in subnet {}", - values_len, - subnet_size, - netuid - ); - return Err(PrecompileFailure::Error { - exit_status: ExitError::InvalidRange, - }); - } - - for i in 0..values_len { - let mut tmp_vec = [0u8; 2]; - let from = second_position - .saturating_add(62) - .saturating_add(i.saturating_mul(32)); - let to = from.saturating_add(2); - tmp_vec.copy_from_slice(get_slice(data, from, to)?); - let value = u16::from_be_bytes(tmp_vec); - values.push(value); - } - - let mut salt_len_vec = [0u8; 2]; - salt_len_vec.copy_from_slice(get_slice(data, third_position + 30, third_position + 32)?); - let salt_len = u16::from_be_bytes(salt_len_vec) as usize; - - if salt_len > subnet_size { - log::error!( - "salt len as {} in reveal weight is more than neurons {} in subnet {}", - salt_len, - subnet_size, - netuid - ); - return Err(PrecompileFailure::Error { - exit_status: ExitError::InvalidRange, - }); - } - - for i in 0..salt_len { - let mut tmp_vec = [0u8; 2]; - let from = third_position - .saturating_add(62) - .saturating_add(i.saturating_mul(32)); - let to = from.saturating_add(2); - tmp_vec.copy_from_slice(get_slice(data, from, to)?); - let value = u16::from_be_bytes(tmp_vec); - salt.push(value); - } - - Ok((netuid, uids, values, salt, version_key)) - } - - fn parse_serve_axon_parameters( - data: &[u8], - ) -> Result<(u16, u32, u128, u16, u8, u8, u8, u8), PrecompileFailure> { - if data.len() < 256 { - return Err(PrecompileFailure::Error { - exit_status: ExitError::InvalidRange, - }); - } - - let netuid = parse_netuid(data, 30)?; - - let mut version_vec = [0u8; 4]; - version_vec.copy_from_slice(get_slice(data, 60, 64)?); - let version = u32::from_be_bytes(version_vec); - - let mut ip_vec = [0u8; 16]; - ip_vec.copy_from_slice(get_slice(data, 80, 96)?); - let ip = u128::from_be_bytes(ip_vec); - - let mut port_vec = [0u8; 2]; - port_vec.copy_from_slice(get_slice(data, 126, 128)?); - let port = u16::from_be_bytes(port_vec); - - let ip_type = get_single_u8(data, 159)?; - let protocol = get_single_u8(data, 191)?; - let placeholder1 = get_single_u8(data, 223)?; - let placeholder2 = get_single_u8(data, 255)?; - Ok(( + #[precompile::public( + "serveAxonTls(uint16,uint32,uint128,uint16,uint8,uint8,uint8,uint8,bytes)" + )] + #[precompile::payable] + #[allow(clippy::too_many_arguments)] + fn serve_axon_tls( + handle: &mut impl PrecompileHandle, + netuid: u16, + version: u32, + ip: u128, + port: u16, + ip_type: u8, + protocol: u8, + placeholder1: u8, + placeholder2: u8, + certificate: UnboundedBytes, + ) -> EvmResult<()> { + let call = pallet_subtensor::Call::::serve_axon_tls { netuid, version, ip, @@ -529,101 +143,31 @@ impl NeuronPrecompile { protocol, placeholder1, placeholder2, - )) - } - - fn parse_serve_axon_tls_parameters( - data: &[u8], - ) -> Result<(u16, u32, u128, u16, u8, u8, u8, u8, vec::Vec), PrecompileFailure> { - let data_len = data.len(); - if data_len < 288 { - return Err(PrecompileFailure::Error { - exit_status: ExitError::InvalidRange, - }); - } - - let netuid = parse_netuid(data, 30)?; - - let mut version_vec = [0u8; 4]; - version_vec.copy_from_slice(get_slice(data, 60, 64)?); - let version = u32::from_be_bytes(version_vec); - - let mut ip_vec = [0u8; 16]; - ip_vec.copy_from_slice(get_slice(data, 80, 96)?); - let ip = u128::from_be_bytes(ip_vec); - - let mut port_vec = [0u8; 2]; - port_vec.copy_from_slice(get_slice(data, 126, 128)?); - let port = u16::from_be_bytes(port_vec); - - let ip_type = get_single_u8(data, 159)?; - let protocol = get_single_u8(data, 191)?; - let placeholder1 = get_single_u8(data, 223)?; - let placeholder2 = get_single_u8(data, 255)?; - - let mut len_position_vec = [0u8; 2]; - len_position_vec.copy_from_slice(get_slice(data, 286, 288)?); - let len_position = u16::from_be_bytes(len_position_vec) as usize; - - if len_position > data_len { - log::error!( - "the start position of certificate as {} is bigger than whole data len {}", - len_position, - data_len - ); - return Err(PrecompileFailure::Error { - exit_status: ExitError::InvalidRange, - }); - } + certificate: certificate.into(), + }; - let mut len_vec = [0u8; 2]; - len_vec.copy_from_slice(get_slice(data, len_position + 30, len_position + 32)?); - let vec_len = u16::from_be_bytes(len_vec) as usize; - - let vec_result = get_slice( - data, - len_position + 32, - len_position.saturating_add(32).saturating_add(vec_len), - )? - .to_vec(); + handle.try_dispatch_runtime_call(call, RawOrigin::Signed(handle.caller_account_id())) + } - Ok(( + #[precompile::public("servePrometheus(uint16,uint32,uint128,uint16,uint8)")] + #[precompile::payable] + #[allow(clippy::too_many_arguments)] + fn serve_prometheus( + handle: &mut impl PrecompileHandle, + netuid: u16, + version: u32, + ip: u128, + port: u16, + ip_type: u8, + ) -> EvmResult<()> { + let call = pallet_subtensor::Call::::serve_prometheus { netuid, version, ip, port, ip_type, - protocol, - placeholder1, - placeholder2, - vec_result, - )) - } - - fn parse_serve_prometheus_parameters( - data: &[u8], - ) -> Result<(u16, u32, u128, u16, u8), PrecompileFailure> { - if data.len() < 160 { - return Err(PrecompileFailure::Error { - exit_status: ExitError::InvalidRange, - }); - } - - let netuid = parse_netuid(data, 30)?; - - let mut version_vec = [0u8; 4]; - version_vec.copy_from_slice(get_slice(data, 60, 64)?); - let version = u32::from_be_bytes(version_vec); - - let mut ip_vec = [0u8; 16]; - ip_vec.copy_from_slice(get_slice(data, 80, 96)?); - let ip = u128::from_be_bytes(ip_vec); - - let mut port_vec = [0u8; 2]; - port_vec.copy_from_slice(get_slice(data, 126, 128)?); - let port = u16::from_be_bytes(port_vec); + }; - let ip_type = get_single_u8(data, 159)?; - Ok((netuid, version, ip, port, ip_type)) + handle.try_dispatch_runtime_call(call, RawOrigin::Signed(handle.caller_account_id())) } } diff --git a/runtime/src/precompiles/solidity/neuron.abi b/runtime/src/precompiles/solidity/neuron.abi index e12685f99f..e4ffb6fa18 100644 --- a/runtime/src/precompiles/solidity/neuron.abi +++ b/runtime/src/precompiles/solidity/neuron.abi @@ -25,9 +25,9 @@ "type": "uint16" }, { - "internalType": "uint256", + "internalType": "bytes32", "name": "commitHash", - "type": "uint256" + "type": "bytes32" } ], "name": "commitWeights", @@ -230,4 +230,4 @@ "stateMutability": "payable", "type": "function" } -] \ No newline at end of file +] diff --git a/runtime/src/precompiles/solidity/neuron.sol b/runtime/src/precompiles/solidity/neuron.sol index 772f290638..204bc3f600 100644 --- a/runtime/src/precompiles/solidity/neuron.sol +++ b/runtime/src/precompiles/solidity/neuron.sol @@ -99,9 +99,9 @@ interface INeuron { * @dev Commits the weights for a neuron. * * @param netuid The subnet to commit the weights for (uint16). - * @param commitHash The commit hash for the weights (uint256). + * @param commitHash The commit hash for the weights (bytes32). */ - function commitWeights(uint16 netuid, uint256 commitHash) external payable; + function commitWeights(uint16 netuid, bytes32 commitHash) external payable; /** * @dev Reveals the weights for a neuron. diff --git a/runtime/src/precompiles/solidity/subnet.abi b/runtime/src/precompiles/solidity/subnet.abi index fd81850b74..3cc16d9df7 100644 --- a/runtime/src/precompiles/solidity/subnet.abi +++ b/runtime/src/precompiles/solidity/subnet.abi @@ -148,9 +148,9 @@ "name": "getImmunityPeriod", "outputs": [ { - "internalType": "uint64", + "internalType": "uint16", "name": "", - "type": "uint64" + "type": "uint16" } ], "stateMutability": "view", @@ -243,9 +243,9 @@ "name": "getMaxWeightLimit", "outputs": [ { - "internalType": "uint64", + "internalType": "uint16", "name": "", - "type": "uint64" + "type": "uint16" } ], "stateMutability": "view", @@ -443,39 +443,39 @@ "type": "bytes32" }, { - "internalType": "bytes", + "internalType": "string", "name": "subnetName", - "type": "bytes" + "type": "string" }, { - "internalType": "bytes", + "internalType": "string", "name": "githubRepo", - "type": "bytes" + "type": "string" }, { - "internalType": "bytes", + "internalType": "string", "name": "subnetContact", - "type": "bytes" + "type": "string" }, { - "internalType": "bytes", + "internalType": "string", "name": "subnetUrl", - "type": "bytes" + "type": "string" }, { - "internalType": "bytes", + "internalType": "string", "name": "discord", - "type": "bytes" + "type": "string" }, { - "internalType": "bytes", + "internalType": "string", "name": "description", - "type": "bytes" + "type": "string" }, { - "internalType": "bytes", + "internalType": "string", "name": "additional", - "type": "bytes" + "type": "string" } ], "name": "registerNetwork", @@ -622,9 +622,9 @@ "type": "uint16" }, { - "internalType": "uint64", + "internalType": "uint16", "name": "immunityPeriod", - "type": "uint64" + "type": "uint16" } ], "name": "setImmunityPeriod", @@ -712,9 +712,9 @@ "type": "uint16" }, { - "internalType": "uint64", + "internalType": "uint16", "name": "maxWeightLimit", - "type": "uint64" + "type": "uint16" } ], "name": "setMaxWeightLimit", @@ -884,4 +884,4 @@ "stateMutability": "payable", "type": "function" } -] \ No newline at end of file +] diff --git a/runtime/src/precompiles/solidity/subnet.sol b/runtime/src/precompiles/solidity/subnet.sol index 1afeced493..d5ef0916d9 100644 --- a/runtime/src/precompiles/solidity/subnet.sol +++ b/runtime/src/precompiles/solidity/subnet.sol @@ -8,13 +8,13 @@ interface ISubnet { /// Registers a new network with specified subnet name, GitHub repository, and contact information. function registerNetwork( bytes32 hotkey, - bytes memory subnetName, - bytes memory githubRepo, - bytes memory subnetContact, - bytes memory subnetUrl, - bytes memory discord, - bytes memory description, - bytes memory additional + string memory subnetName, + string memory githubRepo, + string memory subnetContact, + string memory subnetUrl, + string memory discord, + string memory description, + string memory additional ) external payable; function getServingRateLimit(uint16 netuid) external view returns (uint64); @@ -61,14 +61,14 @@ interface ISubnet { uint64 adjustmentAlpha ) external payable; - function getMaxWeightLimit(uint16 netuid) external view returns (uint64); + function getMaxWeightLimit(uint16 netuid) external view returns (uint16); function setMaxWeightLimit( uint16 netuid, - uint64 maxWeightLimit + uint16 maxWeightLimit ) external payable; - function getImmunityPeriod(uint16) external view returns (uint64); + function getImmunityPeriod(uint16) external view returns (uint16); function setImmunityPeriod( uint16 netuid, diff --git a/runtime/src/precompiles/staking.rs b/runtime/src/precompiles/staking.rs index 8cc1c879af..84b2d84700 100644 --- a/runtime/src/precompiles/staking.rs +++ b/runtime/src/precompiles/staking.rs @@ -25,173 +25,122 @@ // - Precompile checks the result of do_remove_stake and, in case of a failure, reverts the transaction. // -use crate::precompiles::{ - get_method_id, get_pubkey, get_slice, parse_netuid, try_dispatch_runtime_call, -}; -use crate::{ProxyType, Runtime, RuntimeCall}; use frame_system::RawOrigin; -use pallet_evm::{ - AddressMapping, BalanceConverter, ExitError, ExitSucceed, HashedAddressMapping, - PrecompileFailure, PrecompileHandle, PrecompileOutput, PrecompileResult, -}; -use sp_core::U256; -use sp_runtime::traits::{BlakeTwo256, Dispatchable, StaticLookup, UniqueSaturatedInto}; +use pallet_evm::{BalanceConverter, ExitError, PrecompileFailure, PrecompileHandle}; +use precompile_utils::EvmResult; +use sp_core::{H256, U256}; +use sp_runtime::traits::{Dispatchable, StaticLookup, UniqueSaturatedInto}; use sp_runtime::AccountId32; -use sp_std::vec; - -pub const STAKING_PRECOMPILE_INDEX: u64 = 2049; -// ss58 public key i.e., the contract sends funds it received to the destination address from the -// method parameter. -const CONTRACT_ADDRESS_SS58: [u8; 32] = [ - 0x26, 0xf4, 0x10, 0x1e, 0x52, 0xb7, 0x57, 0x34, 0x33, 0x24, 0x5b, 0xc3, 0x0a, 0xe1, 0x8b, 0x63, - 0x99, 0x53, 0xd8, 0x41, 0x79, 0x33, 0x03, 0x61, 0x4d, 0xfa, 0xcf, 0xf0, 0x37, 0xf7, 0x12, 0x94, -]; +use crate::precompiles::{parse_pubkey, try_u16_from_u256, PrecompileExt, PrecompileHandleExt}; +use crate::{ProxyType, Runtime, RuntimeCall}; pub struct StakingPrecompile; -impl StakingPrecompile { - pub fn execute(handle: &mut impl PrecompileHandle) -> PrecompileResult { - let txdata = handle.input(); - let method_id = get_slice(txdata, 0, 4)?; - let method_input = txdata - .get(4..) - .map_or_else(vec::Vec::new, |slice| slice.to_vec()); // Avoiding borrowing conflicts - - if method_id == get_method_id("addStake(bytes32,uint256)") { - Self::add_stake(handle, &method_input) - } else if method_id == get_method_id("removeStake(bytes32,uint256,uint256)") { - Self::remove_stake(handle, &method_input) - } else if method_id == get_method_id("getStake(bytes32,bytes32,uint256)") { - Self::get_stake(&method_input) - } else if method_id == get_method_id("addProxy(bytes32)") { - Self::add_proxy(handle, &method_input) - } else if method_id == get_method_id("removeProxy(bytes32)") { - Self::remove_proxy(handle, &method_input) - } else { - Err(PrecompileFailure::Error { - exit_status: ExitError::InvalidRange, - }) - } - } - - fn add_stake(handle: &mut impl PrecompileHandle, data: &[u8]) -> PrecompileResult { - let account_id = - as AddressMapping>::into_account_id( - handle.context().caller, - ); +impl PrecompileExt for StakingPrecompile { + const INDEX: u64 = 2049; + const ADDRESS_SS58: [u8; 32] = [ + 0x26, 0xf4, 0x10, 0x1e, 0x52, 0xb7, 0x57, 0x34, 0x33, 0x24, 0x5b, 0xc3, 0x0a, 0xe1, 0x8b, + 0x63, 0x99, 0x53, 0xd8, 0x41, 0x79, 0x33, 0x03, 0x61, 0x4d, 0xfa, 0xcf, 0xf0, 0x37, 0xf7, + 0x12, 0x94, + ]; +} - let (hotkey, _) = get_pubkey(data)?; - let amount: U256 = handle.context().apparent_value; - let netuid = parse_netuid(data, 0x3E)?; +#[precompile_utils::precompile] +impl StakingPrecompile { + #[precompile::public("addStake(bytes32,uint256)")] + #[precompile::payable] + fn add_stake(handle: &mut impl PrecompileHandle, address: H256, netuid: U256) -> EvmResult<()> { + let account_id = handle.caller_account_id(); + let amount = handle.context().apparent_value; if !amount.is_zero() { Self::transfer_back_to_caller(&account_id, amount)?; } - let amount_sub = - ::BalanceConverter::into_substrate_balance(amount) - .ok_or(ExitError::OutOfFund)?; - - let call = RuntimeCall::SubtensorModule(pallet_subtensor::Call::::add_stake { + let amount_sub = handle.try_convert_apparent_value()?; + let (hotkey, _) = parse_pubkey(address.as_bytes())?; + let netuid = try_u16_from_u256(netuid)?; + let call = pallet_subtensor::Call::::add_stake { hotkey, netuid, amount_staked: amount_sub.unique_saturated_into(), - }); + }; - try_dispatch_runtime_call(handle, call, RawOrigin::Signed(account_id)) + handle.try_dispatch_runtime_call(call, RawOrigin::Signed(account_id)) } - fn remove_stake(handle: &mut impl PrecompileHandle, data: &[u8]) -> PrecompileResult { - let account_id = - as AddressMapping>::into_account_id( - handle.context().caller, - ); - let (hotkey, _) = get_pubkey(data)?; - let netuid = parse_netuid(data, 0x5E)?; - - // We have to treat this as uint256 (because of Solidity ABI encoding rules, it pads uint64), - // but this will never exceed 8 bytes, se we will ignore higher bytes and will only use lower - // 8 bytes. - let amount = data - .get(56..64) - .map(U256::from_big_endian) - .ok_or(ExitError::OutOfFund)?; - let amount_sub = - ::BalanceConverter::into_substrate_balance(amount) - .ok_or(ExitError::OutOfFund)?; - - let call = RuntimeCall::SubtensorModule(pallet_subtensor::Call::::remove_stake { + #[precompile::public("removeStake(bytes32,uint256,uint256)")] + fn remove_stake( + handle: &mut impl PrecompileHandle, + address: H256, + amount: U256, + netuid: U256, + ) -> EvmResult<()> { + let account_id = handle.caller_account_id(); + let (hotkey, _) = parse_pubkey(address.as_bytes())?; + let netuid = try_u16_from_u256(netuid)?; + let amount_unstaked = amount.unique_saturated_into(); + let call = pallet_subtensor::Call::::remove_stake { hotkey, netuid, - amount_unstaked: amount_sub.unique_saturated_into(), - }); - try_dispatch_runtime_call(handle, call, RawOrigin::Signed(account_id)) + amount_unstaked, + }; + + handle.try_dispatch_runtime_call(call, RawOrigin::Signed(account_id)) } - fn add_proxy(handle: &mut impl PrecompileHandle, data: &[u8]) -> PrecompileResult { - let account_id = - as AddressMapping>::into_account_id( - handle.context().caller, - ); - let (delegate, _) = get_pubkey(data)?; + #[precompile::public("addProxy(bytes32)")] + fn add_proxy(handle: &mut impl PrecompileHandle, delegate: H256) -> EvmResult<()> { + let account_id = handle.caller_account_id(); + let (delegate, _) = parse_pubkey(delegate.as_bytes())?; let delegate = ::Lookup::unlookup(delegate); - let call = RuntimeCall::Proxy(pallet_proxy::Call::::add_proxy { + let call = pallet_proxy::Call::::add_proxy { delegate, proxy_type: ProxyType::Staking, delay: 0, - }); + }; - try_dispatch_runtime_call(handle, call, RawOrigin::Signed(account_id)) + handle.try_dispatch_runtime_call(call, RawOrigin::Signed(account_id)) } - fn remove_proxy(handle: &mut impl PrecompileHandle, data: &[u8]) -> PrecompileResult { - let account_id = - as AddressMapping>::into_account_id( - handle.context().caller, - ); - let (delegate, _) = get_pubkey(data)?; + #[precompile::public("removeProxy(bytes32)")] + fn remove_proxy(handle: &mut impl PrecompileHandle, delegate: H256) -> EvmResult<()> { + let account_id = handle.caller_account_id(); + let (delegate, _) = parse_pubkey(delegate.as_bytes())?; let delegate = ::Lookup::unlookup(delegate); - let call = RuntimeCall::Proxy(pallet_proxy::Call::::remove_proxy { + let call = pallet_proxy::Call::::remove_proxy { delegate, proxy_type: ProxyType::Staking, delay: 0, - }); + }; - try_dispatch_runtime_call(handle, call, RawOrigin::Signed(account_id)) + handle.try_dispatch_runtime_call(call, RawOrigin::Signed(account_id)) } - fn get_stake(data: &[u8]) -> PrecompileResult { - let (hotkey, left_data) = get_pubkey(data)?; - let (coldkey, _) = get_pubkey(&left_data)?; - let netuid = parse_netuid(data, 0x5E)?; - + #[precompile::public("getStake(bytes32,bytes32,uint256)")] + #[precompile::view] + fn get_stake( + _: &mut impl PrecompileHandle, + hotkey: H256, + coldkey: H256, + netuid: U256, + ) -> EvmResult { + let (hotkey, _) = parse_pubkey(hotkey.as_bytes())?; + let (coldkey, _) = parse_pubkey(coldkey.as_bytes())?; + let netuid = try_u16_from_u256(netuid)?; let stake = pallet_subtensor::Pallet::::get_stake_for_hotkey_and_coldkey_on_subnet( &hotkey, &coldkey, netuid, ); - // Convert to EVM decimals - let stake_u256 = U256::from(stake); - let stake_eth = - ::BalanceConverter::into_evm_balance(stake_u256) - .ok_or(ExitError::InvalidRange)?; - - // Format output - let mut result = [0_u8; 32]; - U256::to_big_endian(&stake_eth, &mut result); - - Ok(PrecompileOutput { - exit_status: ExitSucceed::Returned, - output: result.into(), - }) + Ok(stake.into()) } fn transfer_back_to_caller( account_id: &AccountId32, amount: U256, ) -> Result<(), PrecompileFailure> { - let smart_contract_account_id: AccountId32 = CONTRACT_ADDRESS_SS58.into(); - + let smart_contract_account_id: AccountId32 = Self::ADDRESS_SS58.into(); let amount_sub = ::BalanceConverter::into_substrate_balance(amount) .ok_or(ExitError::OutOfFund)?; diff --git a/runtime/src/precompiles/subnet.rs b/runtime/src/precompiles/subnet.rs index ee85a3f864..afda39dd30 100644 --- a/runtime/src/precompiles/subnet.rs +++ b/runtime/src/precompiles/subnet.rs @@ -1,1319 +1,522 @@ -use crate::precompiles::{ - get_method_id, get_pubkey, get_slice, parse_netuid, try_dispatch_runtime_call, -}; -use crate::{Runtime, RuntimeCall}; +use frame_support::traits::ConstU32; use frame_system::RawOrigin; -use pallet_evm::{ - AddressMapping, ExitError, ExitSucceed, HashedAddressMapping, PrecompileFailure, - PrecompileHandle, PrecompileOutput, PrecompileResult, -}; - -use sp_core::U256; -use sp_runtime::{traits::BlakeTwo256, AccountId32, Vec}; -use sp_std::vec; - -pub const SUBNET_PRECOMPILE_INDEX: u64 = 2051; -// bytes with max lenght 1K -pub const MAX_SINGLE_PARAMETER_SIZE: usize = 1024; -// seven bytes with max lenght 1K -pub const MAX_PARAMETER_SIZE: usize = 7 * MAX_SINGLE_PARAMETER_SIZE; -// ss58 public key i.e., the contract sends funds it received to the destination address from the -#[allow(dead_code)] -const CONTRACT_ADDRESS_SS58: [u8; 32] = [ - 0x3a, 0x86, 0x18, 0xfb, 0xbb, 0x1b, 0xbc, 0x47, 0x86, 0x64, 0xff, 0x53, 0x46, 0x18, 0x0c, 0x35, - 0xd0, 0x9f, 0xac, 0x26, 0xf2, 0x02, 0x70, 0x85, 0xb3, 0x1c, 0x56, 0xc1, 0x06, 0x3c, 0x1c, 0xd3, -]; +use pallet_evm::PrecompileHandle; +use precompile_utils::{prelude::BoundedString, EvmResult}; +use sp_core::H256; + +use crate::precompiles::{parse_pubkey, PrecompileExt, PrecompileHandleExt}; +use crate::Runtime; + pub struct SubnetPrecompile; -impl SubnetPrecompile { - pub fn execute(handle: &mut impl PrecompileHandle) -> PrecompileResult { - let txdata = handle.input(); - if txdata.len() > MAX_PARAMETER_SIZE { - log::error!("the length of subnet call is {} ", txdata.len()); - return Err(PrecompileFailure::Error { - exit_status: ExitError::InvalidRange, - }); - } - let method_id = get_slice(txdata, 0, 4)?; - let method_input = txdata - .get(4..) - .map_or_else(vec::Vec::new, |slice| slice.to_vec()); // Avoiding borrowing conflicts - - match method_id { - id if id - == get_method_id( - "registerNetwork(bytes32,bytes,bytes,bytes,bytes,bytes,bytes,bytes)", - ) => - { - Self::register_network(handle, &method_input) - } - id if id == get_method_id("registerNetwork(bytes32)") => { - Self::register_network(handle, &method_input) - } - - id if id == get_method_id("getServingRateLimit(uint16)") => { - Self::get_serving_rate_limit(&method_input) - } - id if id == get_method_id("setServingRateLimit(uint16,uint64)") => { - Self::set_serving_rate_limit(handle, &method_input) - } - - id if id == get_method_id("getMinDifficulty(uint16)") => { - Self::get_min_difficulty(&method_input) - } - id if id == get_method_id("setMinDifficulty(uint16,uint64)") => { - Self::set_min_difficulty(handle, &method_input) - } - - id if id == get_method_id("getMaxDifficulty(uint16)") => { - Self::get_max_difficulty(&method_input) - } - id if id == get_method_id("setMaxDifficulty(uint16,uint64)") => { - Self::set_max_difficulty(handle, &method_input) - } - - id if id == get_method_id("getWeightsVersionKey(uint16)") => { - Self::get_weights_version_key(&method_input) - } - id if id == get_method_id("setWeightsVersionKey(uint16,uint64)") => { - Self::set_weights_version_key(handle, &method_input) - } - - id if id == get_method_id("getWeightsSetRateLimit(uint16)") => { - Self::get_weights_set_rate_limit(&method_input) - } - id if id == get_method_id("setWeightsSetRateLimit(uint16,uint64)") => { - Self::set_weights_set_rate_limit(handle, &method_input) - } - - id if id == get_method_id("getAdjustmentAlpha(uint16)") => { - Self::get_adjustment_alpha(&method_input) - } - id if id == get_method_id("setAdjustmentAlpha(uint16,uint64)") => { - Self::set_adjustment_alpha(handle, &method_input) - } - - id if id == get_method_id("getMaxWeightLimit(uint16)") => { - Self::get_max_weight_limit(&method_input) - } - id if id == get_method_id("setMaxWeightLimit(uint16,uint64)") => { - Self::set_max_weight_limit(handle, &method_input) - } - - id if id == get_method_id("getImmunityPeriod(uint16)") => { - Self::get_immunity_period(&method_input) - } - id if id == get_method_id("setImmunityPeriod(uint16,uint64)") => { - Self::set_immunity_period(handle, &method_input) - } - - id if id == get_method_id("getMinAllowedWeights(uint16)") => { - Self::get_min_allowed_weights(&method_input) - } - id if id == get_method_id("setMinAllowedWeights(uint16,uint16)") => { - Self::set_min_allowed_weights(handle, &method_input) - } - - id if id == get_method_id("getKappa(uint16)") => Self::get_kappa(&method_input), - id if id == get_method_id("setKappa(uint16,uint16)") => { - Self::set_kappa(handle, &method_input) - } - - id if id == get_method_id("getRho(uint16)") => Self::get_rho(&method_input), - id if id == get_method_id("setRho(uint16,uint16)") => { - Self::set_rho(handle, &method_input) - } - - id if id == get_method_id("getActivityCutoff(uint16)") => { - Self::get_activity_cutoff(&method_input) - } - id if id == get_method_id("setActivityCutoff(uint16,uint16)") => { - Self::set_activity_cutoff(handle, &method_input) - } - - id if id == get_method_id("getNetworkRegistrationAllowed(uint16)") => { - Self::get_network_registration_allowed(&method_input) - } - id if id == get_method_id("setNetworkRegistrationAllowed(uint16,bool)") => { - Self::set_network_registration_allowed(handle, &method_input) - } - - id if id == get_method_id("getNetworkPowRegistrationAllowed(uint16)") => { - Self::get_network_pow_registration_allowed(&method_input) - } - id if id == get_method_id("setNetworkPowRegistrationAllowed(uint16,bool)") => { - Self::set_network_pow_registration_allowed(handle, &method_input) - } - - id if id == get_method_id("getMinBurn(uint16)") => Self::get_min_burn(&method_input), - id if id == get_method_id("setMinBurn(uint16,uint64)") => { - Self::set_min_burn(handle, &method_input) - } - - id if id == get_method_id("getMaxBurn(uint16)") => Self::get_max_burn(&method_input), - id if id == get_method_id("setMaxBurn(uint16,uint64)") => { - Self::set_max_burn(handle, &method_input) - } - - id if id == get_method_id("getDifficulty(uint16)") => { - Self::get_difficulty(&method_input) - } - id if id == get_method_id("setDifficulty(uint16,uint64)") => { - Self::set_difficulty(handle, &method_input) - } - - id if id == get_method_id("getBondsMovingAverage(uint16)") => { - Self::get_bonds_moving_average(&method_input) - } - id if id == get_method_id("setBondsMovingAverage(uint16,uint64)") => { - Self::set_bonds_moving_average(handle, &method_input) - } - - id if id == get_method_id("getCommitRevealWeightsEnabled(uint16)") => { - Self::get_commit_reveal_weights_enabled(&method_input) - } - id if id == get_method_id("setCommitRevealWeightsEnabled(uint16,bool)") => { - Self::set_commit_reveal_weights_enabled(handle, &method_input) - } - - id if id == get_method_id("getLiquidAlphaEnabled(uint16)") => { - Self::get_liquid_alpha_enabled(&method_input) - } - id if id == get_method_id("setLiquidAlphaEnabled(uint16,bool)") => { - Self::set_liquid_alpha_enabled(handle, &method_input) - } - - id if id == get_method_id("getAlphaValues(uint16)") => { - Self::get_alpha_values(&method_input) - } - id if id == get_method_id("setAlphaValues(uint16,uint16,uint16)") => { - Self::set_alpha_values(handle, &method_input) - } - - id if id == get_method_id("getCommitRevealWeightsInterval(uint16)") => { - Self::get_commit_reveal_weights_interval(&method_input) - } - id if id == get_method_id("setCommitRevealWeightsInterval(uint16,uint64)") => { - Self::set_commit_reveal_weights_interval(handle, &method_input) - } - _ => Err(PrecompileFailure::Error { - exit_status: ExitError::InvalidRange, - }), - } - } +impl PrecompileExt for SubnetPrecompile { + const INDEX: u64 = 2051; + const ADDRESS_SS58: [u8; 32] = [ + 0x3a, 0x86, 0x18, 0xfb, 0xbb, 0x1b, 0xbc, 0x47, 0x86, 0x64, 0xff, 0x53, 0x46, 0x18, 0x0c, + 0x35, 0xd0, 0x9f, 0xac, 0x26, 0xf2, 0x02, 0x70, 0x85, 0xb3, 0x1c, 0x56, 0xc1, 0x06, 0x3c, + 0x1c, 0xd3, + ]; +} - fn register_network(handle: &mut impl PrecompileHandle, data: &[u8]) -> PrecompileResult { - let call = match data.len() { - 32 => { - let (hotkey, _) = get_pubkey(data)?; - RuntimeCall::SubtensorModule( - pallet_subtensor::Call::::register_network_with_identity { - hotkey, - identity: None, - }, - ) - } - 33.. => { - let ( - hotkey, - subnet_name, - github_repo, - subnet_contact, - subnet_url, - discord, - description, - additional, - ) = Self::parse_register_network_parameters(data)?; - - let identity: pallet_subtensor::SubnetIdentityOfV2 = - pallet_subtensor::SubnetIdentityOfV2 { - subnet_name, - github_repo, - subnet_contact, - subnet_url, - discord, - description, - additional, - }; - - // Create the register_network callcle - RuntimeCall::SubtensorModule( - pallet_subtensor::Call::::register_network_with_identity { - hotkey, - identity: Some(identity), - }, - ) - } - _ => { - return Err(PrecompileFailure::Error { - exit_status: ExitError::InvalidRange, - }); - } +#[precompile_utils::precompile] +impl SubnetPrecompile { + #[precompile::public("registerNetwork(bytes32)")] + #[precompile::payable] + fn register_network(handle: &mut impl PrecompileHandle, hotkey: H256) -> EvmResult<()> { + let (hotkey, _) = parse_pubkey(hotkey.as_bytes())?; + let call = pallet_subtensor::Call::::register_network_with_identity { + hotkey, + identity: None, }; - let account_id = - as AddressMapping>::into_account_id( - handle.context().caller, - ); - - try_dispatch_runtime_call(handle, call, RawOrigin::Signed(account_id)) + handle.try_dispatch_runtime_call(call, RawOrigin::Signed(handle.caller_account_id())) } - fn get_serving_rate_limit(data: &[u8]) -> PrecompileResult { - let netuid = parse_netuid(data, 30)?; - - let value = pallet_subtensor::ServingRateLimit::::get(netuid); + #[precompile::public( + "registerNetwork(bytes32,string,string,string,string,string,string,string)" + )] + #[precompile::payable] + #[allow(clippy::too_many_arguments)] + fn register_network_with_identity( + handle: &mut impl PrecompileHandle, + hotkey: H256, + subnet_name: BoundedString>, + github_repo: BoundedString>, + subnet_contact: BoundedString>, + subnet_url: BoundedString>, + discord: BoundedString>, + description: BoundedString>, + additional: BoundedString>, + ) -> EvmResult<()> { + let (hotkey, _) = parse_pubkey(hotkey.as_bytes())?; + let identity = pallet_subtensor::SubnetIdentityOfV2 { + subnet_name: subnet_name.into(), + github_repo: github_repo.into(), + subnet_contact: subnet_contact.into(), + subnet_url: subnet_url.into(), + discord: discord.into(), + description: description.into(), + additional: additional.into(), + }; - let value_u256 = U256::from(value); - let mut result = [0_u8; 32]; - U256::to_big_endian(&value_u256, &mut result); + let call = pallet_subtensor::Call::::register_network_with_identity { + hotkey, + identity: Some(identity), + }; - Ok(PrecompileOutput { - exit_status: ExitSucceed::Returned, - output: result.into(), - }) + handle.try_dispatch_runtime_call(call, RawOrigin::Signed(handle.caller_account_id())) } - fn set_serving_rate_limit(handle: &mut impl PrecompileHandle, data: &[u8]) -> PrecompileResult { - let (netuid, serving_rate_limit) = Self::parse_netuid_u64_parameter(data)?; - let call = RuntimeCall::AdminUtils( - pallet_admin_utils::Call::::sudo_set_serving_rate_limit { - netuid, - serving_rate_limit, - }, - ); - - let account_id = - as AddressMapping>::into_account_id( - handle.context().caller, - ); - - try_dispatch_runtime_call(handle, call, RawOrigin::Signed(account_id)) + #[precompile::public("getServingRateLimit(uint16)")] + #[precompile::view] + fn get_serving_rate_limit(_: &mut impl PrecompileHandle, netuid: u16) -> EvmResult { + Ok(pallet_subtensor::ServingRateLimit::::get(netuid)) } - fn get_min_difficulty(data: &[u8]) -> PrecompileResult { - let netuid = parse_netuid(data, 30)?; - - let value = pallet_subtensor::MinDifficulty::::get(netuid); - - let value_u256 = U256::from(value); - let mut result = [0_u8; 32]; - U256::to_big_endian(&value_u256, &mut result); + #[precompile::public("setServingRateLimit(uint16,uint64)")] + #[precompile::payable] + fn set_serving_rate_limit( + handle: &mut impl PrecompileHandle, + netuid: u16, + serving_rate_limit: u64, + ) -> EvmResult<()> { + let call = pallet_admin_utils::Call::::sudo_set_serving_rate_limit { + netuid, + serving_rate_limit, + }; - Ok(PrecompileOutput { - exit_status: ExitSucceed::Returned, - output: result.into(), - }) + handle.try_dispatch_runtime_call(call, RawOrigin::Signed(handle.caller_account_id())) } - fn set_min_difficulty(handle: &mut impl PrecompileHandle, data: &[u8]) -> PrecompileResult { - let (netuid, min_difficulty) = Self::parse_netuid_u64_parameter(data)?; - let call = RuntimeCall::AdminUtils( - pallet_admin_utils::Call::::sudo_set_min_difficulty { - netuid, - min_difficulty, - }, - ); - - let account_id = - as AddressMapping>::into_account_id( - handle.context().caller, - ); - - try_dispatch_runtime_call(handle, call, RawOrigin::Signed(account_id)) + #[precompile::public("getMinDifficulty(uint16)")] + #[precompile::view] + fn get_min_difficulty(_: &mut impl PrecompileHandle, netuid: u16) -> EvmResult { + Ok(pallet_subtensor::MinDifficulty::::get(netuid)) } - fn get_max_difficulty(data: &[u8]) -> PrecompileResult { - let netuid = parse_netuid(data, 30)?; - - let value = pallet_subtensor::MaxDifficulty::::get(netuid); - - let value_u256 = U256::from(value); - let mut result = [0_u8; 32]; - U256::to_big_endian(&value_u256, &mut result); + #[precompile::public("setMinDifficulty(uint16,uint64)")] + #[precompile::payable] + fn set_min_difficulty( + handle: &mut impl PrecompileHandle, + netuid: u16, + min_difficulty: u64, + ) -> EvmResult<()> { + let call = pallet_admin_utils::Call::::sudo_set_min_difficulty { + netuid, + min_difficulty, + }; - Ok(PrecompileOutput { - exit_status: ExitSucceed::Returned, - output: result.into(), - }) + handle.try_dispatch_runtime_call(call, RawOrigin::Signed(handle.caller_account_id())) } - fn set_max_difficulty(handle: &mut impl PrecompileHandle, data: &[u8]) -> PrecompileResult { - let (netuid, max_difficulty) = Self::parse_netuid_u64_parameter(data)?; - let call = RuntimeCall::AdminUtils( - pallet_admin_utils::Call::::sudo_set_max_difficulty { - netuid, - max_difficulty, - }, - ); - - let account_id = - as AddressMapping>::into_account_id( - handle.context().caller, - ); - - try_dispatch_runtime_call(handle, call, RawOrigin::Signed(account_id)) + #[precompile::public("getMaxDifficulty(uint16)")] + #[precompile::view] + fn get_max_difficulty(_: &mut impl PrecompileHandle, netuid: u16) -> EvmResult { + Ok(pallet_subtensor::MaxDifficulty::::get(netuid)) } - fn get_weights_version_key(data: &[u8]) -> PrecompileResult { - let netuid = parse_netuid(data, 30)?; - - let value = pallet_subtensor::WeightsVersionKey::::get(netuid); + #[precompile::public("setMaxDifficulty(uint16,uint64)")] + #[precompile::payable] + fn set_max_difficulty( + handle: &mut impl PrecompileHandle, + netuid: u16, + max_difficulty: u64, + ) -> EvmResult<()> { + let call = pallet_admin_utils::Call::::sudo_set_max_difficulty { + netuid, + max_difficulty, + }; - let value_u256 = U256::from(value); - let mut result = [0_u8; 32]; - U256::to_big_endian(&value_u256, &mut result); + handle.try_dispatch_runtime_call(call, RawOrigin::Signed(handle.caller_account_id())) + } - Ok(PrecompileOutput { - exit_status: ExitSucceed::Returned, - output: result.into(), - }) + #[precompile::public("getWeightsVersionKey(uint16)")] + #[precompile::view] + fn get_weights_version_key(_: &mut impl PrecompileHandle, netuid: u16) -> EvmResult { + Ok(pallet_subtensor::WeightsVersionKey::::get(netuid)) } + #[precompile::public("setWeightsVersionKey(uint16,uint64)")] + #[precompile::payable] fn set_weights_version_key( handle: &mut impl PrecompileHandle, - data: &[u8], - ) -> PrecompileResult { - let (netuid, weights_version_key) = Self::parse_netuid_u64_parameter(data)?; - let call = RuntimeCall::AdminUtils( - pallet_admin_utils::Call::::sudo_set_weights_version_key { - netuid, - weights_version_key, - }, - ); - - let account_id = - as AddressMapping>::into_account_id( - handle.context().caller, - ); - - try_dispatch_runtime_call(handle, call, RawOrigin::Signed(account_id)) - } - - fn get_weights_set_rate_limit(data: &[u8]) -> PrecompileResult { - let netuid = parse_netuid(data, 30)?; - - let value = pallet_subtensor::WeightsSetRateLimit::::get(netuid); + netuid: u16, + weights_version_key: u64, + ) -> EvmResult<()> { + let call = pallet_admin_utils::Call::::sudo_set_weights_version_key { + netuid, + weights_version_key, + }; - let value_u256 = U256::from(value); - let mut result = [0_u8; 32]; - U256::to_big_endian(&value_u256, &mut result); + handle.try_dispatch_runtime_call(call, RawOrigin::Signed(handle.caller_account_id())) + } - Ok(PrecompileOutput { - exit_status: ExitSucceed::Returned, - output: result.into(), - }) + #[precompile::public("getWeightsSetRateLimit(uint16)")] + #[precompile::view] + fn get_weights_set_rate_limit(_: &mut impl PrecompileHandle, netuid: u16) -> EvmResult { + Ok(pallet_subtensor::WeightsSetRateLimit::::get( + netuid, + )) } + #[precompile::public("setWeightsSetRateLimit(uint16,uint64)")] + #[precompile::payable] fn set_weights_set_rate_limit( handle: &mut impl PrecompileHandle, - data: &[u8], - ) -> PrecompileResult { - let (netuid, weights_set_rate_limit) = Self::parse_netuid_u64_parameter(data)?; - - let call = RuntimeCall::AdminUtils( - pallet_admin_utils::Call::::sudo_set_weights_set_rate_limit { - netuid, - weights_set_rate_limit, - }, - ); - - let account_id = - as AddressMapping>::into_account_id( - handle.context().caller, - ); - - try_dispatch_runtime_call(handle, call, RawOrigin::Signed(account_id)) - } - - fn get_adjustment_alpha(data: &[u8]) -> PrecompileResult { - let netuid = parse_netuid(data, 30)?; - - let value = pallet_subtensor::AdjustmentAlpha::::get(netuid); - - let value_u256 = U256::from(value); - let mut result = [0_u8; 32]; - U256::to_big_endian(&value_u256, &mut result); + netuid: u16, + weights_set_rate_limit: u64, + ) -> EvmResult<()> { + let call = pallet_admin_utils::Call::::sudo_set_weights_set_rate_limit { + netuid, + weights_set_rate_limit, + }; - Ok(PrecompileOutput { - exit_status: ExitSucceed::Returned, - output: result.into(), - }) + handle.try_dispatch_runtime_call(call, RawOrigin::Signed(handle.caller_account_id())) } - fn set_adjustment_alpha(handle: &mut impl PrecompileHandle, data: &[u8]) -> PrecompileResult { - let (netuid, adjustment_alpha) = Self::parse_netuid_u64_parameter(data)?; - let call = RuntimeCall::AdminUtils( - pallet_admin_utils::Call::::sudo_set_adjustment_alpha { - netuid, - adjustment_alpha, - }, - ); - - let account_id = - as AddressMapping>::into_account_id( - handle.context().caller, - ); - - try_dispatch_runtime_call(handle, call, RawOrigin::Signed(account_id)) + #[precompile::public("getAdjustmentAlpha(uint16)")] + #[precompile::view] + fn get_adjustment_alpha(_: &mut impl PrecompileHandle, netuid: u16) -> EvmResult { + Ok(pallet_subtensor::AdjustmentAlpha::::get(netuid)) } - fn get_max_weight_limit(data: &[u8]) -> PrecompileResult { - let netuid = parse_netuid(data, 30)?; - - let value = pallet_subtensor::MaxWeightsLimit::::get(netuid); - - let value_u256 = U256::from(value); - let mut result = [0_u8; 32]; - U256::to_big_endian(&value_u256, &mut result); + #[precompile::public("setAdjustmentAlpha(uint16,uint64)")] + #[precompile::payable] + fn set_adjustment_alpha( + handle: &mut impl PrecompileHandle, + netuid: u16, + adjustment_alpha: u64, + ) -> EvmResult<()> { + let call = pallet_admin_utils::Call::::sudo_set_adjustment_alpha { + netuid, + adjustment_alpha, + }; - Ok(PrecompileOutput { - exit_status: ExitSucceed::Returned, - output: result.into(), - }) + handle.try_dispatch_runtime_call(call, RawOrigin::Signed(handle.caller_account_id())) } - fn set_max_weight_limit(handle: &mut impl PrecompileHandle, data: &[u8]) -> PrecompileResult { - let (netuid, max_weight_limit) = Self::parse_netuid_u16_parameter(data)?; - let call = RuntimeCall::AdminUtils( - pallet_admin_utils::Call::::sudo_set_max_weight_limit { - netuid, - max_weight_limit, - }, - ); - - let account_id = - as AddressMapping>::into_account_id( - handle.context().caller, - ); - - try_dispatch_runtime_call(handle, call, RawOrigin::Signed(account_id)) + #[precompile::public("getMaxWeightLimit(uint16)")] + #[precompile::view] + fn get_max_weight_limit(_: &mut impl PrecompileHandle, netuid: u16) -> EvmResult { + Ok(pallet_subtensor::MaxWeightsLimit::::get(netuid)) } - fn get_immunity_period(data: &[u8]) -> PrecompileResult { - let netuid = parse_netuid(data, 30)?; - - let value = pallet_subtensor::ImmunityPeriod::::get(netuid); - - let value_u256 = U256::from(value); - let mut result = [0_u8; 32]; - U256::to_big_endian(&value_u256, &mut result); + #[precompile::public("setMaxWeightLimit(uint16,uint16)")] + #[precompile::payable] + fn set_max_weight_limit( + handle: &mut impl PrecompileHandle, + netuid: u16, + max_weight_limit: u16, + ) -> EvmResult<()> { + let call = pallet_admin_utils::Call::::sudo_set_max_weight_limit { + netuid, + max_weight_limit, + }; - Ok(PrecompileOutput { - exit_status: ExitSucceed::Returned, - output: result.into(), - }) + handle.try_dispatch_runtime_call(call, RawOrigin::Signed(handle.caller_account_id())) } - fn set_immunity_period(handle: &mut impl PrecompileHandle, data: &[u8]) -> PrecompileResult { - let (netuid, immunity_period) = Self::parse_netuid_u16_parameter(data)?; - let call = RuntimeCall::AdminUtils( - pallet_admin_utils::Call::::sudo_set_immunity_period { - netuid, - immunity_period, - }, - ); - - let account_id = - as AddressMapping>::into_account_id( - handle.context().caller, - ); - - try_dispatch_runtime_call(handle, call, RawOrigin::Signed(account_id)) + #[precompile::public("getImmunityPeriod(uint16)")] + #[precompile::view] + fn get_immunity_period(_: &mut impl PrecompileHandle, netuid: u16) -> EvmResult { + Ok(pallet_subtensor::ImmunityPeriod::::get(netuid)) } - fn get_min_allowed_weights(data: &[u8]) -> PrecompileResult { - let netuid = parse_netuid(data, 30)?; - - let value = pallet_subtensor::MinAllowedWeights::::get(netuid); + #[precompile::public("setImmunityPeriod(uint16,uint16)")] + #[precompile::payable] + fn set_immunity_period( + handle: &mut impl PrecompileHandle, + netuid: u16, + immunity_period: u16, + ) -> EvmResult<()> { + let call = pallet_admin_utils::Call::::sudo_set_immunity_period { + netuid, + immunity_period, + }; - let value_u256 = U256::from(value); - let mut result = [0_u8; 32]; - U256::to_big_endian(&value_u256, &mut result); + handle.try_dispatch_runtime_call(call, RawOrigin::Signed(handle.caller_account_id())) + } - Ok(PrecompileOutput { - exit_status: ExitSucceed::Returned, - output: result.into(), - }) + #[precompile::public("getMinAllowedWeights(uint16)")] + #[precompile::view] + fn get_min_allowed_weights(_: &mut impl PrecompileHandle, netuid: u16) -> EvmResult { + Ok(pallet_subtensor::MinAllowedWeights::::get(netuid)) } + #[precompile::public("setMinAllowedWeights(uint16,uint16)")] + #[precompile::payable] fn set_min_allowed_weights( handle: &mut impl PrecompileHandle, - data: &[u8], - ) -> PrecompileResult { - let (netuid, min_allowed_weights) = Self::parse_netuid_u16_parameter(data)?; - let call = RuntimeCall::AdminUtils( - pallet_admin_utils::Call::::sudo_set_min_allowed_weights { - netuid, - min_allowed_weights, - }, - ); - - let account_id = - as AddressMapping>::into_account_id( - handle.context().caller, - ); - - try_dispatch_runtime_call(handle, call, RawOrigin::Signed(account_id)) - } - - fn get_kappa(data: &[u8]) -> PrecompileResult { - let netuid = parse_netuid(data, 30)?; - - let value = pallet_subtensor::Kappa::::get(netuid); - - let value_u256 = U256::from(value); - let mut result = [0_u8; 32]; - U256::to_big_endian(&value_u256, &mut result); - - Ok(PrecompileOutput { - exit_status: ExitSucceed::Returned, - output: result.into(), - }) - } - - fn set_kappa(handle: &mut impl PrecompileHandle, data: &[u8]) -> PrecompileResult { - let (netuid, kappa) = Self::parse_netuid_u16_parameter(data)?; - let call = RuntimeCall::AdminUtils(pallet_admin_utils::Call::::sudo_set_kappa { + netuid: u16, + min_allowed_weights: u16, + ) -> EvmResult<()> { + let call = pallet_admin_utils::Call::::sudo_set_min_allowed_weights { netuid, - kappa, - }); - - let account_id = - as AddressMapping>::into_account_id( - handle.context().caller, - ); + min_allowed_weights, + }; - try_dispatch_runtime_call(handle, call, RawOrigin::Signed(account_id)) + handle.try_dispatch_runtime_call(call, RawOrigin::Signed(handle.caller_account_id())) } - fn get_rho(data: &[u8]) -> PrecompileResult { - let netuid = parse_netuid(data, 30)?; - - let value = pallet_subtensor::Rho::::get(netuid); - - let value_u256 = U256::from(value); - let mut result = [0_u8; 32]; - U256::to_big_endian(&value_u256, &mut result); - - Ok(PrecompileOutput { - exit_status: ExitSucceed::Returned, - output: result.into(), - }) + #[precompile::public("getKappa(uint16)")] + #[precompile::view] + fn get_kappa(_: &mut impl PrecompileHandle, netuid: u16) -> EvmResult { + Ok(pallet_subtensor::Kappa::::get(netuid)) } - fn set_rho(handle: &mut impl PrecompileHandle, data: &[u8]) -> PrecompileResult { - let (netuid, rho) = Self::parse_netuid_u16_parameter(data)?; - let call = RuntimeCall::AdminUtils(pallet_admin_utils::Call::::sudo_set_rho { - netuid, - rho, - }); - - let account_id = - as AddressMapping>::into_account_id( - handle.context().caller, - ); + #[precompile::public("setKappa(uint16,uint16)")] + #[precompile::payable] + fn set_kappa(handle: &mut impl PrecompileHandle, netuid: u16, kappa: u16) -> EvmResult<()> { + let call = pallet_admin_utils::Call::::sudo_set_kappa { netuid, kappa }; - try_dispatch_runtime_call(handle, call, RawOrigin::Signed(account_id)) + handle.try_dispatch_runtime_call(call, RawOrigin::Signed(handle.caller_account_id())) } - fn get_activity_cutoff(data: &[u8]) -> PrecompileResult { - let netuid = parse_netuid(data, 30)?; - - let value = pallet_subtensor::ActivityCutoff::::get(netuid); + #[precompile::public("getRho(uint16)")] + #[precompile::view] + fn get_rho(_: &mut impl PrecompileHandle, netuid: u16) -> EvmResult { + Ok(pallet_subtensor::Rho::::get(netuid)) + } - let value_u256 = U256::from(value); - let mut result = [0_u8; 32]; - U256::to_big_endian(&value_u256, &mut result); + #[precompile::public("setRho(uint16,uint16)")] + #[precompile::payable] + fn set_rho(handle: &mut impl PrecompileHandle, netuid: u16, rho: u16) -> EvmResult<()> { + let call = pallet_admin_utils::Call::::sudo_set_rho { netuid, rho }; - Ok(PrecompileOutput { - exit_status: ExitSucceed::Returned, - output: result.into(), - }) + handle.try_dispatch_runtime_call(call, RawOrigin::Signed(handle.caller_account_id())) } - fn set_activity_cutoff(handle: &mut impl PrecompileHandle, data: &[u8]) -> PrecompileResult { - let (netuid, activity_cutoff) = Self::parse_netuid_u16_parameter(data)?; - let call = RuntimeCall::AdminUtils( - pallet_admin_utils::Call::::sudo_set_activity_cutoff { - netuid, - activity_cutoff, - }, - ); - - let account_id = - as AddressMapping>::into_account_id( - handle.context().caller, - ); - - try_dispatch_runtime_call(handle, call, RawOrigin::Signed(account_id)) + #[precompile::public("getActivityCutoff(uint16)")] + #[precompile::view] + fn get_activity_cutoff(_: &mut impl PrecompileHandle, netuid: u16) -> EvmResult { + Ok(pallet_subtensor::ActivityCutoff::::get(netuid)) } - fn get_network_registration_allowed(data: &[u8]) -> PrecompileResult { - let netuid = parse_netuid(data, 30)?; - - let value = pallet_subtensor::NetworkRegistrationAllowed::::get(netuid); + #[precompile::public("setActivityCutoff(uint16,uint16)")] + #[precompile::payable] + fn set_activity_cutoff( + handle: &mut impl PrecompileHandle, + netuid: u16, + activity_cutoff: u16, + ) -> EvmResult<()> { + let call = pallet_admin_utils::Call::::sudo_set_activity_cutoff { + netuid, + activity_cutoff, + }; - let value_u256 = if value { U256::from(1) } else { U256::from(0) }; - let mut result = [0_u8; 32]; - U256::to_big_endian(&value_u256, &mut result); + handle.try_dispatch_runtime_call(call, RawOrigin::Signed(handle.caller_account_id())) + } - Ok(PrecompileOutput { - exit_status: ExitSucceed::Returned, - output: result.into(), - }) + #[precompile::public("getNetworkRegistrationAllowed(uint16)")] + #[precompile::view] + fn get_network_registration_allowed( + _: &mut impl PrecompileHandle, + netuid: u16, + ) -> EvmResult { + Ok(pallet_subtensor::NetworkRegistrationAllowed::::get(netuid)) } + #[precompile::public("setNetworkRegistrationAllowed(uint16,bool)")] + #[precompile::payable] fn set_network_registration_allowed( handle: &mut impl PrecompileHandle, - data: &[u8], - ) -> PrecompileResult { - let (netuid, registration_allowed) = Self::parse_netuid_bool_parameter(data)?; - let call = RuntimeCall::AdminUtils( - pallet_admin_utils::Call::::sudo_set_network_registration_allowed { - netuid, - registration_allowed, - }, - ); - - let account_id = - as AddressMapping>::into_account_id( - handle.context().caller, - ); - - try_dispatch_runtime_call(handle, call, RawOrigin::Signed(account_id)) - } - - fn get_network_pow_registration_allowed(data: &[u8]) -> PrecompileResult { - let netuid = parse_netuid(data, 30)?; - - let value = pallet_subtensor::NetworkPowRegistrationAllowed::::get(netuid); + netuid: u16, + registration_allowed: bool, + ) -> EvmResult<()> { + let call = pallet_admin_utils::Call::::sudo_set_network_registration_allowed { + netuid, + registration_allowed, + }; - let value_u256 = if value { U256::from(1) } else { U256::from(0) }; - let mut result = [0_u8; 32]; - U256::to_big_endian(&value_u256, &mut result); + handle.try_dispatch_runtime_call(call, RawOrigin::Signed(handle.caller_account_id())) + } - Ok(PrecompileOutput { - exit_status: ExitSucceed::Returned, - output: result.into(), - }) + #[precompile::public("getNetworkPowRegistrationAllowed(uint16)")] + #[precompile::view] + fn get_network_pow_registration_allowed( + _: &mut impl PrecompileHandle, + netuid: u16, + ) -> EvmResult { + Ok(pallet_subtensor::NetworkPowRegistrationAllowed::::get(netuid)) } + #[precompile::public("setNetworkPowRegistrationAllowed(uint16,bool)")] + #[precompile::payable] fn set_network_pow_registration_allowed( handle: &mut impl PrecompileHandle, - data: &[u8], - ) -> PrecompileResult { - let (netuid, registration_allowed) = Self::parse_netuid_bool_parameter(data)?; - let call = RuntimeCall::AdminUtils( - pallet_admin_utils::Call::::sudo_set_network_pow_registration_allowed { - netuid, - registration_allowed, - }, - ); - - let account_id = - as AddressMapping>::into_account_id( - handle.context().caller, - ); - - try_dispatch_runtime_call(handle, call, RawOrigin::Signed(account_id)) - } - - fn get_min_burn(data: &[u8]) -> PrecompileResult { - let netuid = parse_netuid(data, 30)?; - - let value = pallet_subtensor::MinBurn::::get(netuid); - - let value_u256 = U256::from(value); - let mut result = [0_u8; 32]; - U256::to_big_endian(&value_u256, &mut result); + netuid: u16, + registration_allowed: bool, + ) -> EvmResult<()> { + let call = pallet_admin_utils::Call::::sudo_set_network_pow_registration_allowed { + netuid, + registration_allowed, + }; - Ok(PrecompileOutput { - exit_status: ExitSucceed::Returned, - output: result.into(), - }) + handle.try_dispatch_runtime_call(call, RawOrigin::Signed(handle.caller_account_id())) } - fn set_min_burn(handle: &mut impl PrecompileHandle, data: &[u8]) -> PrecompileResult { - let (netuid, min_burn) = Self::parse_netuid_u64_parameter(data)?; - let call = - RuntimeCall::AdminUtils(pallet_admin_utils::Call::::sudo_set_min_burn { - netuid, - min_burn, - }); - - let account_id = - as AddressMapping>::into_account_id( - handle.context().caller, - ); - - try_dispatch_runtime_call(handle, call, RawOrigin::Signed(account_id)) + #[precompile::public("getMinBurn(uint16)")] + #[precompile::view] + fn get_min_burn(_: &mut impl PrecompileHandle, netuid: u16) -> EvmResult { + Ok(pallet_subtensor::MinBurn::::get(netuid)) } - fn get_max_burn(data: &[u8]) -> PrecompileResult { - let netuid = parse_netuid(data, 30)?; - - let value = pallet_subtensor::MaxBurn::::get(netuid); - - let value_u256 = U256::from(value); - let mut result = [0_u8; 32]; - U256::to_big_endian(&value_u256, &mut result); + #[precompile::public("setMinBurn(uint16,uint64)")] + #[precompile::payable] + fn set_min_burn( + handle: &mut impl PrecompileHandle, + netuid: u16, + min_burn: u64, + ) -> EvmResult<()> { + let call = pallet_admin_utils::Call::::sudo_set_min_burn { netuid, min_burn }; - Ok(PrecompileOutput { - exit_status: ExitSucceed::Returned, - output: result.into(), - }) + handle.try_dispatch_runtime_call(call, RawOrigin::Signed(handle.caller_account_id())) } - fn set_max_burn(handle: &mut impl PrecompileHandle, data: &[u8]) -> PrecompileResult { - let (netuid, max_burn) = Self::parse_netuid_u64_parameter(data)?; - let call = - RuntimeCall::AdminUtils(pallet_admin_utils::Call::::sudo_set_max_burn { - netuid, - max_burn, - }); - - let account_id = - as AddressMapping>::into_account_id( - handle.context().caller, - ); - - try_dispatch_runtime_call(handle, call, RawOrigin::Signed(account_id)) + #[precompile::public("getMaxBurn(uint16)")] + #[precompile::view] + fn get_max_burn(_: &mut impl PrecompileHandle, netuid: u16) -> EvmResult { + Ok(pallet_subtensor::MaxBurn::::get(netuid)) } - fn get_difficulty(data: &[u8]) -> PrecompileResult { - let netuid = parse_netuid(data, 30)?; - - let value = pallet_subtensor::Difficulty::::get(netuid); - - let value_u256 = U256::from(value); - let mut result = [0_u8; 32]; - U256::to_big_endian(&value_u256, &mut result); + #[precompile::public("setMaxBurn(uint16,uint64)")] + #[precompile::payable] + fn set_max_burn( + handle: &mut impl PrecompileHandle, + netuid: u16, + max_burn: u64, + ) -> EvmResult<()> { + let call = pallet_admin_utils::Call::::sudo_set_max_burn { netuid, max_burn }; - Ok(PrecompileOutput { - exit_status: ExitSucceed::Returned, - output: result.into(), - }) + handle.try_dispatch_runtime_call(call, RawOrigin::Signed(handle.caller_account_id())) } - fn set_difficulty(handle: &mut impl PrecompileHandle, data: &[u8]) -> PrecompileResult { - let (netuid, difficulty) = Self::parse_netuid_u64_parameter(data)?; - let call = - RuntimeCall::AdminUtils(pallet_admin_utils::Call::::sudo_set_difficulty { - netuid, - difficulty, - }); - - let account_id = - as AddressMapping>::into_account_id( - handle.context().caller, - ); - - try_dispatch_runtime_call(handle, call, RawOrigin::Signed(account_id)) + #[precompile::public("getDifficulty(uint16)")] + #[precompile::view] + fn get_difficulty(_: &mut impl PrecompileHandle, netuid: u16) -> EvmResult { + Ok(pallet_subtensor::Difficulty::::get(netuid)) } - fn get_bonds_moving_average(data: &[u8]) -> PrecompileResult { - let netuid = parse_netuid(data, 30)?; - - let value = pallet_subtensor::BondsMovingAverage::::get(netuid); + #[precompile::public("setDifficulty(uint16,uint64)")] + #[precompile::payable] + fn set_difficulty( + handle: &mut impl PrecompileHandle, + netuid: u16, + difficulty: u64, + ) -> EvmResult<()> { + let call = pallet_admin_utils::Call::::sudo_set_difficulty { netuid, difficulty }; - let value_u256 = U256::from(value); - let mut result = [0_u8; 32]; - U256::to_big_endian(&value_u256, &mut result); + handle.try_dispatch_runtime_call(call, RawOrigin::Signed(handle.caller_account_id())) + } - Ok(PrecompileOutput { - exit_status: ExitSucceed::Returned, - output: result.into(), - }) + #[precompile::public("getBondsMovingAverage(uint16)")] + #[precompile::view] + fn get_bonds_moving_average(_: &mut impl PrecompileHandle, netuid: u16) -> EvmResult { + Ok(pallet_subtensor::BondsMovingAverage::::get(netuid)) } + #[precompile::public("setBondsMovingAverage(uint16,uint64)")] + #[precompile::payable] fn set_bonds_moving_average( handle: &mut impl PrecompileHandle, - data: &[u8], - ) -> PrecompileResult { - let (netuid, bonds_moving_average) = Self::parse_netuid_u64_parameter(data)?; - let call = RuntimeCall::AdminUtils( - pallet_admin_utils::Call::::sudo_set_bonds_moving_average { - netuid, - bonds_moving_average, - }, - ); - - let account_id = - as AddressMapping>::into_account_id( - handle.context().caller, - ); - - try_dispatch_runtime_call(handle, call, RawOrigin::Signed(account_id)) - } - - fn get_commit_reveal_weights_enabled(data: &[u8]) -> PrecompileResult { - let netuid = parse_netuid(data, 30)?; - - let value = pallet_subtensor::CommitRevealWeightsEnabled::::get(netuid); + netuid: u16, + bonds_moving_average: u64, + ) -> EvmResult<()> { + let call = pallet_admin_utils::Call::::sudo_set_bonds_moving_average { + netuid, + bonds_moving_average, + }; - let value_u256 = if value { U256::from(1) } else { U256::from(0) }; - let mut result = [0_u8; 32]; - U256::to_big_endian(&value_u256, &mut result); + handle.try_dispatch_runtime_call(call, RawOrigin::Signed(handle.caller_account_id())) + } - Ok(PrecompileOutput { - exit_status: ExitSucceed::Returned, - output: result.into(), - }) + #[precompile::public("getCommitRevealWeightsEnabled(uint16)")] + #[precompile::view] + fn get_commit_reveal_weights_enabled( + _: &mut impl PrecompileHandle, + netuid: u16, + ) -> EvmResult { + Ok(pallet_subtensor::CommitRevealWeightsEnabled::::get(netuid)) } + #[precompile::public("setCommitRevealWeightsEnabled(uint16,bool)")] + #[precompile::payable] fn set_commit_reveal_weights_enabled( handle: &mut impl PrecompileHandle, - data: &[u8], - ) -> PrecompileResult { - let (netuid, enabled) = Self::parse_netuid_bool_parameter(data)?; - let call = RuntimeCall::AdminUtils( - pallet_admin_utils::Call::::sudo_set_commit_reveal_weights_enabled { - netuid, - enabled, - }, - ); - - let account_id = - as AddressMapping>::into_account_id( - handle.context().caller, - ); - - try_dispatch_runtime_call(handle, call, RawOrigin::Signed(account_id)) - } - - fn get_liquid_alpha_enabled(data: &[u8]) -> PrecompileResult { - let netuid = parse_netuid(data, 30)?; - - let value = pallet_subtensor::LiquidAlphaOn::::get(netuid); + netuid: u16, + enabled: bool, + ) -> EvmResult<()> { + let call = pallet_admin_utils::Call::::sudo_set_commit_reveal_weights_enabled { + netuid, + enabled, + }; - let value_u256 = if value { U256::from(1) } else { U256::from(0) }; - let mut result = [0_u8; 32]; - U256::to_big_endian(&value_u256, &mut result); + handle.try_dispatch_runtime_call(call, RawOrigin::Signed(handle.caller_account_id())) + } - Ok(PrecompileOutput { - exit_status: ExitSucceed::Returned, - output: result.into(), - }) + #[precompile::public("getLiquidAlphaEnabled(uint16)")] + #[precompile::view] + fn get_liquid_alpha_enabled(_: &mut impl PrecompileHandle, netuid: u16) -> EvmResult { + Ok(pallet_subtensor::LiquidAlphaOn::::get(netuid)) } + #[precompile::public("setLiquidAlphaEnabled(uint16,bool)")] + #[precompile::payable] fn set_liquid_alpha_enabled( handle: &mut impl PrecompileHandle, - data: &[u8], - ) -> PrecompileResult { - let (netuid, enabled) = Self::parse_netuid_bool_parameter(data)?; - let call = RuntimeCall::AdminUtils( - pallet_admin_utils::Call::::sudo_set_liquid_alpha_enabled { netuid, enabled }, - ); - - let account_id = - as AddressMapping>::into_account_id( - handle.context().caller, - ); - - try_dispatch_runtime_call(handle, call, RawOrigin::Signed(account_id)) - } - - fn get_alpha_values(data: &[u8]) -> PrecompileResult { - let netuid = parse_netuid(data, 30)?; - - let (alpha_low, alpha_high) = pallet_subtensor::AlphaValues::::get(netuid); - - let mut value_u256 = U256::from(alpha_low); - let mut result = [0_u8; 64]; - U256::to_big_endian(&value_u256, &mut result[0..]); - - value_u256 = U256::from(alpha_high); - U256::to_big_endian(&value_u256, &mut result[32..]); - - Ok(PrecompileOutput { - exit_status: ExitSucceed::Returned, - output: result.into(), - }) - } - - fn set_alpha_values(handle: &mut impl PrecompileHandle, data: &[u8]) -> PrecompileResult { - let (netuid, alpha_low, alpha_high) = Self::parse_netuid_u16_u16_parameter(data)?; + netuid: u16, + enabled: bool, + ) -> EvmResult<()> { let call = - RuntimeCall::AdminUtils(pallet_admin_utils::Call::::sudo_set_alpha_values { - netuid, - alpha_low, - alpha_high, - }); - - let account_id = - as AddressMapping>::into_account_id( - handle.context().caller, - ); - - try_dispatch_runtime_call(handle, call, RawOrigin::Signed(account_id)) - } - - fn get_commit_reveal_weights_interval(data: &[u8]) -> PrecompileResult { - let netuid = parse_netuid(data, 30)?; - - let value = pallet_subtensor::RevealPeriodEpochs::::get(netuid); - - let value_u256 = U256::from(value); - let mut result = [0_u8; 32]; - U256::to_big_endian(&value_u256, &mut result); - - Ok(PrecompileOutput { - exit_status: ExitSucceed::Returned, - output: result.into(), - }) - } - - fn set_commit_reveal_weights_interval( - handle: &mut impl PrecompileHandle, - data: &[u8], - ) -> PrecompileResult { - let (netuid, interval) = Self::parse_netuid_u64_parameter(data)?; - let call = RuntimeCall::AdminUtils( - pallet_admin_utils::Call::::sudo_set_commit_reveal_weights_interval { - netuid, - interval, - }, - ); - - let account_id = - as AddressMapping>::into_account_id( - handle.context().caller, - ); - - try_dispatch_runtime_call(handle, call, RawOrigin::Signed(account_id)) - } + pallet_admin_utils::Call::::sudo_set_liquid_alpha_enabled { netuid, enabled }; - fn parse_register_network_parameters( - data: &[u8], - ) -> Result< - ( - AccountId32, - Vec, - Vec, - Vec, - Vec, - Vec, - Vec, - Vec, - ), - PrecompileFailure, - > { - let (pubkey, dynamic_params) = get_pubkey(data)?; - let dynamic_data_len = dynamic_params.len(); - - let mut buf = [0_u8; 4]; - // get all start points for the data items: name, repo, contact, url, discord, description, additional - buf.copy_from_slice(get_slice(data, 60, 64)?); - let subnet_name_start: usize = u32::from_be_bytes(buf) as usize; - if subnet_name_start > dynamic_data_len { - log::error!( - "the start position of subnet name as {} is too big ", - subnet_name_start - ); - return Err(PrecompileFailure::Error { - exit_status: ExitError::InvalidRange, - }); - } - - buf.copy_from_slice(get_slice(data, 92, 96)?); - let github_repo_start: usize = u32::from_be_bytes(buf) as usize; - if github_repo_start > dynamic_data_len { - log::error!( - "the start position of github repo as {} is too big ", - github_repo_start - ); - return Err(PrecompileFailure::Error { - exit_status: ExitError::InvalidRange, - }); - } - - buf.copy_from_slice(get_slice(data, 124, 128)?); - let subnet_contact_start: usize = u32::from_be_bytes(buf) as usize; - if subnet_contact_start > dynamic_data_len { - log::error!( - "the start position of subnet contact as {} is too big ", - subnet_contact_start - ); - return Err(PrecompileFailure::Error { - exit_status: ExitError::InvalidRange, - }); - } - - buf.copy_from_slice(get_slice(data, 156, 160)?); - let subnet_url_start: usize = u32::from_be_bytes(buf) as usize; - if subnet_url_start > dynamic_data_len { - log::error!( - "the start position of subnet_url as {} is too big ", - subnet_url_start - ); - return Err(PrecompileFailure::Error { - exit_status: ExitError::InvalidRange, - }); - } - - buf.copy_from_slice(get_slice(data, 188, 192)?); - let discord_start: usize = u32::from_be_bytes(buf) as usize; - if discord_start > dynamic_data_len { - log::error!( - "the start position of discord as {} is too big ", - discord_start - ); - return Err(PrecompileFailure::Error { - exit_status: ExitError::InvalidRange, - }); - } - - buf.copy_from_slice(get_slice(data, 220, 224)?); - let description_start: usize = u32::from_be_bytes(buf) as usize; - if description_start > dynamic_data_len { - log::error!( - "the start position of description as {} is too big ", - description_start - ); - return Err(PrecompileFailure::Error { - exit_status: ExitError::InvalidRange, - }); - } - - buf.copy_from_slice(get_slice(data, 252, 256)?); - let additional_start: usize = u32::from_be_bytes(buf) as usize; - if additional_start > dynamic_data_len { - log::error!( - "the start position of additional as {} is too big ", - additional_start - ); - return Err(PrecompileFailure::Error { - exit_status: ExitError::InvalidRange, - }); - } - - // get name - buf.copy_from_slice(get_slice( - data, - subnet_name_start + 28, - subnet_name_start + 32, - )?); - let subnet_name_len: usize = u32::from_be_bytes(buf) as usize; - - if subnet_name_len > MAX_SINGLE_PARAMETER_SIZE { - log::error!( - "the length of subnet name as {} is too big", - subnet_name_len - ); - return Err(PrecompileFailure::Error { - exit_status: ExitError::InvalidRange, - }); - } - - let mut name_vec = vec![0; subnet_name_len]; - name_vec.copy_from_slice(get_slice( - data, - subnet_name_start + 32, - subnet_name_start + subnet_name_len + 32, - )?); - - // get repo data - buf.copy_from_slice(get_slice( - data, - github_repo_start + 28, - github_repo_start + 32, - )?); - let github_repo_len: usize = u32::from_be_bytes(buf) as usize; - if github_repo_len > MAX_SINGLE_PARAMETER_SIZE { - log::error!( - "the length of github repo as {} is too big", - github_repo_len - ); - return Err(PrecompileFailure::Error { - exit_status: ExitError::InvalidRange, - }); - } - - let mut repo_vec = vec![0; github_repo_len]; - repo_vec.copy_from_slice(get_slice( - data, - github_repo_start + 32, - github_repo_start + github_repo_len + 32, - )?); - - // get contact data - buf.copy_from_slice(get_slice( - data, - subnet_contact_start + 28, - subnet_contact_start + 32, - )?); - let subnet_contact_len: usize = u32::from_be_bytes(buf) as usize; - if subnet_contact_len > MAX_SINGLE_PARAMETER_SIZE { - log::error!( - "the length of subnet contact as {} is too big", - subnet_contact_len - ); - return Err(PrecompileFailure::Error { - exit_status: ExitError::InvalidRange, - }); - } - - let mut contact_vec = vec![0; subnet_contact_len]; - contact_vec.copy_from_slice(get_slice( - data, - subnet_contact_start + 32, - subnet_contact_start + subnet_contact_len + 32, - )?); - - // get subnet_url - buf.copy_from_slice(get_slice( - data, - subnet_url_start + 28, - subnet_url_start + 32, - )?); - let subnet_url_len: usize = u32::from_be_bytes(buf) as usize; - if subnet_url_len > MAX_SINGLE_PARAMETER_SIZE { - log::error!("the length of subnet_url as {} is too big", subnet_url_len); - return Err(PrecompileFailure::Error { - exit_status: ExitError::InvalidRange, - }); - } - let mut url_vec = vec![0; subnet_url_len]; - url_vec.copy_from_slice(get_slice( - data, - subnet_url_start + 32, - subnet_url_start + subnet_url_len + 32, - )?); - - // get discord - buf.copy_from_slice(get_slice(data, discord_start + 28, discord_start + 32)?); - let discord_len: usize = u32::from_be_bytes(buf) as usize; - if discord_len > MAX_SINGLE_PARAMETER_SIZE { - log::error!("the length of discord as {} is too big", discord_len); - return Err(PrecompileFailure::Error { - exit_status: ExitError::InvalidRange, - }); - } - let mut discord_vec = vec![0; discord_len]; - discord_vec.copy_from_slice(get_slice( - data, - discord_start + 32, - discord_start + discord_len + 32, - )?); - - // get description - buf.copy_from_slice(get_slice( - data, - description_start + 28, - description_start + 32, - )?); - let description_len: usize = u32::from_be_bytes(buf) as usize; - if description_len > MAX_SINGLE_PARAMETER_SIZE { - log::error!( - "the length of description as {} is too big", - description_len - ); - return Err(PrecompileFailure::Error { - exit_status: ExitError::InvalidRange, - }); - } - let mut description_vec = vec![0; description_len]; - description_vec.copy_from_slice(get_slice( - data, - description_start + 32, - description_start + description_len + 32, - )?); - - // get additional - buf.copy_from_slice(get_slice( - data, - additional_start + 28, - additional_start + 32, - )?); - let additional_len: usize = u32::from_be_bytes(buf) as usize; - if additional_len > MAX_SINGLE_PARAMETER_SIZE { - log::error!("the length of additional as {} is too big", additional_len); - return Err(PrecompileFailure::Error { - exit_status: ExitError::InvalidRange, - }); - } - let mut additional_vec = vec![0; additional_len]; - additional_vec.copy_from_slice(get_slice( - data, - additional_start + 32, - additional_start + additional_len + 32, - )?); - - Ok(( - pubkey, - name_vec, - repo_vec, - contact_vec, - url_vec, - discord_vec, - description_vec, - additional_vec, - )) + handle.try_dispatch_runtime_call(call, RawOrigin::Signed(handle.caller_account_id())) } - fn parse_netuid_u64_parameter(data: &[u8]) -> Result<(u16, u64), PrecompileFailure> { - if data.len() < 64 { - return Err(PrecompileFailure::Error { - exit_status: ExitError::InvalidRange, - }); - } - let netuid = parse_netuid(data, 30)?; - - let mut parameter_vec = [0u8; 8]; - parameter_vec.copy_from_slice(get_slice(data, 56, 64)?); - let parameter = u64::from_be_bytes(parameter_vec); - - Ok((netuid, parameter)) + #[precompile::public("getAlphaValues(uint16)")] + #[precompile::view] + fn get_alpha_values(_: &mut impl PrecompileHandle, netuid: u16) -> EvmResult<(u16, u16)> { + Ok(pallet_subtensor::AlphaValues::::get(netuid)) } - fn parse_netuid_u16_parameter(data: &[u8]) -> Result<(u16, u16), PrecompileFailure> { - if data.len() < 64 { - return Err(PrecompileFailure::Error { - exit_status: ExitError::InvalidRange, - }); - } - let netuid = parse_netuid(data, 30)?; - - let mut parameter_vec = [0u8; 2]; - parameter_vec.copy_from_slice(get_slice(data, 62, 64)?); - let parameter = u16::from_be_bytes(parameter_vec); + #[precompile::public("setAlphaValues(uint16,uint16,uint16)")] + #[precompile::payable] + fn set_alpha_values( + handle: &mut impl PrecompileHandle, + netuid: u16, + alpha_low: u16, + alpha_high: u16, + ) -> EvmResult<()> { + let call = pallet_admin_utils::Call::::sudo_set_alpha_values { + netuid, + alpha_low, + alpha_high, + }; - Ok((netuid, parameter)) + handle.try_dispatch_runtime_call(call, RawOrigin::Signed(handle.caller_account_id())) } - fn parse_netuid_u16_u16_parameter(data: &[u8]) -> Result<(u16, u16, u16), PrecompileFailure> { - if data.len() < 96 { - return Err(PrecompileFailure::Error { - exit_status: ExitError::InvalidRange, - }); - } - let netuid = parse_netuid(data, 30)?; - - let mut parameter_1_vec = [0u8; 2]; - parameter_1_vec.copy_from_slice(get_slice(data, 62, 64)?); - let parameter_1 = u16::from_be_bytes(parameter_1_vec); - - let mut parameter_2_vec = [0u8; 2]; - parameter_2_vec.copy_from_slice(get_slice(data, 94, 96)?); - let parameter_2 = u16::from_be_bytes(parameter_2_vec); - - Ok((netuid, parameter_1, parameter_2)) + #[precompile::public("getCommitRevealWeightsInterval(uint16)")] + #[precompile::view] + fn get_commit_reveal_weights_interval( + _: &mut impl PrecompileHandle, + netuid: u16, + ) -> EvmResult { + Ok(pallet_subtensor::RevealPeriodEpochs::::get(netuid)) } - fn parse_netuid_bool_parameter(data: &[u8]) -> Result<(u16, bool), PrecompileFailure> { - if data.len() < 64 { - return Err(PrecompileFailure::Error { - exit_status: ExitError::InvalidRange, - }); - } - let netuid = parse_netuid(data, 30)?; - - let mut parameter_vec = [0_u8]; - parameter_vec.copy_from_slice(get_slice(data, 63, 64)?); - - let parameter = parameter_vec[0] != 0; + #[precompile::public("setCommitRevealWeightsInterval(uint16,uint64)")] + #[precompile::payable] + fn set_commit_reveal_weights_interval( + handle: &mut impl PrecompileHandle, + netuid: u16, + interval: u64, + ) -> EvmResult<()> { + let call = pallet_admin_utils::Call::::sudo_set_commit_reveal_weights_interval { + netuid, + interval, + }; - Ok((netuid, parameter)) + handle.try_dispatch_runtime_call(call, RawOrigin::Signed(handle.caller_account_id())) } }