Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Create wrapper types for EVM and Substrate balances #10

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 7 additions & 5 deletions frame/ethereum/src/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ use sp_runtime::{
AccountId32, BuildStorage,
};
// Frontier
use pallet_evm::{AddressMapping, BalanceConverter, EnsureAddressTruncated, FeeCalculator};
use pallet_evm::{AddressMapping, BalanceConverter, EnsureAddressTruncated, EvmBalance, FeeCalculator, SubstrateBalance};

use super::*;
use crate::IntermediateStateRoot;
Expand Down Expand Up @@ -163,27 +163,29 @@ pub struct SubtensorEvmBalanceConverter;

impl BalanceConverter for SubtensorEvmBalanceConverter {
/// Convert from Substrate balance (u64) to EVM balance (U256)
fn into_evm_balance(value: U256) -> Option<U256> {
fn into_evm_balance(value: SubstrateBalance) -> Option<EvmBalance> {
value
.into_u256()
.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)
Some(EvmBalance::new(evm_value))
} else {
None
}
})
}

/// Convert from EVM balance (U256) to Substrate balance (u64)
fn into_substrate_balance(value: U256) -> Option<U256> {
fn into_substrate_balance(value: EvmBalance) -> Option<SubstrateBalance> {
value
.into_u256()
.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)
Some(SubstrateBalance::new(substrate_value))
} else {
None
}
Expand Down
13 changes: 7 additions & 6 deletions frame/evm/precompile/dispatch/src/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,7 @@ use sp_runtime::traits::{BlakeTwo256, IdentityLookup};

use fp_evm::{ExitError, ExitReason, Transfer};
use pallet_evm::{
BalanceConverter, Context, EnsureAddressNever, EnsureAddressRoot, FeeCalculator,
IdentityAddressMapping, PrecompileHandle,
BalanceConverter, Context, EnsureAddressNever, EnsureAddressRoot, EvmBalance, FeeCalculator, IdentityAddressMapping, PrecompileHandle, SubstrateBalance
};

frame_support::construct_runtime! {
Expand Down Expand Up @@ -126,27 +125,29 @@ pub struct SubtensorEvmBalanceConverter;

impl BalanceConverter for SubtensorEvmBalanceConverter {
/// Convert from Substrate balance (u64) to EVM balance (U256)
fn into_evm_balance(value: U256) -> Option<U256> {
fn into_evm_balance(value: SubstrateBalance) -> Option<EvmBalance> {
value
.into_u256()
.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)
Some(EvmBalance::new(evm_value))
} else {
None
}
})
}

/// Convert from EVM balance (U256) to Substrate balance (u64)
fn into_substrate_balance(value: U256) -> Option<U256> {
fn into_substrate_balance(value: EvmBalance) -> Option<SubstrateBalance> {
value
.into_u256()
.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)
Some(SubstrateBalance::new(substrate_value))
} else {
None
}
Expand Down
12 changes: 7 additions & 5 deletions frame/evm/precompile/storage-cleaner/src/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@

use crate::{StorageCleanerPrecompile, StorageCleanerPrecompileCall};
use frame_support::{parameter_types, weights::Weight};
use pallet_evm::{BalanceConverter, EnsureAddressNever, EnsureAddressRoot, IdentityAddressMapping};
use pallet_evm::{BalanceConverter, EnsureAddressNever, EnsureAddressRoot, EvmBalance, IdentityAddressMapping, SubstrateBalance};
use precompile_utils::{precompile_set::*, testing::*};
use sp_core::{ConstU32, H256, U256};
use sp_runtime::{
Expand Down Expand Up @@ -128,27 +128,29 @@ pub struct SubtensorEvmBalanceConverter;

impl BalanceConverter for SubtensorEvmBalanceConverter {
/// Convert from Substrate balance (u64) to EVM balance (U256)
fn into_evm_balance(value: U256) -> Option<U256> {
fn into_evm_balance(value: SubstrateBalance) -> Option<EvmBalance> {
value
.into_u256()
.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)
Some(EvmBalance::new(evm_value))
} else {
None
}
})
}

/// Convert from EVM balance (U256) to Substrate balance (u64)
fn into_substrate_balance(value: U256) -> Option<U256> {
fn into_substrate_balance(value: EvmBalance) -> Option<SubstrateBalance> {
value
.into_u256()
.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)
Some(SubstrateBalance::new(substrate_value))
} else {
None
}
Expand Down
118 changes: 84 additions & 34 deletions frame/evm/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -950,14 +950,14 @@ impl<T: Config> Pallet<T> {
let nonce = frame_system::Pallet::<T>::account_nonce(&account_id);
let balance =
T::Currency::reducible_balance(&account_id, Preservation::Preserve, Fortitude::Polite);
let balance_u256 = U256::from(UniqueSaturatedInto::<u128>::unique_saturated_into(balance));
let balance_sub = SubstrateBalance::from(UniqueSaturatedInto::<u128>::unique_saturated_into(balance));
let balance_eth =
T::BalanceConverter::into_evm_balance(balance_u256).unwrap_or(U256::from(0));
T::BalanceConverter::into_evm_balance(balance_sub).unwrap_or(EvmBalance::from(0));

(
Account {
nonce: U256::from(UniqueSaturatedInto::<u128>::unique_saturated_into(nonce)),
balance: balance_eth,
balance: balance_eth.into(),
},
T::DbWeight::get().reads(2),
)
Expand All @@ -979,7 +979,7 @@ pub trait OnChargeEVMTransaction<T: Config> {

/// Before the transaction is executed the payment of the transaction fees
/// need to be secured.
fn withdraw_fee(who: &H160, fee: U256) -> Result<Self::LiquidityInfo, Error<T>>;
fn withdraw_fee(who: &H160, fee: EvmBalance) -> Result<Self::LiquidityInfo, Error<T>>;

/// After the transaction was executed the actual fee can be calculated.
/// This function should refund any overpaid fees and optionally deposit
Expand All @@ -988,8 +988,8 @@ pub trait OnChargeEVMTransaction<T: Config> {
/// Returns the `NegativeImbalance` - if any - produced by the priority fee.
fn correct_and_deposit_fee(
who: &H160,
corrected_fee: U256,
base_fee: U256,
corrected_fee: EvmBalance,
base_fee: EvmBalance,
already_withdrawn: Self::LiquidityInfo,
) -> Self::LiquidityInfo;

Expand Down Expand Up @@ -1021,8 +1021,8 @@ where
// Kept type as Option to satisfy bound of Default
type LiquidityInfo = Option<NegativeImbalanceOf<C, T>>;

fn withdraw_fee(who: &H160, fee: U256) -> Result<Self::LiquidityInfo, Error<T>> {
if fee.is_zero() {
fn withdraw_fee(who: &H160, fee: EvmBalance) -> Result<Self::LiquidityInfo, Error<T>> {
if fee.0.is_zero() {
return Ok(None);
}
let account_id = T::AddressMapping::into_account_id(*who);
Expand All @@ -1033,7 +1033,7 @@ where

let imbalance = C::withdraw(
&account_id,
fee_sub.unique_saturated_into(),
fee_sub.0.unique_saturated_into(),
WithdrawReasons::FEE,
ExistenceRequirement::AllowDeath,
)
Expand All @@ -1043,21 +1043,21 @@ where

fn correct_and_deposit_fee(
who: &H160,
corrected_fee: U256,
base_fee: U256,
corrected_fee: EvmBalance,
base_fee: EvmBalance,
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));
T::BalanceConverter::into_substrate_balance(corrected_fee).unwrap_or(SubstrateBalance::from(0));

// Calculate how much refund we should return
let refund_amount = paid
.peek()
.saturating_sub(corrected_fee_sub.unique_saturated_into());
.saturating_sub(corrected_fee_sub.0.unique_saturated_into());

// refund to the account that paid the fees. If this fails, the
// account might have dropped below the existential balance. In
Expand Down Expand Up @@ -1091,9 +1091,9 @@ where

// Convert base fee into substrate balance
let base_fee_sub =
T::BalanceConverter::into_substrate_balance(base_fee).unwrap_or(U256::from(0));
T::BalanceConverter::into_substrate_balance(base_fee).unwrap_or(SubstrateBalance::from(0));

let (base_fee, tip) = adjusted_paid.split(base_fee_sub.unique_saturated_into());
let (base_fee, tip) = adjusted_paid.split(base_fee_sub.0.unique_saturated_into());
// Handle base fee. Can be either burned, rationed, etc ...
OU::on_unbalanced(base_fee);
return Some(tip); // Returns substrate balance
Expand Down Expand Up @@ -1128,8 +1128,8 @@ where
// Kept type as Option to satisfy bound of Default
type LiquidityInfo = Option<Credit<T::AccountId, F>>;

fn withdraw_fee(who: &H160, fee: U256) -> Result<Self::LiquidityInfo, Error<T>> {
if fee.is_zero() {
fn withdraw_fee(who: &H160, fee: EvmBalance) -> Result<Self::LiquidityInfo, Error<T>> {
if fee.0.is_zero() {
return Ok(None);
}
let account_id = T::AddressMapping::into_account_id(*who);
Expand All @@ -1140,7 +1140,7 @@ where

let imbalance = F::withdraw(
&account_id,
fee_sub.unique_saturated_into(),
fee_sub.0.unique_saturated_into(),
Precision::Exact,
Preservation::Preserve,
Fortitude::Polite,
Expand All @@ -1151,21 +1151,21 @@ where

fn correct_and_deposit_fee(
who: &H160,
corrected_fee: U256,
base_fee: U256,
corrected_fee: EvmBalance,
base_fee: EvmBalance,
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));
T::BalanceConverter::into_substrate_balance(corrected_fee).unwrap_or(SubstrateBalance::from(0));

// Calculate how much refund we should return
let refund_amount = paid
.peek()
.saturating_sub(corrected_fee_sub.unique_saturated_into());
.saturating_sub(corrected_fee_sub.0.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::<T::AccountId, F>::zero());
Expand All @@ -1178,9 +1178,9 @@ where

// Convert base fee into substrate balance
let base_fee_sub =
T::BalanceConverter::into_substrate_balance(base_fee).unwrap_or(U256::from(0));
T::BalanceConverter::into_substrate_balance(base_fee).unwrap_or(SubstrateBalance::from(0));

let (base_fee, tip) = adjusted_paid.split(base_fee_sub.unique_saturated_into());
let (base_fee, tip) = adjusted_paid.split(base_fee_sub.0.unique_saturated_into());
// Handle base fee. Can be either burned, rationed, etc ...
OU::on_unbalanced(base_fee);
return Some(tip); // Returns substrate balance
Expand Down Expand Up @@ -1210,14 +1210,14 @@ where
// Kept type as Option to satisfy bound of Default
type LiquidityInfo = Option<Credit<T::AccountId, T::Currency>>;

fn withdraw_fee(who: &H160, fee: U256) -> Result<Self::LiquidityInfo, Error<T>> {
fn withdraw_fee(who: &H160, fee: EvmBalance) -> Result<Self::LiquidityInfo, Error<T>> {
EVMFungibleAdapter::<T::Currency, ()>::withdraw_fee(who, fee)
}

fn correct_and_deposit_fee(
who: &H160,
corrected_fee: U256,
base_fee: U256,
corrected_fee: EvmBalance,
base_fee: EvmBalance,
already_withdrawn: Self::LiquidityInfo,
) -> Self::LiquidityInfo {
<EVMFungibleAdapter<T::Currency, ()> as OnChargeEVMTransaction<T>>::correct_and_deposit_fee(
Expand Down Expand Up @@ -1250,22 +1250,72 @@ impl<T> OnCreate<T> for Tuple {
}
}

#[derive(Clone, Copy)]
pub struct SubstrateBalance(U256);

impl SubstrateBalance {
pub fn new(value: U256) -> Self {
SubstrateBalance(value)
}

pub fn into_u256(self) -> U256 {
self.0
}
}

impl From<u128> for SubstrateBalance {
fn from(value: u128) -> Self {
SubstrateBalance(U256::from(value))
}
}

impl From<SubstrateBalance> for U256 {
fn from(value: SubstrateBalance) -> Self {
value.0
}
}

#[derive(Clone, Copy)]
pub struct EvmBalance(U256);

impl EvmBalance {
pub fn new(value: U256) -> Self {
EvmBalance(value)
}

pub fn into_u256(self) -> U256 {
self.0
}
}

impl From<u128> for EvmBalance {
fn from(value: u128) -> Self {
EvmBalance(U256::from(value))
}
}

impl From<EvmBalance> for U256 {
fn from(value: EvmBalance) -> Self {
value.0
}
}

pub trait BalanceConverter {
/// Convert from Substrate balance to EVM balance (U256) with correct decimals
fn into_evm_balance(value: U256) -> Option<U256>;
fn into_evm_balance(value: SubstrateBalance) -> Option<EvmBalance>;

/// Convert from EVM (U256) balance to Substrate balance with correct decimals
fn into_substrate_balance(value: U256) -> Option<U256>;
fn into_substrate_balance(value: EvmBalance) -> Option<SubstrateBalance>;
}

impl BalanceConverter for () {
fn into_evm_balance(value: U256) -> Option<U256> {
Some(U256::from(
UniqueSaturatedInto::<u128>::unique_saturated_into(value),
fn into_evm_balance(value: SubstrateBalance) -> Option<EvmBalance> {
Some(EvmBalance::from(
UniqueSaturatedInto::<u128>::unique_saturated_into(value.0),
))
}

fn into_substrate_balance(value: U256) -> Option<U256> {
Some(value)
fn into_substrate_balance(value: EvmBalance) -> Option<SubstrateBalance> {
Some(SubstrateBalance(value.0))
}
}
Loading