Skip to content

Commit

Permalink
Add lazy migration to set evm contract metadata (#2919)
Browse files Browse the repository at this point in the history
* add lazy migration create_contract_metadata

* test lazy migration create_contract_metadata

* update frontier pin

* fix rust tests

* fix rust tests

* update Cargo.lock

---------

Co-authored-by: Rodrigo Quelhas <[email protected]>
  • Loading branch information
librelois and RomarQ authored Sep 11, 2024
1 parent 3398a8f commit 9c821e2
Show file tree
Hide file tree
Showing 4 changed files with 127 additions and 29 deletions.
53 changes: 26 additions & 27 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 0 additions & 1 deletion pallets/moonbeam-lazy-migrations/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ log = {workspace = true}
frame-support = {workspace = true}
frame-system = {workspace = true}
pallet-scheduler = {workspace = true}
pallet-assets = {workspace = true}
pallet-balances = {workspace = true}
parity-scale-codec = {workspace = true}
scale-info = {workspace = true, features = ["derive"]}
Expand Down
56 changes: 56 additions & 0 deletions pallets/moonbeam-lazy-migrations/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ use frame_support::pallet;

pub use pallet::*;

const MAX_CONTRACT_CODE_SIZE: u64 = 25 * 1024;

#[pallet]
pub mod pallet {
use super::*;
Expand Down Expand Up @@ -65,6 +67,10 @@ pub mod pallet {
AddressesLengthCannotBeZero,
/// The contract is not corrupted (Still exist or properly suicided)
ContractNotCorrupted,
/// The contract already have metadata
ContractMetadataAlreadySet,
/// Contract not exist
ContractNotExist,
}

#[pallet::call]
Expand Down Expand Up @@ -124,5 +130,55 @@ pub mod pallet {
}
Ok(Pays::No.into())
}
#[pallet::call_index(2)]
#[pallet::weight(Pallet::<T>::create_contract_metadata_weight(MAX_CONTRACT_CODE_SIZE))]
pub fn create_contract_metadata(
origin: OriginFor<T>,
address: H160,
) -> DispatchResultWithPostInfo {
ensure_signed(origin)?;

ensure!(
pallet_evm::AccountCodesMetadata::<T>::get(address).is_none(),
Error::<T>::ContractMetadataAlreadySet
);

// Ensure contract exist
let code = pallet_evm::AccountCodes::<T>::get(address);
ensure!(!code.is_empty(), Error::<T>::ContractNotExist);

// Construct metadata
let code_size = code.len() as u64;
let code_hash = sp_core::H256::from(sp_io::hashing::keccak_256(&code));
let meta = pallet_evm::CodeMetadata {
size: code_size,
hash: code_hash,
};

// Set metadata
pallet_evm::AccountCodesMetadata::<T>::insert(address, meta);

Ok((
Some(Self::create_contract_metadata_weight(code_size)),
Pays::No,
)
.into())
}
}

impl<T: Config> Pallet<T> {
fn create_contract_metadata_weight(code_size: u64) -> Weight {
// max entry size of AccountCodesMetadata (full key + value)
const PROOF_SIZE_CODE_METADATA: u64 = 100;
// intermediates nodes might be up to 3Kb
const PROOF_SIZE_INTERMEDIATES_NODES: u64 = 3 * 1024;

// Account for 2 reads, 1 write
<T as frame_system::Config>::DbWeight::get()
.reads_writes(2, 1)
.set_proof_size(
code_size + (PROOF_SIZE_INTERMEDIATES_NODES * 2) + PROOF_SIZE_CODE_METADATA,
)
}
}
}
46 changes: 45 additions & 1 deletion pallets/moonbeam-lazy-migrations/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ use {
mock::{ExtBuilder, LazyMigrations, RuntimeOrigin, Test},
Error,
},
frame_support::assert_noop,
frame_support::{assert_noop, assert_ok},
rlp::RlpStream,
sp_core::{H160, H256},
sp_io::hashing::keccak_256,
Expand Down Expand Up @@ -64,6 +64,13 @@ fn mock_contract_with_entries(seed: u8, nonce: u64, num_entries: u32) -> H160 {
contract_address
}

fn create_dummy_contract_without_metadata(seed: u8) -> H160 {
let address = address_build(seed);
let dummy_code = vec![1, 2, 3];
pallet_evm::AccountCodes::<Test>::insert(address, dummy_code);
address
}

#[test]
fn test_clear_suicided_contract_succesfull() {
ExtBuilder::default().build().execute_with(|| {
Expand Down Expand Up @@ -263,3 +270,40 @@ fn test_clear_suicided_mixed_suicided_and_non_suicided() {
);
})
}

#[test]
fn test_create_contract_metadata_contract_not_exist() {
ExtBuilder::default().build().execute_with(|| {
assert_noop!(
LazyMigrations::create_contract_metadata(
RuntimeOrigin::signed(AccountId32::from([45; 32])),
address_build(1),
),
Error::<Test>::ContractNotExist
);
});
}

#[test]
fn test_create_contract_metadata_success_path() {
ExtBuilder::default().build().execute_with(|| {
// Setup: create a dummy contract
let address = create_dummy_contract_without_metadata(1);

assert_ok!(LazyMigrations::create_contract_metadata(
RuntimeOrigin::signed(AccountId32::from([45; 32])),
address,
));

assert!(pallet_evm::AccountCodesMetadata::<Test>::get(address).is_some());

// Should not be able to set metadata again
assert_noop!(
LazyMigrations::create_contract_metadata(
RuntimeOrigin::signed(AccountId32::from([45; 32])),
address,
),
Error::<Test>::ContractMetadataAlreadySet
);
});
}

0 comments on commit 9c821e2

Please sign in to comment.