#![cfg_attr(not(feature = "std"), no_std)] extern crate alloc; use core::marker::PhantomData; use crate::extensions::*; pub use address_mapping::AddressMappingPrecompile; pub use alpha::AlphaPrecompile; pub use balance::BalancePrecompile; pub use balance_transfer::BalanceTransferPrecompile; pub use crowdloan::CrowdloanPrecompile; pub use ed25519::Ed25519Verify; pub use extensions::PrecompileExt; use fp_evm::{ExitError, PrecompileFailure}; use frame_support::traits::IsSubType; use frame_support::{ dispatch::{DispatchInfo, GetDispatchInfo, PostDispatchInfo}, pallet_prelude::Decode, }; pub use leasing::LeasingPrecompile; pub use metagraph::MetagraphPrecompile; pub use neuron::NeuronPrecompile; use pallet_admin_utils::PrecompileEnum; use pallet_evm::{ AddressMapping, IsPrecompileResult, Precompile, PrecompileHandle, PrecompileResult, PrecompileSet, }; use pallet_evm_precompile_bn128::{Bn128Add, Bn128Mul, Bn128Pairing}; use pallet_evm_precompile_dispatch::Dispatch; use pallet_evm_precompile_modexp::Modexp; use pallet_evm_precompile_sha3fips::Sha3FIPS256; use pallet_evm_precompile_simple::{ECRecover, ECRecoverPublicKey, Identity, Ripemd160, Sha256}; use pallet_subtensor_proxy as pallet_proxy; pub use proxy::ProxyPrecompile; use sp_core::{H160, U256, crypto::ByteArray}; use sp_runtime::traits::{AsSystemOriginSigner, Dispatchable, StaticLookup}; pub use sr25519::Sr25519Verify; pub use staking::{StakingPrecompile, StakingPrecompileV2}; pub use storage_query::StorageQueryPrecompile; pub use subnet::SubnetPrecompile; use subtensor_runtime_common::ProxyType; pub use uid_lookup::UidLookupPrecompile; pub use voting_power::VotingPowerPrecompile; mod address_mapping; mod alpha; mod balance; mod balance_transfer; mod crowdloan; mod ed25519; mod extensions; mod leasing; mod metagraph; mod neuron; mod proxy; mod sr25519; mod staking; mod storage_query; mod subnet; mod uid_lookup; mod voting_power; #[cfg(test)] mod mock; pub struct Precompiles(PhantomData); impl Default for Precompiles where R: frame_system::Config + pallet_evm::Config + pallet_balances::Config + pallet_admin_utils::Config + pallet_subtensor::Config + pallet_subtensor_swap::Config + pallet_proxy::Config + pallet_crowdloan::Config + pallet_shield::Config + pallet_subtensor_proxy::Config + Send + Sync + scale_info::TypeInfo, R::AccountId: From<[u8; 32]> + ByteArray + Into<[u8; 32]>, ::RuntimeOrigin: AsSystemOriginSigner + Clone, ::RuntimeCall: From> + From> + From> + From> + From> + GetDispatchInfo + Dispatchable + IsSubType> + IsSubType> + IsSubType> + IsSubType>, ::AddressMapping: AddressMapping, ::Balance: Into + TryFrom, <::Lookup as StaticLookup>::Source: From, { fn default() -> Self { Self::new() } } impl Precompiles where R: frame_system::Config + pallet_evm::Config + pallet_balances::Config + pallet_admin_utils::Config + pallet_subtensor::Config + pallet_subtensor_swap::Config + pallet_proxy::Config + pallet_crowdloan::Config + pallet_shield::Config + pallet_subtensor_proxy::Config + Send + Sync + scale_info::TypeInfo, R::AccountId: From<[u8; 32]> + ByteArray + Into<[u8; 32]>, ::RuntimeOrigin: AsSystemOriginSigner + Clone, ::RuntimeCall: From> + From> + From> + From> + From> + GetDispatchInfo + Dispatchable + IsSubType> + IsSubType> + IsSubType> + IsSubType>, ::AddressMapping: AddressMapping, ::Balance: Into + TryFrom, <::Lookup as StaticLookup>::Source: From, { pub fn new() -> Self { Self(Default::default()) } pub fn used_addresses() -> [H160; 28] { [ hash(1), hash(2), hash(3), hash(4), hash(5), hash(6), hash(7), hash(8), hash(9), hash(1024), hash(1025), hash(Ed25519Verify::::INDEX), hash(Sr25519Verify::::INDEX), hash(BalanceTransferPrecompile::::INDEX), hash(StakingPrecompile::::INDEX), hash(SubnetPrecompile::::INDEX), hash(MetagraphPrecompile::::INDEX), hash(NeuronPrecompile::::INDEX), hash(StakingPrecompileV2::::INDEX), hash(StorageQueryPrecompile::::INDEX), hash(UidLookupPrecompile::::INDEX), hash(AlphaPrecompile::::INDEX), hash(CrowdloanPrecompile::::INDEX), hash(LeasingPrecompile::::INDEX), hash(VotingPowerPrecompile::::INDEX), hash(ProxyPrecompile::::INDEX), hash(AddressMappingPrecompile::::INDEX), hash(BalancePrecompile::::INDEX), ] } } impl PrecompileSet for Precompiles where R: frame_system::Config + pallet_evm::Config + pallet_balances::Config + pallet_admin_utils::Config + pallet_subtensor::Config + pallet_subtensor_swap::Config + pallet_proxy::Config + pallet_crowdloan::Config + pallet_shield::Config + pallet_subtensor_proxy::Config + Send + Sync + scale_info::TypeInfo, R::AccountId: From<[u8; 32]> + ByteArray + Into<[u8; 32]>, ::RuntimeOrigin: AsSystemOriginSigner + Clone, ::RuntimeCall: From> + From> + From> + From> + From> + GetDispatchInfo + Dispatchable + IsSubType> + IsSubType> + IsSubType> + IsSubType> + Decode, <::RuntimeCall as Dispatchable>::RuntimeOrigin: From>>, ::AddressMapping: AddressMapping, ::Balance: Into + TryFrom, <::Lookup as StaticLookup>::Source: From, { fn execute(&self, handle: &mut impl PrecompileHandle) -> Option { match handle.code_address() { // Ethereum precompiles : a if a == hash(1) => Some(ECRecover::execute(handle)), a if a == hash(2) => Some(Sha256::execute(handle)), a if a == hash(3) => Some(Ripemd160::execute(handle)), a if a == hash(4) => Some(Identity::execute(handle)), a if a == hash(5) => Some(Modexp::execute(handle)), a if a == hash(6) => Some(Dispatch::::execute(handle)), a if a == hash(7) => Some(Bn128Mul::execute(handle)), a if a == hash(8) => Some(Bn128Pairing::execute(handle)), a if a == hash(9) => Some(Bn128Add::execute(handle)), // 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(Ed25519Verify::::INDEX) => { Some(Ed25519Verify::::execute(handle)) } a if a == hash(Sr25519Verify::::INDEX) => { Some(Sr25519Verify::::execute(handle)) } // Subtensor specific precompiles : a if a == hash(BalanceTransferPrecompile::::INDEX) => { BalanceTransferPrecompile::::try_execute::( handle, PrecompileEnum::BalanceTransfer, ) } a if a == hash(StakingPrecompile::::INDEX) => { StakingPrecompile::::try_execute::(handle, PrecompileEnum::Staking) } a if a == hash(StakingPrecompileV2::::INDEX) => { StakingPrecompileV2::::try_execute::(handle, PrecompileEnum::Staking) } a if a == hash(SubnetPrecompile::::INDEX) => { SubnetPrecompile::::try_execute::(handle, PrecompileEnum::Subnet) } a if a == hash(MetagraphPrecompile::::INDEX) => { MetagraphPrecompile::::try_execute::(handle, PrecompileEnum::Metagraph) } a if a == hash(NeuronPrecompile::::INDEX) => { NeuronPrecompile::::try_execute::(handle, PrecompileEnum::Neuron) } a if a == hash(UidLookupPrecompile::::INDEX) => { UidLookupPrecompile::::try_execute::(handle, PrecompileEnum::UidLookup) } a if a == hash(StorageQueryPrecompile::::INDEX) => { Some(StorageQueryPrecompile::::execute(handle)) } a if a == hash(AlphaPrecompile::::INDEX) => { AlphaPrecompile::::try_execute::(handle, PrecompileEnum::Alpha) } a if a == hash(CrowdloanPrecompile::::INDEX) => { CrowdloanPrecompile::::try_execute::(handle, PrecompileEnum::Crowdloan) } a if a == hash(LeasingPrecompile::::INDEX) => { LeasingPrecompile::::try_execute::(handle, PrecompileEnum::Leasing) } a if a == hash(VotingPowerPrecompile::::INDEX) => { VotingPowerPrecompile::::try_execute::(handle, PrecompileEnum::VotingPower) } a if a == hash(ProxyPrecompile::::INDEX) => { ProxyPrecompile::::try_execute::(handle, PrecompileEnum::Proxy) } a if a == hash(AddressMappingPrecompile::::INDEX) => { AddressMappingPrecompile::::try_execute::( handle, PrecompileEnum::AddressMapping, ) } a if a == hash(BalancePrecompile::::INDEX) => { BalancePrecompile::::try_execute::(handle, PrecompileEnum::AccountBalance) } _ => None, } } fn is_precompile(&self, address: H160, _gas: u64) -> IsPrecompileResult { IsPrecompileResult::Answer { is_precompile: Self::used_addresses().contains(&address), extra_cost: 0, } } } fn hash(a: u64) -> H160 { H160::from_low_u64_be(a) } /* * * This is used to parse a slice from bytes with PrecompileFailure as Error * */ 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) } else { log::error!( "fail to get slice from data, {:?}, from {}, to {}", &data, from, to ); Err(PrecompileFailure::Error { exit_status: ExitError::InvalidRange, }) } }