diff --git a/frame/evm/Cargo.toml b/frame/evm/Cargo.toml index 61e577346c..cfa4e476dc 100644 --- a/frame/evm/Cargo.toml +++ b/frame/evm/Cargo.toml @@ -73,3 +73,4 @@ try-runtime = [ "frame-system/try-runtime", ] forbid-evm-reentrancy = ["dep:environmental"] +dbc-adaptor = [] diff --git a/frame/evm/src/lib.rs b/frame/evm/src/lib.rs index fb3a0388f8..214637e489 100644 --- a/frame/evm/src/lib.rs +++ b/frame/evm/src/lib.rs @@ -107,6 +107,33 @@ pub use self::{ weights::WeightInfo, }; +#[cfg(feature = "dbc-adaptor")] +pub const CHAINS_VALUE_ADAPTOR: u128 = 1000; + +pub fn dbc_value_expand(origin: U256) -> U256 { + #[cfg(feature = "dbc-adaptor")] + { + origin.saturating_mul(U256::from(CHAINS_VALUE_ADAPTOR)) + } + #[cfg(not(feature = "dbc-adaptor"))] + { + origin + } +} + +pub fn dbc_value_shrink(origin: U256) -> U256 { + #[cfg(feature = "dbc-adaptor")] + { + origin + .checked_div(U256::from(CHAINS_VALUE_ADAPTOR)) + .expect("divisor is non-zero; qed") + } + #[cfg(not(feature = "dbc-adaptor"))] + { + origin + } +} + #[frame_support::pallet] pub mod pallet { use super::*; @@ -857,7 +884,9 @@ impl Pallet { ( Account { nonce: U256::from(UniqueSaturatedInto::::unique_saturated_into(nonce)), - balance: U256::from(UniqueSaturatedInto::::unique_saturated_into(balance)), + balance: dbc_value_expand(U256::from( + UniqueSaturatedInto::::unique_saturated_into(balance), + )), }, T::DbWeight::get().reads(2), ) diff --git a/frame/evm/src/runner/stack.rs b/frame/evm/src/runner/stack.rs index 7af212593a..97e84f10bd 100644 --- a/frame/evm/src/runner/stack.rs +++ b/frame/evm/src/runner/stack.rs @@ -17,6 +17,8 @@ //! EVM stack-based runner. +#[cfg(feature = "dbc-adaptor")] +use crate::{dbc_value_expand, dbc_value_shrink}; use evm::{ backend::Backend as BackendT, executor::stack::{Accessed, StackExecutor, StackState as StackStateT, StackSubstateMetadata}, @@ -25,6 +27,7 @@ use evm::{ }; // Substrate use frame_support::{ + ensure, traits::{ tokens::{currency::Currency, ExistenceRequirement}, Get, Time, @@ -233,7 +236,7 @@ where })?; // Deduct fee from the `source` account. Returns `None` if `total_fee` is Zero. - let fee = T::OnChargeTransaction::withdraw_fee(&source, total_fee) + let fee = T::OnChargeTransaction::withdraw_fee(&source, dbc_value_shrink(total_fee)) .map_err(|e| RunnerError { error: e, weight })?; // Execute the EVM call. @@ -301,9 +304,9 @@ where let actual_priority_fee = T::OnChargeTransaction::correct_and_deposit_fee( &source, // Actual fee after evm execution, including tip. - actual_fee, + dbc_value_shrink(actual_fee), // Base fee. - actual_base_fee, + dbc_value_shrink(actual_base_fee), // Fee initially withdrawn. fee, ); @@ -906,13 +909,19 @@ where fn transfer(&mut self, transfer: Transfer) -> Result<(), ExitError> { let source = T::AddressMapping::into_account_id(transfer.source); let target = T::AddressMapping::into_account_id(transfer.target); + + let value = dbc_value_shrink(transfer.value); + ensure!( + dbc_value_expand(value) == transfer.value, + ExitError::Other(sp_std::borrow::Cow::Borrowed( + "DBC value must end with 3 zeros due to 15 decimal precision" + )) + ); + T::Currency::transfer( &source, &target, - transfer - .value - .try_into() - .map_err(|_| ExitError::OutOfFund)?, + value.try_into().map_err(|_| ExitError::OutOfFund)?, ExistenceRequirement::AllowDeath, ) .map_err(|_| ExitError::OutOfFund) diff --git a/template/runtime/Cargo.toml b/template/runtime/Cargo.toml index ad52167e55..8f70cdfef6 100644 --- a/template/runtime/Cargo.toml +++ b/template/runtime/Cargo.toml @@ -51,7 +51,7 @@ fp-self-contained = { workspace = true } pallet-base-fee = { workspace = true } pallet-dynamic-fee = { workspace = true } pallet-ethereum = { workspace = true } -pallet-evm = { workspace = true } +pallet-evm = { workspace = true, features = ["dbc-adaptor"] } pallet-evm-chain-id = { workspace = true } pallet-evm-precompile-modexp = { workspace = true } pallet-evm-precompile-sha3fips = { workspace = true }