pallet_hotfix_sufficients/
lib.rs

1// This file is part of Frontier.
2
3// Copyright (C) Parity Technologies (UK) Ltd.
4// SPDX-License-Identifier: Apache-2.0
5
6// Licensed under the Apache License, Version 2.0 (the "License");
7// you may not use this file except in compliance with the License.
8// You may obtain a copy of the License at
9//
10// 	http://www.apache.org/licenses/LICENSE-2.0
11//
12// Unless required by applicable law or agreed to in writing, software
13// distributed under the License is distributed on an "AS IS" BASIS,
14// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15// See the License for the specific language governing permissions and
16// limitations under the License.
17
18#![cfg_attr(not(feature = "std"), no_std)]
19#![warn(unused_crate_dependencies)]
20#![allow(clippy::useless_conversion)]
21
22extern crate alloc;
23
24#[cfg(feature = "runtime-benchmarks")]
25pub mod benchmarking;
26#[cfg(test)]
27mod mock;
28#[cfg(test)]
29mod tests;
30pub mod weights;
31
32use alloc::vec::Vec;
33// Substrate
34use frame_support::dispatch::PostDispatchInfo;
35use sp_core::H160;
36use sp_runtime::traits::Zero;
37// Frontier
38pub use pallet_evm::AddressMapping;
39
40pub use self::{pallet::*, weights::WeightInfo};
41
42#[frame_support::pallet]
43pub mod pallet {
44	use super::*;
45	use frame_support::pallet_prelude::*;
46	use frame_system::pallet_prelude::*;
47
48	#[pallet::pallet]
49	pub struct Pallet<T>(PhantomData<T>);
50
51	#[pallet::config]
52	pub trait Config: frame_system::Config {
53		/// Mapping from address to account id.
54		type AddressMapping: AddressMapping<Self::AccountId>;
55		/// Weight information for extrinsics in this pallet.
56		type WeightInfo: WeightInfo;
57	}
58
59	#[pallet::error]
60	pub enum Error<T> {
61		/// Maximum address count exceeded
62		MaxAddressCountExceeded,
63	}
64
65	#[pallet::call]
66	impl<T: Config> Pallet<T> {
67		/// Increment `sufficients` for existing accounts having a nonzero `nonce` but zero `sufficients`, `consumers` and `providers` value.
68		/// This state was caused by a previous bug in EVM create account dispatchable.
69		///
70		/// Any accounts in the input list not satisfying the above condition will remain unaffected.
71		#[pallet::call_index(0)]
72		#[pallet::weight(
73			<T as pallet::Config>::WeightInfo::hotfix_inc_account_sufficients(addresses.len().try_into().unwrap_or(u32::MAX))
74		)]
75		pub fn hotfix_inc_account_sufficients(
76			origin: OriginFor<T>,
77			addresses: Vec<H160>,
78		) -> DispatchResultWithPostInfo {
79			const MAX_ADDRESS_COUNT: usize = 1000;
80
81			frame_system::ensure_signed(origin)?;
82			ensure!(
83				addresses.len() <= MAX_ADDRESS_COUNT,
84				Error::<T>::MaxAddressCountExceeded
85			);
86
87			for address in addresses {
88				let account_id = T::AddressMapping::into_account_id(address);
89				let nonce = frame_system::Pallet::<T>::account_nonce(&account_id);
90				let refs = frame_system::Pallet::<T>::consumers(&account_id)
91					.saturating_add(frame_system::Pallet::<T>::providers(&account_id))
92					.saturating_add(frame_system::Pallet::<T>::sufficients(&account_id));
93
94				if !nonce.is_zero() && refs.is_zero() {
95					frame_system::Pallet::<T>::inc_sufficients(&account_id);
96				}
97			}
98
99			Ok(PostDispatchInfo {
100				actual_weight: None,
101				pays_fee: Pays::Yes,
102			})
103		}
104	}
105}