CVE-2022-31111 (Rust, published 2022-07-06T18:15Z)
Description: value: Frontier is Substrate's Ethereum compatibility layer. In affected versions the truncation done when converting between EVM balance type and Substrate balance type was incorrectly implemented. This leads to possible discrepancy between appeared EVM transfer value and actual Substrate value transferred. It is recommended that an emergency upgrade to be planned and EVM execution temporarily paused in the mean time. The issue is patched in Frontier master branch commit fed5e0a9577c10bea021721e8c2c5c378e16bf66 and polkadot-v0.9.22 branch commit e3e427fa2e5d1200a784679f8015d4774cedc934. This vulnerability affects only EVM internal states, but not Substrate balance states or node. You can temporarily pause EVM execution (by setting up a Substrate `CallFilter` that disables `pallet-evm` and `pallet-ethereum` calls before the patch can be applied.
Severity: MEDIUM (CVSS v3 base score: 5.3)
Weakness: CWE-670 \u2014 Always-Incorrect Control Flow Implementation
The code contains a control flow path that does not reflect the algorithm that the path is intended to implement, leading to incorrect behavior any time this path is navigated.
Repository: https://github.com/paritytech/frontier
Files changed:
frame/ethereum/src/lib.rs
frame/evm/src/lib.rs
frame/evm/src/runner/stack.rs
frame/evm/src/tests.rs
primitives/evm/src/validation.rs
template/runtime/src/lib.rs
Commit message: Limit number of iterations in genesis nonce building (#753)



Vulnerable code:
					gas_limit.low_u64(),
					gas_limit.low_u64(),
use sp_std::vec::Vec;
	impl<T: Config> GenesisBuild<T> for GenesisConfig {
				for _ in 0..account.nonce.low_u128() {
				T::Currency::deposit_creating(
					&account_id,
					account.balance.low_u128().unique_saturated_into(),
				);
			fee.low_u128().unique_saturated_into(),
				.saturating_sub(corrected_fee.low_u128().unique_saturated_into());
			let (base_fee, tip) = adjusted_paid.split(base_fee.low_u128().unique_saturated_into());
		Imbalance<<T::Currency as Currency<<T as frame_system::Config>::AccountId>>::Balance, Opposite = <T::Currency as Currency<<T as frame_system::Config>::AccountId>>::PositiveImbalance>, {
	runner::Runner as RunnerT, AccountCodes, AccountStorages, AddressMapping, BlockHashMapping,
	Config, Error, Event, FeeCalculator, OnChargeEVMTransaction, Pallet, RunnerError,
impl<T: Config> Runner<T> {
impl<T: Config> RunnerT<T> for Runner<T> {
			transfer.value.low_u128().unique_saturated_into(),
		let (base_fee, _) = <Test as Config>::FeeCalculator::min_gas_price();
		assert_eq!(after_tip, (before_tip - (base_fee.low_u64() * 21_000)));
		assert_eq!(after_tip, (before_tip + actual_tip.low_u128()));
			self.transaction.gas_limit.low_u64(),
		IdentifyAccount, NumberFor, PostDispatchInfoOf, Verify,
				gas_limit.low_u64(),
				gas_limit.low_u64(),

Fixed code:
					gas_limit.unique_saturated_into(),
					gas_limit.unique_saturated_into(),
use sp_std::{cmp::min, vec::Vec};
	impl<T: Config> GenesisBuild<T> for GenesisConfig
	where
		U256: UniqueSaturatedInto<BalanceOf<T>>,
	{
			const MAX_ACCOUNT_NONCE: usize = 100;

				for _ in 0..min(
					MAX_ACCOUNT_NONCE,
					UniqueSaturatedInto::<usize>::unique_saturated_into(account.nonce),
				) {
				T::Currency::deposit_creating(&account_id, account.balance.unique_saturated_into());
	U256: UniqueSaturatedInto<<C as Currency<<T as frame_system::Config>::AccountId>>::Balance>,
			fee.unique_saturated_into(),
				.saturating_sub(corrected_fee.unique_saturated_into());
			let (base_fee, tip) = adjusted_paid.split(base_fee.unique_saturated_into());
Imbalance<<T::Currency as Currency<<T as frame_system::Config>::AccountId>>::Balance, Opposite = <T::Currency as Currency<<T as frame_system::Config>::AccountId>>::PositiveImbalance>,
U256: UniqueSaturatedInto<BalanceOf<T>>,

{
	runner::Runner as RunnerT, AccountCodes, AccountStorages, AddressMapping, BalanceOf,
	BlockHashMapping, Config, Error, Event, FeeCalculator, OnChargeEVMTransaction, Pallet,
	RunnerError,
impl<T: Config> Runner<T>
where
	BalanceOf<T>: TryFrom<U256> + Into<U256>,
{
impl<T: Config> RunnerT<T> for Runner<T>
where
	BalanceOf<T>: TryFrom<U256> + Into<U256>,
{
where
	BalanceOf<T>: TryFrom<U256> + Into<U256>,
			transfer
				.value
				.try_into()
				.map_err(|_| ExitError::OutOfFund)?,
		let base_fee: u64 = <Test as Config>::FeeCalculator::min_gas_price()
			.0
			.unique_saturated_into();
		assert_eq!(after_tip, (before_tip - (base_fee * 21_000)));
		assert_eq!(after_tip, (before_tip + actual_tip));
use frame_support::sp_runtime::traits::UniqueSaturatedInto;
			self.transaction.gas_limit.unique_saturated_into(),
		IdentifyAccount, NumberFor, PostDispatchInfoOf, UniqueSaturatedInto, Verify,
				gas_limit.unique_saturated_into(),
				gas_limit.unique_saturated_into(),