pallet_evm_tracker/
lib.rs#![cfg_attr(not(feature = "std"), no_std)]
#[cfg(not(feature = "std"))]
extern crate alloc;
pub mod check_nonce;
pub mod create_contract;
pub mod traits;
pub use check_nonce::CheckNonce;
use domain_runtime_primitives::EthereumAccountId;
pub use pallet::*;
use sp_core::U256;
use sp_domains::PermissionedActionAllowedBy;
#[frame_support::pallet]
mod pallet {
use domain_runtime_primitives::EthereumAccountId;
use frame_support::pallet_prelude::*;
use frame_system::pallet_prelude::*;
use sp_core::U256;
use sp_domains::PermissionedActionAllowedBy;
use sp_evm_tracker::{InherentError, InherentType, INHERENT_IDENTIFIER};
#[pallet::config]
pub trait Config: frame_system::Config {}
#[pallet::storage]
pub(super) type AccountNonce<T: Config> =
StorageMap<_, Identity, T::AccountId, U256, OptionQuery>;
#[pallet::storage]
pub(super) type ContractCreationAllowedBy<T: Config> = StorageValue<
_,
PermissionedActionAllowedBy<EthereumAccountId>,
ValueQuery,
DefaultToAnyone,
>;
pub struct DefaultToAnyone;
impl Get<PermissionedActionAllowedBy<EthereumAccountId>> for DefaultToAnyone {
fn get() -> PermissionedActionAllowedBy<EthereumAccountId> {
PermissionedActionAllowedBy::Anyone
}
}
#[pallet::pallet]
#[pallet::without_storage_info]
pub struct Pallet<T>(_);
#[pallet::call]
impl<T: Config> Pallet<T> {
#[pallet::call_index(0)]
#[pallet::weight((T::DbWeight::get().reads_writes(0, 1), DispatchClass::Mandatory))]
pub fn set_contract_creation_allowed_by(
origin: OriginFor<T>,
contract_creation_allowed_by: PermissionedActionAllowedBy<EthereumAccountId>,
) -> DispatchResult {
ensure_none(origin)?;
ContractCreationAllowedBy::<T>::put(contract_creation_allowed_by);
Ok(())
}
}
#[pallet::inherent]
impl<T: Config> ProvideInherent for Pallet<T> {
type Call = Call<T>;
type Error = InherentError;
const INHERENT_IDENTIFIER: InherentIdentifier = INHERENT_IDENTIFIER;
fn create_inherent(data: &InherentData) -> Option<Self::Call> {
let inherent_data = data
.get_data::<InherentType>(&INHERENT_IDENTIFIER)
.expect("EVM tracker inherent data not correctly encoded")
.expect("EVM tracker inherent data must be provided");
inherent_data
.maybe_call
.map(
|contract_creation_allowed_by| Call::set_contract_creation_allowed_by {
contract_creation_allowed_by,
},
)
}
fn is_inherent_required(data: &InherentData) -> Result<Option<Self::Error>, Self::Error> {
let inherent_data = data
.get_data::<InherentType>(&INHERENT_IDENTIFIER)
.expect("EVM tracker inherent data not correctly encoded")
.expect("EVM tracker inherent data must be provided");
Ok(inherent_data
.maybe_call
.map(|_encoded_call| InherentError::MissingRuntimeCall))
}
fn check_inherent(call: &Self::Call, data: &InherentData) -> Result<(), Self::Error> {
let maybe_provided_call = Self::create_inherent(data);
if let Some(provided_call) = maybe_provided_call {
if Self::is_inherent(call) && call != &provided_call {
return Err(InherentError::IncorrectRuntimeCall);
}
} else {
return Err(InherentError::MissingRuntimeCall);
}
Ok(())
}
fn is_inherent(call: &Self::Call) -> bool {
matches!(call, Call::set_contract_creation_allowed_by { .. })
}
}
#[pallet::hooks]
impl<T: Config> Hooks<BlockNumberFor<T>> for Pallet<T> {
fn on_finalize(_now: BlockNumberFor<T>) {
let _ = AccountNonce::<T>::clear(u32::MAX, None);
}
}
}
impl<T: Config> Pallet<T> {
pub fn account_nonce(account: T::AccountId) -> Option<U256> {
AccountNonce::<T>::get(account)
}
pub fn set_account_nonce(account: T::AccountId, nonce: U256) {
AccountNonce::<T>::set(account, Some(nonce))
}
pub fn is_allowed_to_create_contracts(signer: &EthereumAccountId) -> bool {
ContractCreationAllowedBy::<T>::get().is_allowed(signer)
}
pub fn is_allowed_to_create_unsigned_contracts() -> bool {
ContractCreationAllowedBy::<T>::get().is_anyone_allowed()
}
pub fn contract_creation_allowed_by() -> PermissionedActionAllowedBy<EthereumAccountId> {
ContractCreationAllowedBy::<T>::get()
}
}