diff --git a/frame/ethereum/src/mock.rs b/frame/ethereum/src/mock.rs index 332549ddd0..c74ca34ec2 100644 --- a/frame/ethereum/src/mock.rs +++ b/frame/ethereum/src/mock.rs @@ -32,7 +32,7 @@ use sp_runtime::{ AccountId32, BuildStorage, }; // Frontier -use pallet_evm::{AddressMapping, EnsureAddressTruncated, FeeCalculator}; +use pallet_evm::{AddressMapping, BalanceConverter, EnsureAddressTruncated, FeeCalculator}; use super::*; use crate::IntermediateStateRoot; @@ -158,8 +158,42 @@ parameter_types! { pub SuicideQuickClearLimit: u32 = 0; } +const EVM_DECIMALS_FACTOR: u64 = 1_000_000_000_u64; +pub struct SubtensorEvmBalanceConverter; + +impl BalanceConverter for SubtensorEvmBalanceConverter { + /// Convert from Substrate balance (u64) to EVM balance (U256) + fn into_evm_balance(value: U256) -> Option { + value + .checked_mul(U256::from(EVM_DECIMALS_FACTOR)) + .and_then(|evm_value| { + // Ensure the result fits within the maximum U256 value + if evm_value <= U256::MAX { + Some(evm_value) + } else { + None + } + }) + } + + /// Convert from EVM balance (U256) to Substrate balance (u64) + fn into_substrate_balance(value: U256) -> Option { + value + .checked_div(U256::from(EVM_DECIMALS_FACTOR)) + .and_then(|substrate_value| { + // Ensure the result fits within the TAO balance type (u64) + if substrate_value <= U256::from(u64::MAX) { + Some(substrate_value) + } else { + None + } + }) + } +} + impl pallet_evm::Config for Test { type FeeCalculator = FixedGasPrice; + type BalanceConverter = SubtensorEvmBalanceConverter; type GasWeightMapping = pallet_evm::FixedGasWeightMapping; type WeightPerGas = WeightPerGas; type BlockHashMapping = crate::EthereumBlockHashMapping; diff --git a/frame/ethereum/src/tests/eip1559.rs b/frame/ethereum/src/tests/eip1559.rs index 2dd7f7c823..c2b552d3ba 100644 --- a/frame/ethereum/src/tests/eip1559.rs +++ b/frame/ethereum/src/tests/eip1559.rs @@ -537,7 +537,7 @@ fn validated_transaction_apply_zero_gas_price_works() { max_fee_per_gas: U256::zero(), gas_limit: U256::from(21_000), action: ethereum::TransactionAction::Call(bob.address), - value: U256::from(100), + value: U256::from(100e9 as u128), input: Default::default(), } .sign(&alice.private_key, None); diff --git a/frame/ethereum/src/tests/eip2930.rs b/frame/ethereum/src/tests/eip2930.rs index 4cb6a13c4d..0cf0518d77 100644 --- a/frame/ethereum/src/tests/eip2930.rs +++ b/frame/ethereum/src/tests/eip2930.rs @@ -462,7 +462,7 @@ fn validated_transaction_apply_zero_gas_price_works() { gas_price: U256::zero(), gas_limit: U256::from(21_000), action: ethereum::TransactionAction::Call(bob.address), - value: U256::from(100), + value: U256::from(100e9 as u128), input: Default::default(), } .sign(&alice.private_key, None); diff --git a/frame/ethereum/src/tests/legacy.rs b/frame/ethereum/src/tests/legacy.rs index e90d6cb092..3234e510a4 100644 --- a/frame/ethereum/src/tests/legacy.rs +++ b/frame/ethereum/src/tests/legacy.rs @@ -462,7 +462,7 @@ fn validated_transaction_apply_zero_gas_price_works() { gas_price: U256::zero(), gas_limit: U256::from(21_000), action: ethereum::TransactionAction::Call(bob.address), - value: U256::from(100), + value: U256::from(100e9 as u128), input: Default::default(), } .sign(&alice.private_key); diff --git a/frame/evm/precompile/dispatch/src/mock.rs b/frame/evm/precompile/dispatch/src/mock.rs index d2fce9dc8d..8b20e0074a 100644 --- a/frame/evm/precompile/dispatch/src/mock.rs +++ b/frame/evm/precompile/dispatch/src/mock.rs @@ -29,8 +29,8 @@ use sp_runtime::traits::{BlakeTwo256, IdentityLookup}; use fp_evm::{ExitError, ExitReason, Transfer}; use pallet_evm::{ - Context, EnsureAddressNever, EnsureAddressRoot, FeeCalculator, IdentityAddressMapping, - PrecompileHandle, + BalanceConverter, Context, EnsureAddressNever, EnsureAddressRoot, FeeCalculator, + IdentityAddressMapping, PrecompileHandle, }; frame_support::construct_runtime! { @@ -121,6 +121,39 @@ impl FeeCalculator for FixedGasPrice { } } +const EVM_DECIMALS_FACTOR: u64 = 1_000_000_000_u64; +pub struct SubtensorEvmBalanceConverter; + +impl BalanceConverter for SubtensorEvmBalanceConverter { + /// Convert from Substrate balance (u64) to EVM balance (U256) + fn into_evm_balance(value: U256) -> Option { + value + .checked_mul(U256::from(EVM_DECIMALS_FACTOR)) + .and_then(|evm_value| { + // Ensure the result fits within the maximum U256 value + if evm_value <= U256::MAX { + Some(evm_value) + } else { + None + } + }) + } + + /// Convert from EVM balance (U256) to Substrate balance (u64) + fn into_substrate_balance(value: U256) -> Option { + value + .checked_div(U256::from(EVM_DECIMALS_FACTOR)) + .and_then(|substrate_value| { + // Ensure the result fits within the TAO balance type (u64) + if substrate_value <= U256::from(u64::MAX) { + Some(substrate_value) + } else { + None + } + }) + } +} + pub struct FindAuthorTruncated; impl FindAuthor for FindAuthorTruncated { fn find_author<'a, I>(_digests: I) -> Option @@ -147,6 +180,8 @@ impl pallet_evm::Config for Test { type AddressMapping = IdentityAddressMapping; type Currency = Balances; + type BalanceConverter = SubtensorEvmBalanceConverter; + type RuntimeEvent = RuntimeEvent; type PrecompilesType = (); type PrecompilesValue = (); diff --git a/frame/evm/precompile/storage-cleaner/src/mock.rs b/frame/evm/precompile/storage-cleaner/src/mock.rs index 06c58e5f96..488a93ea1c 100644 --- a/frame/evm/precompile/storage-cleaner/src/mock.rs +++ b/frame/evm/precompile/storage-cleaner/src/mock.rs @@ -19,7 +19,7 @@ use crate::{StorageCleanerPrecompile, StorageCleanerPrecompileCall}; use frame_support::{parameter_types, weights::Weight}; -use pallet_evm::{EnsureAddressNever, EnsureAddressRoot, IdentityAddressMapping}; +use pallet_evm::{BalanceConverter, EnsureAddressNever, EnsureAddressRoot, IdentityAddressMapping}; use precompile_utils::{precompile_set::*, testing::*}; use sp_core::{ConstU32, H256, U256}; use sp_runtime::{ @@ -123,7 +123,41 @@ parameter_types! { pub SuicideQuickClearLimit: u32 = 0; } +const EVM_DECIMALS_FACTOR: u64 = 1_000_000_000_u64; +pub struct SubtensorEvmBalanceConverter; + +impl BalanceConverter for SubtensorEvmBalanceConverter { + /// Convert from Substrate balance (u64) to EVM balance (U256) + fn into_evm_balance(value: U256) -> Option { + value + .checked_mul(U256::from(EVM_DECIMALS_FACTOR)) + .and_then(|evm_value| { + // Ensure the result fits within the maximum U256 value + if evm_value <= U256::MAX { + Some(evm_value) + } else { + None + } + }) + } + + /// Convert from EVM balance (U256) to Substrate balance (u64) + fn into_substrate_balance(value: U256) -> Option { + value + .checked_div(U256::from(EVM_DECIMALS_FACTOR)) + .and_then(|substrate_value| { + // Ensure the result fits within the TAO balance type (u64) + if substrate_value <= U256::from(u64::MAX) { + Some(substrate_value) + } else { + None + } + }) + } +} + impl pallet_evm::Config for Runtime { + type BalanceConverter = SubtensorEvmBalanceConverter; type FeeCalculator = (); type GasWeightMapping = pallet_evm::FixedGasWeightMapping; type WeightPerGas = WeightPerGas; diff --git a/frame/evm/src/lib.rs b/frame/evm/src/lib.rs index 117b87cdb0..de839396ab 100644 --- a/frame/evm/src/lib.rs +++ b/frame/evm/src/lib.rs @@ -951,7 +951,8 @@ impl Pallet { let balance = T::Currency::reducible_balance(&account_id, Preservation::Preserve, Fortitude::Polite); let balance_u256 = U256::from(UniqueSaturatedInto::::unique_saturated_into(balance)); - let balance_eth = T::BalanceConverter::into_evm_balance(balance_u256).unwrap_or(U256::from(0)); + let balance_eth = + T::BalanceConverter::into_evm_balance(balance_u256).unwrap_or(U256::from(0)); ( Account { @@ -1027,7 +1028,8 @@ where let account_id = T::AddressMapping::into_account_id(*who); // Recalculate fee decimals using BalanceConverter - let fee_sub = T::BalanceConverter::into_substrate_balance(fee).ok_or(Error::::FeeOverflow)?; + let fee_sub = + T::BalanceConverter::into_substrate_balance(fee).ok_or(Error::::FeeOverflow)?; let imbalance = C::withdraw( &account_id, @@ -1036,22 +1038,27 @@ where ExistenceRequirement::AllowDeath, ) .map_err(|_| Error::::BalanceLow)?; - Ok(Some(imbalance)) + Ok(Some(imbalance)) // Returns substrate balance } fn correct_and_deposit_fee( who: &H160, corrected_fee: U256, base_fee: U256, - already_withdrawn: Self::LiquidityInfo, + already_withdrawn: Self::LiquidityInfo, // Expects substrate balance ) -> Self::LiquidityInfo { if let Some(paid) = already_withdrawn { let account_id = T::AddressMapping::into_account_id(*who); + // Convert corrected fee into substrate balance + let corrected_fee_sub = + T::BalanceConverter::into_substrate_balance(corrected_fee).unwrap_or(U256::from(0)); + // Calculate how much refund we should return let refund_amount = paid .peek() - .saturating_sub(corrected_fee.unique_saturated_into()); + .saturating_sub(corrected_fee_sub.unique_saturated_into()); + // refund to the account that paid the fees. If this fails, the // account might have dropped below the existential balance. In // that case we don't refund anything. @@ -1082,15 +1089,20 @@ where .same() .unwrap_or_else(|_| C::NegativeImbalance::zero()); - let (base_fee, tip) = adjusted_paid.split(base_fee.unique_saturated_into()); + // Convert base fee into substrate balance + let base_fee_sub = + T::BalanceConverter::into_substrate_balance(base_fee).unwrap_or(U256::from(0)); + + let (base_fee, tip) = adjusted_paid.split(base_fee_sub.unique_saturated_into()); // Handle base fee. Can be either burned, rationed, etc ... OU::on_unbalanced(base_fee); - return Some(tip); + return Some(tip); // Returns substrate balance } None } fn pay_priority_fee(tip: Self::LiquidityInfo) { + // Expects substrate balance // Default Ethereum behaviour: issue the tip to the block author. if let Some(tip) = tip { let account_id = T::AddressMapping::into_account_id(>::find_author()); @@ -1123,7 +1135,8 @@ where let account_id = T::AddressMapping::into_account_id(*who); // Recalculate fee decimals using BalanceConverter - let fee_sub = T::BalanceConverter::into_substrate_balance(fee).ok_or(Error::::FeeOverflow)?; + let fee_sub = + T::BalanceConverter::into_substrate_balance(fee).ok_or(Error::::FeeOverflow)?; let imbalance = F::withdraw( &account_id, @@ -1133,22 +1146,26 @@ where Fortitude::Polite, ) .map_err(|_| Error::::BalanceLow)?; - Ok(Some(imbalance)) + Ok(Some(imbalance)) // Returns substrate balance } fn correct_and_deposit_fee( who: &H160, corrected_fee: U256, base_fee: U256, - already_withdrawn: Self::LiquidityInfo, + already_withdrawn: Self::LiquidityInfo, // Expects substrate balance ) -> Self::LiquidityInfo { if let Some(paid) = already_withdrawn { let account_id = T::AddressMapping::into_account_id(*who); + // Convert corrected fee into substrate balance + let corrected_fee_sub = + T::BalanceConverter::into_substrate_balance(corrected_fee).unwrap_or(U256::from(0)); + // Calculate how much refund we should return let refund_amount = paid .peek() - .saturating_sub(corrected_fee.unique_saturated_into()); + .saturating_sub(corrected_fee_sub.unique_saturated_into()); // refund to the account that paid the fees. let refund_imbalance = F::deposit(&account_id, refund_amount, Precision::BestEffort) .unwrap_or_else(|_| Debt::::zero()); @@ -1159,15 +1176,20 @@ where .same() .unwrap_or_else(|_| Credit::::zero()); - let (base_fee, tip) = adjusted_paid.split(base_fee.unique_saturated_into()); + // Convert base fee into substrate balance + let base_fee_sub = + T::BalanceConverter::into_substrate_balance(base_fee).unwrap_or(U256::from(0)); + + let (base_fee, tip) = adjusted_paid.split(base_fee_sub.unique_saturated_into()); // Handle base fee. Can be either burned, rationed, etc ... OU::on_unbalanced(base_fee); - return Some(tip); + return Some(tip); // Returns substrate balance } None } fn pay_priority_fee(tip: Self::LiquidityInfo) { + // Expects substrate balance // Default Ethereum behaviour: issue the tip to the block author. if let Some(tip) = tip { let account_id = T::AddressMapping::into_account_id(>::find_author()); @@ -1236,10 +1258,11 @@ pub trait BalanceConverter { fn into_substrate_balance(value: U256) -> Option; } -impl BalanceConverter for () -{ +impl BalanceConverter for () { fn into_evm_balance(value: U256) -> Option { - Some(U256::from(UniqueSaturatedInto::::unique_saturated_into(value))) + Some(U256::from( + UniqueSaturatedInto::::unique_saturated_into(value), + )) } fn into_substrate_balance(value: U256) -> Option { diff --git a/frame/evm/src/mock.rs b/frame/evm/src/mock.rs index ab98820f11..2f42a8bef8 100644 --- a/frame/evm/src/mock.rs +++ b/frame/evm/src/mock.rs @@ -30,7 +30,7 @@ use sp_runtime::{ }; use crate::{ - EnsureAddressNever, EnsureAddressRoot, FeeCalculator, IdentityAddressMapping, + BalanceConverter, EnsureAddressNever, EnsureAddressRoot, FeeCalculator, IdentityAddressMapping, IsPrecompileResult, Precompile, PrecompileHandle, PrecompileResult, PrecompileSet, }; @@ -133,7 +133,42 @@ parameter_types! { pub MockPrecompiles: MockPrecompileSet = MockPrecompileSet; pub SuicideQuickClearLimit: u32 = 0; } + +const EVM_DECIMALS_FACTOR: u64 = 1_000_000_000_u64; +pub struct SubtensorEvmBalanceConverter; + +impl BalanceConverter for SubtensorEvmBalanceConverter { + /// Convert from Substrate balance (u64) to EVM balance (U256) + fn into_evm_balance(value: U256) -> Option { + value + .checked_mul(U256::from(EVM_DECIMALS_FACTOR)) + .and_then(|evm_value| { + // Ensure the result fits within the maximum U256 value + if evm_value <= U256::MAX { + Some(evm_value) + } else { + None + } + }) + } + + /// Convert from EVM balance (U256) to Substrate balance (u64) + fn into_substrate_balance(value: U256) -> Option { + value + .checked_div(U256::from(EVM_DECIMALS_FACTOR)) + .and_then(|substrate_value| { + // Ensure the result fits within the TAO balance type (u64) + if substrate_value <= U256::from(u64::MAX) { + Some(substrate_value) + } else { + None + } + }) + } +} + impl crate::Config for Test { + type BalanceConverter = SubtensorEvmBalanceConverter; type FeeCalculator = FixedGasPrice; type GasWeightMapping = crate::FixedGasWeightMapping; type WeightPerGas = WeightPerGas; diff --git a/frame/evm/src/runner/stack.rs b/frame/evm/src/runner/stack.rs index caf365bbba..ea2eada195 100644 --- a/frame/evm/src/runner/stack.rs +++ b/frame/evm/src/runner/stack.rs @@ -48,7 +48,7 @@ use fp_evm::{ use crate::{ runner::Runner as RunnerT, AccountCodes, AccountCodesMetadata, AccountStorages, AddressMapping, - BalanceOf, BalanceConverter, BlockHashMapping, Config, Error, Event, FeeCalculator, + BalanceConverter, BalanceOf, BlockHashMapping, Config, Error, Event, FeeCalculator, OnChargeEVMTransaction, OnCreate, Pallet, RunnerError, }; @@ -230,6 +230,7 @@ where })?; // Deduct fee from the `source` account. Returns `None` if `total_fee` is Zero. + // === Note: This fee gets converted to substrate decimals in `withdraw_fee` === let fee = T::OnChargeTransaction::withdraw_fee(&source, total_fee) .map_err(|e| RunnerError { error: e, weight })?; @@ -295,6 +296,8 @@ where // Refunded 200 - 40 = 160. // Tip 5 * 6 = 30. // Burned 200 - (160 + 30) = 10. Which is equivalent to gas_used * base_fee. + // === Note: we expect acutal_fee and actual_base_fee to be in EVM decimals. but `fee` should be in substrate decimals already === + // === Note: `actual_priority_fee` gets converted to substrate decimals in `correct_and_deposit_fee` === let actual_priority_fee = T::OnChargeTransaction::correct_and_deposit_fee( &source, // Actual fee after evm execution, including tip. @@ -304,6 +307,7 @@ where // Fee initially withdrawn. fee, ); + // === Note: `actual_priority_fee` is already in substrate decimals === T::OnChargeTransaction::pay_priority_fee(actual_priority_fee); let state = executor.into_state(); @@ -923,7 +927,8 @@ where let target = T::AddressMapping::into_account_id(transfer.target); // Adjust decimals - let value_sub = T::BalanceConverter::into_substrate_balance(transfer.value).ok_or(ExitError::OutOfFund)?; + let value_sub = T::BalanceConverter::into_substrate_balance(transfer.value) + .ok_or(ExitError::OutOfFund)?; T::Currency::transfer( &source, diff --git a/frame/evm/src/tests.rs b/frame/evm/src/tests.rs index f2379c19d5..07da3e7720 100644 --- a/frame/evm/src/tests.rs +++ b/frame/evm/src/tests.rs @@ -89,6 +89,9 @@ mod proof_size_test { gas_limit: u64, weight_limit: Option, ) -> Result>> { + let whitelist = Vec::new(); + let whitelist_disabled = true; + ::Runner::create( H160::default(), hex::decode(PROOF_SIZE_TEST_CALLEE_CONTRACT_BYTECODE.trim_end()).unwrap(), @@ -98,6 +101,8 @@ mod proof_size_test { None, None, Vec::new(), + whitelist, + whitelist_disabled, true, // transactional true, // must be validated weight_limit, @@ -110,6 +115,9 @@ mod proof_size_test { gas_limit: u64, weight_limit: Option, ) -> Result>> { + let whitelist = Vec::new(); + let whitelist_disabled = true; + ::Runner::create( H160::default(), hex::decode(PROOF_SIZE_TEST_CONTRACT_BYTECODE.trim_end()).unwrap(), @@ -119,6 +127,8 @@ mod proof_size_test { None, None, Vec::new(), + whitelist, + whitelist_disabled, true, // non-transactional true, // must be validated weight_limit, @@ -714,6 +724,7 @@ fn fail_call_return_ok() { }); } +// cargo test --package pallet-evm --lib -- tests::fee_deduction --exact --show-output #[test] fn fee_deduction() { new_test_ext().execute_with(|| { @@ -726,11 +737,11 @@ fn fee_deduction() { assert_eq!(Balances::free_balance(substrate_addr), 100); // Deduct fees as 10 units - let imbalance = <::OnChargeTransaction as OnChargeEVMTransaction>::withdraw_fee(&evm_addr, U256::from(10)).unwrap(); + let imbalance = <::OnChargeTransaction as OnChargeEVMTransaction>::withdraw_fee(&evm_addr, U256::from(10e9 as u64)).unwrap(); assert_eq!(Balances::free_balance(substrate_addr), 90); // Refund fees as 5 units - <::OnChargeTransaction as OnChargeEVMTransaction>::correct_and_deposit_fee(&evm_addr, U256::from(5), U256::from(5), imbalance); + <::OnChargeTransaction as OnChargeEVMTransaction>::correct_and_deposit_fee(&evm_addr, U256::from(5e9 as u64), U256::from(5e9 as u64), imbalance); assert_eq!(Balances::free_balance(substrate_addr), 95); }); } diff --git a/precompiles/tests-external/lib.rs b/precompiles/tests-external/lib.rs index de0c5de26e..7d83e0e3f6 100644 --- a/precompiles/tests-external/lib.rs +++ b/precompiles/tests-external/lib.rs @@ -34,7 +34,7 @@ use sp_runtime::{ }; // Frontier use fp_evm::{ExitReason, ExitRevert, PrecompileFailure, PrecompileHandle}; -use pallet_evm::{EnsureAddressNever, EnsureAddressRoot}; +use pallet_evm::{BalanceConverter, EnsureAddressNever, EnsureAddressRoot}; use precompile_utils::{ precompile_set::*, solidity::{codec::Writer, revert::revert}, @@ -229,7 +229,41 @@ parameter_types! { pub SuicideQuickClearLimit: u32 = 0; } +const EVM_DECIMALS_FACTOR: u64 = 1_000_000_000_u64; +pub struct SubtensorEvmBalanceConverter; + +impl BalanceConverter for SubtensorEvmBalanceConverter { + /// Convert from Substrate balance (u64) to EVM balance (U256) + fn into_evm_balance(value: U256) -> Option { + value + .checked_mul(U256::from(EVM_DECIMALS_FACTOR)) + .and_then(|evm_value| { + // Ensure the result fits within the maximum U256 value + if evm_value <= U256::MAX { + Some(evm_value) + } else { + None + } + }) + } + + /// Convert from EVM balance (U256) to Substrate balance (u64) + fn into_substrate_balance(value: U256) -> Option { + value + .checked_div(U256::from(EVM_DECIMALS_FACTOR)) + .and_then(|substrate_value| { + // Ensure the result fits within the TAO balance type (u64) + if substrate_value <= U256::from(u64::MAX) { + Some(substrate_value) + } else { + None + } + }) + } +} + impl pallet_evm::Config for Runtime { + type BalanceConverter = SubtensorEvmBalanceConverter; type FeeCalculator = (); type GasWeightMapping = pallet_evm::FixedGasWeightMapping; type WeightPerGas = WeightPerGas; diff --git a/template/runtime/src/lib.rs b/template/runtime/src/lib.rs index 776de5fe74..a639d1ed43 100644 --- a/template/runtime/src/lib.rs +++ b/template/runtime/src/lib.rs @@ -52,7 +52,8 @@ use fp_evm::weight_per_gas; use fp_rpc::TransactionStatus; use pallet_ethereum::{Call::transact, PostLogContent, Transaction as EthereumTransaction}; use pallet_evm::{ - Account as EVMAccount, EnsureAccountId20, FeeCalculator, IdentityAddressMapping, Runner, + Account as EVMAccount, BalanceConverter, EnsureAccountId20, FeeCalculator, + IdentityAddressMapping, Runner, }; // A few exports that help ease life for downstream crates. @@ -347,6 +348,39 @@ parameter_types! { pub SuicideQuickClearLimit: u32 = 0; } +const EVM_DECIMALS_FACTOR: u64 = 1_000_000_000_u64; +pub struct SubtensorEvmBalanceConverter; + +impl BalanceConverter for SubtensorEvmBalanceConverter { + /// Convert from Substrate balance (u64) to EVM balance (U256) + fn into_evm_balance(value: U256) -> Option { + value + .checked_mul(U256::from(EVM_DECIMALS_FACTOR)) + .and_then(|evm_value| { + // Ensure the result fits within the maximum U256 value + if evm_value <= U256::MAX { + Some(evm_value) + } else { + None + } + }) + } + + /// Convert from EVM balance (U256) to Substrate balance (u64) + fn into_substrate_balance(value: U256) -> Option { + value + .checked_div(U256::from(EVM_DECIMALS_FACTOR)) + .and_then(|substrate_value| { + // Ensure the result fits within the TAO balance type (u64) + if substrate_value <= U256::from(u64::MAX) { + Some(substrate_value) + } else { + None + } + }) + } +} + impl pallet_evm::Config for Runtime { type FeeCalculator = BaseFee; type GasWeightMapping = pallet_evm::FixedGasWeightMapping; @@ -369,7 +403,7 @@ impl pallet_evm::Config for Runtime { type SuicideQuickClearLimit = SuicideQuickClearLimit; type Timestamp = Timestamp; type WeightInfo = pallet_evm::weights::SubstrateWeight; - type BalanceConverter = (); + type BalanceConverter = SubtensorEvmBalanceConverter; } parameter_types! {