pallet_moonbeam_lazy_migrations/
lib.rs

1// Copyright 2024 Moonbeam foundation
2// This file is part of Moonbeam.
3
4// Moonbeam is free software: you can redistribute it and/or modify
5// it under the terms of the GNU General Public License as published by
6// the Free Software Foundation, either version 3 of the License, or
7// (at your option) any later version.
8
9// Moonbeam is distributed in the hope that it will be useful,
10// but WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12// GNU General Public License for more details.
13
14// You should have received a copy of the GNU General Public License
15// along with Moonbeam.  If not, see <http://www.gnu.org/licenses/>.
16
17//! # Lazy Migration Pallet
18//!
19//! An empty pallet reserved for future migrations.
20
21#![allow(non_camel_case_types)]
22#![cfg_attr(not(feature = "std"), no_std)]
23
24#[cfg(test)]
25pub mod mock;
26
27#[cfg(test)]
28mod tests;
29
30// #[cfg(any(test, feature = "runtime-benchmarks"))]
31// mod benchmarks;
32
33pub mod weights;
34pub use weights::WeightInfo;
35
36use frame_support::pallet;
37use frame_support::pallet_prelude::*;
38use frame_system::pallet_prelude::*;
39pub use pallet::*;
40
41const MAX_CONTRACT_CODE_SIZE: u64 = 25 * 1024;
42
43#[pallet]
44pub mod pallet {
45
46	use super::*;
47	use sp_core::H160;
48
49	/// Pallet for multi block migrations
50	#[pallet::pallet]
51	pub struct Pallet<T>(PhantomData<T>);
52
53	/// Configuration trait of this pallet.
54	#[pallet::config]
55	pub trait Config: frame_system::Config + pallet_evm::Config {
56		type WeightInfo: WeightInfo;
57	}
58
59	#[pallet::error]
60	pub enum Error<T> {
61		/// The contract already have metadata
62		ContractMetadataAlreadySet,
63		/// Contract not exist
64		ContractNotExist,
65	}
66
67	#[pallet::call]
68	impl<T: Config> Pallet<T>
69	where
70		<T as frame_system::Config>::AccountId: Into<H160> + From<H160>,
71	{
72		#[pallet::call_index(2)]
73		#[pallet::weight(Pallet::<T>::create_contract_metadata_weight(MAX_CONTRACT_CODE_SIZE))]
74		pub fn create_contract_metadata(
75			origin: OriginFor<T>,
76			address: H160,
77		) -> DispatchResultWithPostInfo {
78			ensure_signed(origin)?;
79
80			ensure!(
81				pallet_evm::AccountCodesMetadata::<T>::get(address).is_none(),
82				Error::<T>::ContractMetadataAlreadySet
83			);
84
85			// Ensure contract exist
86			let code = pallet_evm::AccountCodes::<T>::get(address);
87			ensure!(!code.is_empty(), Error::<T>::ContractNotExist);
88
89			// Construct metadata
90			let code_size = code.len() as u64;
91			let code_hash = sp_core::H256::from(sp_io::hashing::keccak_256(&code));
92			let meta = pallet_evm::CodeMetadata {
93				size: code_size,
94				hash: code_hash,
95			};
96
97			// Set metadata
98			pallet_evm::AccountCodesMetadata::<T>::insert(address, meta);
99
100			Ok((
101				Some(Self::create_contract_metadata_weight(code_size)),
102				Pays::No,
103			)
104				.into())
105		}
106	}
107
108	impl<T: Config> Pallet<T> {
109		fn create_contract_metadata_weight(code_size: u64) -> Weight {
110			// max entry size of AccountCodesMetadata (full key + value)
111			const PROOF_SIZE_CODE_METADATA: u64 = 100;
112			// intermediates nodes might be up to 3Kb
113			const PROOF_SIZE_INTERMEDIATES_NODES: u64 = 3 * 1024;
114
115			// Account for 2 reads, 1 write
116			<T as frame_system::Config>::DbWeight::get()
117				.reads_writes(2, 1)
118				.set_proof_size(
119					code_size + (PROOF_SIZE_INTERMEDIATES_NODES * 2) + PROOF_SIZE_CODE_METADATA,
120				)
121		}
122	}
123}