pallet_evm_tracker/
lib.rs1#![cfg_attr(not(feature = "std"), no_std)]
19
20#[cfg(not(feature = "std"))]
21extern crate alloc;
22
23pub mod check_nonce;
24pub mod create_contract;
25pub mod fees;
26pub mod traits;
27
28pub use check_nonce::CheckNonce;
29use domain_runtime_primitives::EthereumAccountId;
30pub use pallet::*;
31use sp_core::U256;
32use sp_domains::PermissionedActionAllowedBy;
33
34#[frame_support::pallet]
35mod pallet {
36 use domain_runtime_primitives::EthereumAccountId;
37 use frame_support::pallet_prelude::*;
38 use frame_system::pallet_prelude::*;
39 use sp_core::U256;
40 use sp_domains::PermissionedActionAllowedBy;
41 use sp_evm_tracker::{InherentError, InherentType, INHERENT_IDENTIFIER};
42
43 #[pallet::config]
44 pub trait Config: frame_system::Config {}
45
46 #[pallet::storage]
50 pub(super) type AccountNonce<T: Config> =
51 StorageMap<_, Identity, T::AccountId, U256, OptionQuery>;
52
53 #[pallet::storage]
61 pub(super) type ContractCreationAllowedBy<T: Config> = StorageValue<
62 _,
63 PermissionedActionAllowedBy<EthereumAccountId>,
64 ValueQuery,
65 DefaultToAnyone,
66 >;
67
68 pub struct DefaultToAnyone;
70
71 impl Get<PermissionedActionAllowedBy<EthereumAccountId>> for DefaultToAnyone {
72 fn get() -> PermissionedActionAllowedBy<EthereumAccountId> {
73 PermissionedActionAllowedBy::Anyone
74 }
75 }
76
77 #[pallet::pallet]
79 #[pallet::without_storage_info]
80 pub struct Pallet<T>(_);
81
82 #[pallet::call]
83 impl<T: Config> Pallet<T> {
84 #[pallet::call_index(0)]
86 #[pallet::weight((T::DbWeight::get().reads_writes(0, 1), DispatchClass::Mandatory))]
87 pub fn set_contract_creation_allowed_by(
88 origin: OriginFor<T>,
89 contract_creation_allowed_by: PermissionedActionAllowedBy<EthereumAccountId>,
90 ) -> DispatchResult {
91 ensure_none(origin)?;
92
93 ContractCreationAllowedBy::<T>::put(contract_creation_allowed_by);
96
97 Ok(())
98 }
99 }
100
101 #[pallet::inherent]
102 impl<T: Config> ProvideInherent for Pallet<T> {
103 type Call = Call<T>;
104 type Error = InherentError;
105 const INHERENT_IDENTIFIER: InherentIdentifier = INHERENT_IDENTIFIER;
106
107 fn create_inherent(data: &InherentData) -> Option<Self::Call> {
108 let inherent_data = data
109 .get_data::<InherentType>(&INHERENT_IDENTIFIER)
110 .expect("EVM tracker inherent data not correctly encoded")
111 .expect("EVM tracker inherent data must be provided");
112
113 inherent_data
114 .maybe_call
115 .map(
116 |contract_creation_allowed_by| Call::set_contract_creation_allowed_by {
117 contract_creation_allowed_by,
118 },
119 )
120 }
121
122 fn is_inherent_required(data: &InherentData) -> Result<Option<Self::Error>, Self::Error> {
123 let inherent_data = data
124 .get_data::<InherentType>(&INHERENT_IDENTIFIER)
125 .expect("EVM tracker inherent data not correctly encoded")
126 .expect("EVM tracker inherent data must be provided");
127
128 Ok(inherent_data
129 .maybe_call
130 .map(|_encoded_call| InherentError::MissingRuntimeCall))
131 }
132
133 fn check_inherent(call: &Self::Call, data: &InherentData) -> Result<(), Self::Error> {
134 let maybe_provided_call = Self::create_inherent(data);
135
136 if let Some(provided_call) = maybe_provided_call {
137 if Self::is_inherent(call) && call != &provided_call {
138 return Err(InherentError::IncorrectRuntimeCall);
139 }
140 } else {
141 return Err(InherentError::MissingRuntimeCall);
142 }
143
144 Ok(())
145 }
146
147 fn is_inherent(call: &Self::Call) -> bool {
148 matches!(call, Call::set_contract_creation_allowed_by { .. })
149 }
150 }
151
152 #[pallet::hooks]
153 impl<T: Config> Hooks<BlockNumberFor<T>> for Pallet<T> {
154 fn on_finalize(_now: BlockNumberFor<T>) {
155 let _ = AccountNonce::<T>::clear(u32::MAX, None);
158 }
159 }
160}
161
162impl<T: Config> Pallet<T> {
163 pub fn account_nonce(account: T::AccountId) -> Option<U256> {
165 AccountNonce::<T>::get(account)
166 }
167
168 pub fn set_account_nonce(account: T::AccountId, nonce: U256) {
170 AccountNonce::<T>::set(account, Some(nonce))
171 }
172
173 pub fn is_allowed_to_create_contracts(signer: &EthereumAccountId) -> bool {
175 ContractCreationAllowedBy::<T>::get().is_allowed(signer)
176 }
177
178 pub fn is_allowed_to_create_unsigned_contracts() -> bool {
180 ContractCreationAllowedBy::<T>::get().is_anyone_allowed()
181 }
182
183 pub fn contract_creation_allowed_by() -> PermissionedActionAllowedBy<EthereumAccountId> {
186 ContractCreationAllowedBy::<T>::get()
187 }
188}