#![cfg_attr(not(feature = "std"), no_std)] #[cfg(test)] mod mock; #[cfg(test)] mod tests; pub mod types; use crate::types::{ColdkeyLock, FunctionId, Output, StakeAvailability, SubnetRegistrationState}; use codec::{Decode, Encode, MaxEncodedLen}; use frame_support::{DebugNoBound, traits::Get}; use frame_system::RawOrigin; use pallet_contracts::chain_extension::{ BufInBufOutState, ChainExtension, Environment, Ext, InitState, RetVal, SysConfig, }; use pallet_subtensor::weights::WeightInfo as SubtensorWeightInfo; use pallet_subtensor_proxy as pallet_proxy; use pallet_subtensor_proxy::WeightInfo; use sp_runtime::{DispatchError, Weight, traits::StaticLookup}; use sp_std::marker::PhantomData; use substrate_fixed::types::U64F64; use subtensor_runtime_common::{AlphaBalance, NetUid, ProxyType, TaoBalance}; use subtensor_swap_interface::SwapHandler; #[derive(DebugNoBound)] pub struct SubtensorChainExtension(PhantomData); impl Default for SubtensorChainExtension { fn default() -> Self { Self(PhantomData) } } impl ChainExtension for SubtensorChainExtension where T: pallet_subtensor::Config + pallet_contracts::Config + pallet_proxy::Config + pallet_subtensor_swap::Config, T::AccountId: Clone, <::Lookup as StaticLookup>::Source: From<::AccountId>, { fn call(&mut self, env: Environment) -> Result where E: Ext, { let mut adapter = ContractsEnvAdapter::::new(env); Self::dispatch(&mut adapter) } fn enabled() -> bool { true } } impl SubtensorChainExtension where T: pallet_subtensor::Config + pallet_contracts::Config + pallet_proxy::Config + pallet_subtensor_swap::Config, T::AccountId: Clone, { fn dispatch_add_stake_v1( env: &mut Env, origin: RawOrigin, ) -> Result where Env: SubtensorExtensionEnv, <::Lookup as StaticLookup>::Source: From<::AccountId>, { let (hotkey, netuid, amount_staked): (T::AccountId, NetUid, TaoBalance) = env .read_as() .map_err(|_| DispatchError::Other("Failed to decode input parameters"))?; let weight = <::WeightInfo as SubtensorWeightInfo>::add_stake(); env.charge_weight(weight)?; let call_result = pallet_subtensor::Pallet::::add_stake(origin.into(), hotkey, netuid, amount_staked); match call_result { Ok(_) => Ok(RetVal::Converging(Output::Success as u32)), Err(e) => { let error_code = Output::from(e) as u32; Ok(RetVal::Converging(error_code)) } } } fn dispatch_remove_stake_v1( env: &mut Env, origin: RawOrigin, ) -> Result where Env: SubtensorExtensionEnv, <::Lookup as StaticLookup>::Source: From<::AccountId>, { let (hotkey, netuid, amount_unstaked): (T::AccountId, NetUid, AlphaBalance) = env .read_as() .map_err(|_| DispatchError::Other("Failed to decode input parameters"))?; // weight for remove_stake is not defined in the Subtensor pallet's WeightInfo let weight = <::WeightInfo as SubtensorWeightInfo>::remove_stake(); env.charge_weight(weight)?; let call_result = pallet_subtensor::Pallet::::remove_stake( origin.into(), hotkey, netuid, amount_unstaked, ); match call_result { Ok(_) => Ok(RetVal::Converging(Output::Success as u32)), Err(e) => { let error_code = Output::from(e) as u32; Ok(RetVal::Converging(error_code)) } } } fn dispatch_unstake_all_v1( env: &mut Env, origin: RawOrigin, ) -> Result where Env: SubtensorExtensionEnv, <::Lookup as StaticLookup>::Source: From<::AccountId>, { let hotkey: T::AccountId = env .read_as() .map_err(|_| DispatchError::Other("Failed to decode input parameters"))?; let weight = <::WeightInfo as SubtensorWeightInfo>::unstake_all(); env.charge_weight(weight)?; let call_result = pallet_subtensor::Pallet::::unstake_all(origin.into(), hotkey); match call_result { Ok(_) => Ok(RetVal::Converging(Output::Success as u32)), Err(e) => { let error_code = Output::from(e) as u32; Ok(RetVal::Converging(error_code)) } } } fn dispatch_unstake_all_alpha_v1( env: &mut Env, origin: RawOrigin, ) -> Result where Env: SubtensorExtensionEnv, <::Lookup as StaticLookup>::Source: From<::AccountId>, { let hotkey: T::AccountId = env .read_as() .map_err(|_| DispatchError::Other("Failed to decode input parameters"))?; let weight = <::WeightInfo as SubtensorWeightInfo>::unstake_all_alpha( ); env.charge_weight(weight)?; let call_result = pallet_subtensor::Pallet::::unstake_all_alpha(origin.into(), hotkey); match call_result { Ok(_) => Ok(RetVal::Converging(Output::Success as u32)), Err(e) => { let error_code = Output::from(e) as u32; Ok(RetVal::Converging(error_code)) } } } fn dispatch_move_stake_v1( env: &mut Env, origin: RawOrigin, ) -> Result where Env: SubtensorExtensionEnv, <::Lookup as StaticLookup>::Source: From<::AccountId>, { let (origin_hotkey, destination_hotkey, origin_netuid, destination_netuid, alpha_amount): ( T::AccountId, T::AccountId, NetUid, NetUid, AlphaBalance, ) = env .read_as() .map_err(|_| DispatchError::Other("Failed to decode input parameters"))?; let weight = <::WeightInfo as SubtensorWeightInfo>::move_stake(); env.charge_weight(weight)?; let call_result = pallet_subtensor::Pallet::::move_stake( origin.into(), origin_hotkey, destination_hotkey, origin_netuid, destination_netuid, alpha_amount, ); match call_result { Ok(_) => Ok(RetVal::Converging(Output::Success as u32)), Err(e) => { let error_code = Output::from(e) as u32; Ok(RetVal::Converging(error_code)) } } } fn dispatch_transfer_stake_v1( env: &mut Env, origin: RawOrigin, ) -> Result where Env: SubtensorExtensionEnv, <::Lookup as StaticLookup>::Source: From<::AccountId>, { let (destination_coldkey, hotkey, origin_netuid, destination_netuid, alpha_amount): ( T::AccountId, T::AccountId, NetUid, NetUid, AlphaBalance, ) = env .read_as() .map_err(|_| DispatchError::Other("Failed to decode input parameters"))?; let weight = <::WeightInfo as SubtensorWeightInfo>::transfer_stake(); env.charge_weight(weight)?; let call_result = pallet_subtensor::Pallet::::transfer_stake( origin.into(), destination_coldkey, hotkey, origin_netuid, destination_netuid, alpha_amount, ); match call_result { Ok(_) => Ok(RetVal::Converging(Output::Success as u32)), Err(e) => { let error_code = Output::from(e) as u32; Ok(RetVal::Converging(error_code)) } } } fn dispatch_swap_stake_v1( env: &mut Env, origin: RawOrigin, ) -> Result where Env: SubtensorExtensionEnv, <::Lookup as StaticLookup>::Source: From<::AccountId>, { let (hotkey, origin_netuid, destination_netuid, alpha_amount): ( T::AccountId, NetUid, NetUid, AlphaBalance, ) = env .read_as() .map_err(|_| DispatchError::Other("Failed to decode input parameters"))?; let weight = <::WeightInfo as SubtensorWeightInfo>::swap_stake(); env.charge_weight(weight)?; let call_result = pallet_subtensor::Pallet::::swap_stake( origin.into(), hotkey, origin_netuid, destination_netuid, alpha_amount, ); match call_result { Ok(_) => Ok(RetVal::Converging(Output::Success as u32)), Err(e) => { let error_code = Output::from(e) as u32; Ok(RetVal::Converging(error_code)) } } } fn dispatch_add_stake_limit_v1( env: &mut Env, origin: RawOrigin, ) -> Result where Env: SubtensorExtensionEnv, <::Lookup as StaticLookup>::Source: From<::AccountId>, { let (hotkey, netuid, amount_staked, limit_price, allow_partial): ( T::AccountId, NetUid, TaoBalance, TaoBalance, bool, ) = env .read_as() .map_err(|_| DispatchError::Other("Failed to decode input parameters"))?; let weight = <::WeightInfo as SubtensorWeightInfo>::add_stake_limit(); env.charge_weight(weight)?; let call_result = pallet_subtensor::Pallet::::add_stake_limit( origin.into(), hotkey, netuid, amount_staked, limit_price, allow_partial, ); match call_result { Ok(_) => Ok(RetVal::Converging(Output::Success as u32)), Err(e) => { let error_code = Output::from(e) as u32; Ok(RetVal::Converging(error_code)) } } } fn dispatch_remove_stake_limit_v1( env: &mut Env, origin: RawOrigin, ) -> Result where Env: SubtensorExtensionEnv, <::Lookup as StaticLookup>::Source: From<::AccountId>, { let (hotkey, netuid, amount_unstaked, limit_price, allow_partial): ( T::AccountId, NetUid, AlphaBalance, TaoBalance, bool, ) = env .read_as() .map_err(|_| DispatchError::Other("Failed to decode input parameters"))?; let weight = <::WeightInfo as SubtensorWeightInfo>::remove_stake_limit(); env.charge_weight(weight)?; let call_result = pallet_subtensor::Pallet::::remove_stake_limit( origin.into(), hotkey, netuid, amount_unstaked, limit_price, allow_partial, ); match call_result { Ok(_) => Ok(RetVal::Converging(Output::Success as u32)), Err(e) => { let error_code = Output::from(e) as u32; Ok(RetVal::Converging(error_code)) } } } fn dispatch_swap_stake_limit_v1( env: &mut Env, origin: RawOrigin, ) -> Result where Env: SubtensorExtensionEnv, <::Lookup as StaticLookup>::Source: From<::AccountId>, { let ( hotkey, origin_netuid, destination_netuid, alpha_amount, limit_price, allow_partial, ): (T::AccountId, NetUid, NetUid, AlphaBalance, TaoBalance, bool) = env.read_as() .map_err(|_| DispatchError::Other("Failed to decode input parameters"))?; let weight = <::WeightInfo as SubtensorWeightInfo>::swap_stake_limit( ); env.charge_weight(weight)?; let call_result = pallet_subtensor::Pallet::::swap_stake_limit( origin.into(), hotkey, origin_netuid, destination_netuid, alpha_amount, limit_price, allow_partial, ); match call_result { Ok(_) => Ok(RetVal::Converging(Output::Success as u32)), Err(e) => { let error_code = Output::from(e) as u32; Ok(RetVal::Converging(error_code)) } } } fn dispatch_remove_stake_full_limit_v1( env: &mut Env, origin: RawOrigin, ) -> Result where Env: SubtensorExtensionEnv, <::Lookup as StaticLookup>::Source: From<::AccountId>, { let (hotkey, netuid, limit_price): (T::AccountId, NetUid, Option) = env .read_as() .map_err(|_| DispatchError::Other("Failed to decode input parameters"))?; let weight = <::WeightInfo as SubtensorWeightInfo>::remove_stake_full_limit(); env.charge_weight(weight)?; let call_result = pallet_subtensor::Pallet::::remove_stake_full_limit( origin.into(), hotkey, netuid, limit_price, ); match call_result { Ok(_) => Ok(RetVal::Converging(Output::Success as u32)), Err(e) => { let error_code = Output::from(e) as u32; Ok(RetVal::Converging(error_code)) } } } fn dispatch_set_coldkey_auto_stake_hotkey_v1( env: &mut Env, origin: RawOrigin, ) -> Result where Env: SubtensorExtensionEnv, <::Lookup as StaticLookup>::Source: From<::AccountId>, { let (netuid, hotkey): (NetUid, T::AccountId) = env .read_as() .map_err(|_| DispatchError::Other("Failed to decode input parameters"))?; let weight = <::WeightInfo as SubtensorWeightInfo>::set_coldkey_auto_stake_hotkey(); env.charge_weight(weight)?; let call_result = pallet_subtensor::Pallet::::set_coldkey_auto_stake_hotkey( origin.into(), netuid, hotkey, ); match call_result { Ok(_) => Ok(RetVal::Converging(Output::Success as u32)), Err(e) => { let error_code = Output::from(e) as u32; Ok(RetVal::Converging(error_code)) } } } fn dispatch_add_proxy_v1( env: &mut Env, origin: RawOrigin, ) -> Result where Env: SubtensorExtensionEnv, <::Lookup as StaticLookup>::Source: From<::AccountId>, { let delegate: T::AccountId = env .read_as() .map_err(|_| DispatchError::Other("Failed to decode input parameters"))?; let weight = ::WeightInfo::add_proxy( ::MaxProxies::get(), ); env.charge_weight(weight)?; let delegate_lookup = <::Lookup as StaticLookup>::Source::from(delegate); let call_result = pallet_proxy::Pallet::::add_proxy( origin.into(), delegate_lookup, ProxyType::Staking, 0u32.into(), ); match call_result { Ok(_) => Ok(RetVal::Converging(Output::Success as u32)), Err(e) => { let error_code = Output::from(e) as u32; Ok(RetVal::Converging(error_code)) } } } fn dispatch_remove_proxy_v1( env: &mut Env, origin: RawOrigin, ) -> Result where Env: SubtensorExtensionEnv, <::Lookup as StaticLookup>::Source: From<::AccountId>, { let delegate: T::AccountId = env .read_as() .map_err(|_| DispatchError::Other("Failed to decode input parameters"))?; let weight = ::WeightInfo::remove_proxy( ::MaxProxies::get(), ); env.charge_weight(weight)?; let delegate_lookup = <::Lookup as StaticLookup>::Source::from(delegate); let call_result = pallet_proxy::Pallet::::remove_proxy( origin.into(), delegate_lookup, ProxyType::Staking, 0u32.into(), ); match call_result { Ok(_) => Ok(RetVal::Converging(Output::Success as u32)), Err(e) => { let error_code = Output::from(e) as u32; Ok(RetVal::Converging(error_code)) } } } fn dispatch(env: &mut Env) -> Result where Env: SubtensorExtensionEnv, <::Lookup as StaticLookup>::Source: From<::AccountId>, { let func_id: FunctionId = env.func_id().try_into().map_err(|_| { DispatchError::Other( "Invalid function id - does not correspond to any registered function", ) })?; match func_id { FunctionId::GetStakeInfoForHotkeyColdkeyNetuidV1 => { let (hotkey, coldkey, netuid): (T::AccountId, T::AccountId, NetUid) = env .read_as() .map_err(|_| DispatchError::Other("Failed to decode input parameters"))?; let stake_info = pallet_subtensor::Pallet::::get_stake_info_for_hotkey_coldkey_netuid( hotkey, coldkey, netuid, ); let encoded_result = stake_info.encode(); env.write_output(&encoded_result) .map_err(|_| DispatchError::Other("Failed to write output"))?; Ok(RetVal::Converging(Output::Success as u32)) } FunctionId::GetSubnetRegistrationStateV1 => { let netuid: NetUid = env .read_as() .map_err(|_| DispatchError::Other("Failed to decode input parameters"))?; let state = SubnetRegistrationState { netuid, exists: pallet_subtensor::Pallet::::if_subnet_exist(netuid), registered_subnet_counter: pallet_subtensor::Pallet::::get_registered_subnet_counter(netuid), }; env.write_output(&state.encode()) .map_err(|_| DispatchError::Other("Failed to write output"))?; Ok(RetVal::Converging(Output::Success as u32)) } FunctionId::GetColdkeyLockV1 => { let (coldkey, netuid): (T::AccountId, NetUid) = env .read_as() .map_err(|_| DispatchError::Other("Failed to decode input parameters"))?; let lock = pallet_subtensor::Pallet::::get_coldkey_lock(&coldkey, netuid).map(|lock| { ColdkeyLock { locked_mass: lock.locked_mass, conviction_bits: lock.conviction.to_bits(), last_update: lock.last_update, } }); env.write_output(&lock.encode()) .map_err(|_| DispatchError::Other("Failed to write output"))?; Ok(RetVal::Converging(Output::Success as u32)) } FunctionId::GetStakeAvailabilityV1 => { let (coldkey, netuid): (T::AccountId, NetUid) = env .read_as() .map_err(|_| DispatchError::Other("Failed to decode input parameters"))?; let (total, locked, available) = pallet_subtensor::Pallet::::stake_availability(&coldkey, netuid); let availability = StakeAvailability { netuid, total, locked, available, }; env.write_output(&availability.encode()) .map_err(|_| DispatchError::Other("Failed to write output"))?; Ok(RetVal::Converging(Output::Success as u32)) } FunctionId::AddStakeV1 => { let origin = RawOrigin::Signed(env.caller()); Self::dispatch_add_stake_v1(env, origin) } FunctionId::CallerAddStakeV1 => { let origin = convert_origin(env.origin()); Self::dispatch_add_stake_v1(env, origin) } FunctionId::RemoveStakeV1 => { let origin = RawOrigin::Signed(env.caller()); Self::dispatch_remove_stake_v1(env, origin) } FunctionId::CallerRemoveStakeV1 => { let origin = convert_origin(env.origin()); Self::dispatch_remove_stake_v1(env, origin) } FunctionId::UnstakeAllV1 => { let origin = RawOrigin::Signed(env.caller()); Self::dispatch_unstake_all_v1(env, origin) } FunctionId::CallerUnstakeAllV1 => { let origin = convert_origin(env.origin()); Self::dispatch_unstake_all_v1(env, origin) } FunctionId::UnstakeAllAlphaV1 => { let origin = RawOrigin::Signed(env.caller()); Self::dispatch_unstake_all_alpha_v1(env, origin) } FunctionId::CallerUnstakeAllAlphaV1 => { let origin = convert_origin(env.origin()); Self::dispatch_unstake_all_alpha_v1(env, origin) } FunctionId::MoveStakeV1 => { let origin = RawOrigin::Signed(env.caller()); Self::dispatch_move_stake_v1(env, origin) } FunctionId::CallerMoveStakeV1 => { let origin = convert_origin(env.origin()); Self::dispatch_move_stake_v1(env, origin) } FunctionId::TransferStakeV1 => { let origin = RawOrigin::Signed(env.caller()); Self::dispatch_transfer_stake_v1(env, origin) } FunctionId::CallerTransferStakeV1 => { let origin = convert_origin(env.origin()); Self::dispatch_transfer_stake_v1(env, origin) } FunctionId::SwapStakeV1 => { let origin = RawOrigin::Signed(env.caller()); Self::dispatch_swap_stake_v1(env, origin) } FunctionId::CallerSwapStakeV1 => { let origin = convert_origin(env.origin()); Self::dispatch_swap_stake_v1(env, origin) } FunctionId::AddStakeLimitV1 => { let origin = RawOrigin::Signed(env.caller()); Self::dispatch_add_stake_limit_v1(env, origin) } FunctionId::CallerAddStakeLimitV1 => { let origin = convert_origin(env.origin()); Self::dispatch_add_stake_limit_v1(env, origin) } FunctionId::RemoveStakeLimitV1 => { let origin = RawOrigin::Signed(env.caller()); Self::dispatch_remove_stake_limit_v1(env, origin) } FunctionId::CallerRemoveStakeLimitV1 => { let origin = convert_origin(env.origin()); Self::dispatch_remove_stake_limit_v1(env, origin) } FunctionId::SwapStakeLimitV1 => { let origin = RawOrigin::Signed(env.caller()); Self::dispatch_swap_stake_limit_v1(env, origin) } FunctionId::CallerSwapStakeLimitV1 => { let origin = convert_origin(env.origin()); Self::dispatch_swap_stake_limit_v1(env, origin) } FunctionId::RemoveStakeFullLimitV1 => { let origin = RawOrigin::Signed(env.caller()); Self::dispatch_remove_stake_full_limit_v1(env, origin) } FunctionId::CallerRemoveStakeFullLimitV1 => { let origin = convert_origin(env.origin()); Self::dispatch_remove_stake_full_limit_v1(env, origin) } FunctionId::SetColdkeyAutoStakeHotkeyV1 => { let origin = RawOrigin::Signed(env.caller()); Self::dispatch_set_coldkey_auto_stake_hotkey_v1(env, origin) } FunctionId::CallerSetColdkeyAutoStakeHotkeyV1 => { let origin = convert_origin(env.origin()); Self::dispatch_set_coldkey_auto_stake_hotkey_v1(env, origin) } FunctionId::AddProxyV1 => { let origin = RawOrigin::Signed(env.caller()); Self::dispatch_add_proxy_v1(env, origin) } FunctionId::CallerAddProxyV1 => { let origin = convert_origin(env.origin()); Self::dispatch_add_proxy_v1(env, origin) } FunctionId::RemoveProxyV1 => { let origin = RawOrigin::Signed(env.caller()); Self::dispatch_remove_proxy_v1(env, origin) } FunctionId::CallerRemoveProxyV1 => { let origin = convert_origin(env.origin()); Self::dispatch_remove_proxy_v1(env, origin) } FunctionId::GetAlphaPriceV1 => { let netuid: NetUid = env .read_as() .map_err(|_| DispatchError::Other("Failed to decode input parameters"))?; let current_alpha_price = as SwapHandler>::current_alpha_price( netuid.into(), ); let price = current_alpha_price.saturating_mul(U64F64::from_num(1_000_000_000)); let price: u64 = price.saturating_to_num(); let encoded_result = price.encode(); env.write_output(&encoded_result) .map_err(|_| DispatchError::Other("Failed to write output"))?; Ok(RetVal::Converging(Output::Success as u32)) } FunctionId::RecycleAlphaV1 => { let weight = <::WeightInfo as SubtensorWeightInfo>::recycle_alpha(); env.charge_weight(weight)?; let (hotkey, netuid, amount): (T::AccountId, NetUid, AlphaBalance) = env.read_as()?; let caller = env.caller(); let call_result = pallet_subtensor::Pallet::::do_recycle_alpha( RawOrigin::Signed(caller).into(), hotkey, amount, netuid, ); match call_result { Ok(real_amount) => { env.write_output(&real_amount.encode()) .map_err(|_| DispatchError::Other("Failed to write output"))?; Ok(RetVal::Converging(Output::Success as u32)) } Err(e) => { let error_code = Output::from(e) as u32; Ok(RetVal::Converging(error_code)) } } } FunctionId::BurnAlphaV1 => { let weight = <::WeightInfo as SubtensorWeightInfo>::burn_alpha(); env.charge_weight(weight)?; let (hotkey, netuid, amount): (T::AccountId, NetUid, AlphaBalance) = env.read_as()?; let caller = env.caller(); let call_result = pallet_subtensor::Pallet::::do_burn_alpha( RawOrigin::Signed(caller).into(), hotkey, amount, netuid, ); match call_result { Ok(real_amount) => { env.write_output(&real_amount.encode()) .map_err(|_| DispatchError::Other("Failed to write output"))?; Ok(RetVal::Converging(Output::Success as u32)) } Err(e) => { let error_code = Output::from(e) as u32; Ok(RetVal::Converging(error_code)) } } } FunctionId::AddStakeRecycleV1 => { let weight = <::WeightInfo as SubtensorWeightInfo>::add_stake() .saturating_add( <::WeightInfo as SubtensorWeightInfo>::recycle_alpha(), ); env.charge_weight(weight)?; let (hotkey, netuid, tao_amount): (T::AccountId, NetUid, TaoBalance) = env.read_as()?; let call_result = pallet_subtensor::Pallet::::do_add_stake_recycle( RawOrigin::Signed(env.caller()).into(), hotkey, netuid, tao_amount, ); match call_result { Ok(alpha) => { env.write_output(&alpha.encode()) .map_err(|_| DispatchError::Other("Failed to write output"))?; Ok(RetVal::Converging(Output::Success as u32)) } Err(e) => { let error_code = Output::from(e) as u32; Ok(RetVal::Converging(error_code)) } } } FunctionId::AddStakeBurnV1 => { let weight = <::WeightInfo as SubtensorWeightInfo>::add_stake() .saturating_add( <::WeightInfo as SubtensorWeightInfo>::burn_alpha(), ); env.charge_weight(weight)?; let (hotkey, netuid, tao_amount): (T::AccountId, NetUid, TaoBalance) = env.read_as()?; let call_result = pallet_subtensor::Pallet::::do_add_stake_burn_permissionless( RawOrigin::Signed(env.caller()).into(), hotkey, netuid, tao_amount, ); match call_result { Ok(alpha) => { env.write_output(&alpha.encode()) .map_err(|_| DispatchError::Other("Failed to write output"))?; Ok(RetVal::Converging(Output::Success as u32)) } Err(e) => { let error_code = Output::from(e) as u32; Ok(RetVal::Converging(error_code)) } } } } } } // Convert from the contract origin to the raw origin fn convert_origin(origin: pallet_contracts::Origin) -> RawOrigin where T: pallet_contracts::Config, { match origin { pallet_contracts::Origin::Signed(caller) => RawOrigin::Signed(caller), pallet_contracts::Origin::Root => RawOrigin::Root, } } trait SubtensorExtensionEnv where T: pallet_contracts::Config, { fn func_id(&self) -> u16; fn charge_weight(&mut self, weight: Weight) -> Result<(), DispatchError>; fn read_as(&mut self) -> Result; fn write_output(&mut self, data: &[u8]) -> Result<(), DispatchError>; fn caller(&mut self) -> T::AccountId; #[allow(dead_code)] fn origin(&mut self) -> pallet_contracts::Origin; } struct ContractsEnvAdapter<'a, 'b, T, E> where T: pallet_subtensor::Config + pallet_contracts::Config, E: Ext, { env: Environment<'a, 'b, E, BufInBufOutState>, _marker: PhantomData, } impl<'a, 'b, T, E> ContractsEnvAdapter<'a, 'b, T, E> where T: pallet_subtensor::Config + pallet_contracts::Config, T::AccountId: Clone, E: Ext, { fn new(env: Environment<'a, 'b, E, InitState>) -> Self { Self { env: env.buf_in_buf_out(), _marker: PhantomData, } } } impl<'a, 'b, T, E> SubtensorExtensionEnv for ContractsEnvAdapter<'a, 'b, T, E> where T: pallet_subtensor::Config + pallet_contracts::Config, T::AccountId: Clone, E: Ext, { fn func_id(&self) -> u16 { self.env.func_id() } fn charge_weight(&mut self, weight: Weight) -> Result<(), DispatchError> { self.env.charge_weight(weight).map(|_| ()) } fn read_as(&mut self) -> Result { self.env.read_as() } fn write_output(&mut self, data: &[u8]) -> Result<(), DispatchError> { self.env.write(data, false, None) } fn caller(&mut self) -> T::AccountId { self.env.ext().address().clone() } fn origin(&mut self) -> pallet_contracts::Origin { self.env.ext().caller() } }