difftreelog
feat fake event injection
in: master
8 files changed
Cargo.lockdiffbeforeafterboth6038name = "pallet-evm-migration"6038name = "pallet-evm-migration"6039version = "0.1.1"6039version = "0.1.1"6040dependencies = [6040dependencies = [6041 "ethereum",6041 "fp-evm",6042 "fp-evm",6042 "frame-benchmarking",6043 "frame-benchmarking",6043 "frame-support",6044 "frame-support",pallets/evm-migration/Cargo.tomldiffbeforeafterboth8scale-info = { version = "2.0.1", default-features = false, features = [8scale-info = { version = "2.0.1", default-features = false, features = [9 "derive",9 "derive",10] }10] }11ethereum = { version = "0.12.0", default-features = false }11frame-support = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.30" }12frame-support = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.30" }12frame-system = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.30" }13frame-system = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.30" }13frame-benchmarking = { default-features = false, optional = true, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.30" }14frame-benchmarking = { default-features = false, optional = true, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.30" }pallets/evm-migration/src/benchmarking.rsdiffbeforeafterboth20use frame_benchmarking::benchmarks;20use frame_benchmarking::benchmarks;21use frame_system::RawOrigin;21use frame_system::RawOrigin;22use sp_core::{H160, H256};22use sp_core::{H160, H256};23use sp_std::vec::Vec;23use sp_std::{vec::Vec, vec};242425benchmarks! {25benchmarks! {26 where_clause { where <T as Config>::RuntimeEvent: codec::Encode }2726 begin {28 begin {27 }: _(RawOrigin::Root, H160::default())29 }: _(RawOrigin::Root, H160::default())46 <Pallet<T>>::begin(RawOrigin::Root.into(), address)?;48 <Pallet<T>>::begin(RawOrigin::Root.into(), address)?;47 }: _(RawOrigin::Root, address, data)49 }: _(RawOrigin::Root, address, data)5051 insert_eth_logs {52 let b in 0..200;53 let logs = (0..b).map(|_| ethereum::Log {54 address: H160([b as u8; 20]),55 data: vec![b as u8; 128],56 topics: vec![H256([b as u8; 32]); 6],57 }).collect::<Vec<_>>();58 }: _(RawOrigin::Root, logs)5960 insert_events {61 let b in 0..200;62 use codec::Encode;63 let logs = (0..b).map(|_| <T as Config>::RuntimeEvent::from(crate::Event::<T>::TestEvent).encode()).collect::<Vec<_>>();64 }: _(RawOrigin::Root, logs)48}65}4966pallets/evm-migration/src/lib.rsdiffbeforeafterboth252526#[frame_support::pallet]26#[frame_support::pallet]27pub mod pallet {27pub mod pallet {28 use frame_support::pallet_prelude::*;28 use frame_support::{29 pallet_prelude::{*, DispatchResult},30 traits::IsType,31 };29 use frame_system::pallet_prelude::*;32 use frame_system::pallet_prelude::{*, OriginFor};30 use sp_core::{H160, H256};33 use sp_core::{H160, H256};31 use sp_std::vec::Vec;34 use sp_std::vec::Vec;32 use super::weights::WeightInfo;35 use super::weights::WeightInfo;36 pub trait Config: frame_system::Config + pallet_evm::Config {39 pub trait Config: frame_system::Config + pallet_evm::Config {37 /// Weights40 /// Weights38 type WeightInfo: WeightInfo;41 type WeightInfo: WeightInfo;42 /// The overarching event type.43 type RuntimeEvent: From<Event<Self>> + IsType<<Self as frame_system::Config>::RuntimeEvent>;39 }44 }404541 type SelfWeightOf<T> = <T as Config>::WeightInfo;46 type SelfWeightOf<T> = <T as Config>::WeightInfo;44 #[pallet::generate_store(pub(super) trait Store)]49 #[pallet::generate_store(pub(super) trait Store)]45 pub struct Pallet<T>(_);50 pub struct Pallet<T>(_);5152 #[pallet::event]53 pub enum Event<T: Config> {54 /// This event is used in benchmarking and can be used for tests55 TestEvent,56 }465747 #[pallet::error]58 #[pallet::error]48 pub enum Error<T> {59 pub enum Error<T> {49 /// Can only migrate to empty address.60 /// Can only migrate to empty address.50 AccountNotEmpty,61 AccountNotEmpty,51 /// Migration of this account is not yet started, or already finished.62 /// Migration of this account is not yet started, or already finished.52 AccountIsNotMigrating,63 AccountIsNotMigrating,64 /// Failed to decode event bytes65 BadEvent,53 }66 }546755 #[pallet::storage]68 #[pallet::storage]108 Ok(())121 Ok(())109 }122 }123124 /// Create ethereum events attached to the fake transaction125 #[pallet::weight(<SelfWeightOf<T>>::insert_eth_logs(logs.len() as u32))]126 pub fn insert_eth_logs(origin: OriginFor<T>, logs: Vec<ethereum::Log>) -> DispatchResult {127 ensure_root(origin)?;128 for log in logs {129 <pallet_evm::Pallet<T>>::deposit_log(log);130 }131 // Transactions is created by FakeTransactionFinalizer132 Ok(())133 }134135 /// Create substrate events136 #[pallet::weight(<SelfWeightOf<T>>::insert_events(events.len() as u32))]137 pub fn insert_events(origin: OriginFor<T>, events: Vec<Vec<u8>>) -> DispatchResult {138 ensure_root(origin)?;139 for event in events {140 <frame_system::Pallet<T>>::deposit_event(141 <T as frame_system::Config>::RuntimeEvent::decode(&mut event.as_slice())142 .map_err(|_| <Error<T>>::BadEvent)?,143 );144 }145 Ok(())146 }110 }147 }111148112 /// Implements [`pallet_evm::OnMethodCall`], which reserves accounts with pending migration149 /// Implements [`pallet_evm::OnMethodCall`], which reserves accounts with pending migrationpallets/evm-migration/src/weights.rsdiffbeforeafterboth3//! Autogenerated weights for pallet_evm_migration3//! Autogenerated weights for pallet_evm_migration4//!4//!5//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev5//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev6//! DATE: 2022-08-15, STEPS: `50`, REPEAT: 80, LOW RANGE: `[]`, HIGH RANGE: `[]`6//! DATE: 2022-11-23, STEPS: `50`, REPEAT: 80, LOW RANGE: `[]`, HIGH RANGE: `[]`7//! EXECUTION: None, WASM-EXECUTION: Compiled, CHAIN: None, DB CACHE: 10247//! EXECUTION: None, WASM-EXECUTION: Compiled, CHAIN: None, DB CACHE: 1024889// Executed Command:9// Executed Command:37 fn begin() -> Weight;37 fn begin() -> Weight;38 fn set_data(b: u32, ) -> Weight;38 fn set_data(b: u32, ) -> Weight;39 fn finish(b: u32, ) -> Weight;39 fn finish(b: u32, ) -> Weight;40 fn insert_eth_logs(b: u32, ) -> Weight;41 fn insert_events(b: u32, ) -> Weight;40}42}414342/// Weights for pallet_evm_migration using the Substrate node and recommended hardware.44/// Weights for pallet_evm_migration using the Substrate node and recommended hardware.46 // Storage: System Account (r:1 w:0)48 // Storage: System Account (r:1 w:0)47 // Storage: EVM AccountCodes (r:1 w:0)49 // Storage: EVM AccountCodes (r:1 w:0)48 fn begin() -> Weight {50 fn begin() -> Weight {49 Weight::from_ref_time(8_035_000)51 Weight::from_ref_time(16_080_000 as u64)50 .saturating_add(T::DbWeight::get().reads(3 as u64))52 .saturating_add(T::DbWeight::get().reads(3 as u64))51 .saturating_add(T::DbWeight::get().writes(1 as u64))53 .saturating_add(T::DbWeight::get().writes(1 as u64))52 }54 }53 // Storage: EvmMigration MigrationPending (r:1 w:0)55 // Storage: EvmMigration MigrationPending (r:1 w:0)54 // Storage: EVM AccountStorages (r:0 w:1)56 // Storage: EVM AccountStorages (r:0 w:1)55 fn set_data(b: u32, ) -> Weight {57 fn set_data(b: u32, ) -> Weight {56 Weight::from_ref_time(3_076_000)58 Weight::from_ref_time(7_945_000 as u64)57 // Standard Error: 059 // Standard Error: 1_27258 .saturating_add(Weight::from_ref_time(828_000).saturating_mul(b as u64))60 .saturating_add(Weight::from_ref_time(1_056_832 as u64).saturating_mul(b as u64))59 .saturating_add(T::DbWeight::get().reads(1 as u64))61 .saturating_add(T::DbWeight::get().reads(1 as u64))60 .saturating_add(T::DbWeight::get().writes((1 as u64).saturating_mul(b as u64)))62 .saturating_add(T::DbWeight::get().writes((1 as u64).saturating_mul(b as u64)))61 }63 }62 // Storage: EvmMigration MigrationPending (r:1 w:1)64 // Storage: EvmMigration MigrationPending (r:1 w:1)63 // Storage: EVM AccountCodes (r:0 w:1)65 // Storage: EVM AccountCodes (r:0 w:1)64 fn finish(_b: u32, ) -> Weight {66 fn finish(b: u32, ) -> Weight {65 Weight::from_ref_time(6_591_000)67 Weight::from_ref_time(8_336_000 as u64)68 // Standard Error: 8969 .saturating_add(Weight::from_ref_time(6_411 as u64).saturating_mul(b as u64))66 .saturating_add(T::DbWeight::get().reads(1 as u64))70 .saturating_add(T::DbWeight::get().reads(1 as u64))67 .saturating_add(T::DbWeight::get().writes(2 as u64))71 .saturating_add(T::DbWeight::get().writes(2 as u64))68 }72 }73 fn insert_eth_logs(b: u32, ) -> Weight {74 Weight::from_ref_time(3_447_000 as u64)75 // Standard Error: 84376 .saturating_add(Weight::from_ref_time(901_039 as u64).saturating_mul(b as u64))77 }78 fn insert_events(b: u32, ) -> Weight {79 Weight::from_ref_time(3_457_000 as u64)80 // Standard Error: 1_46081 .saturating_add(Weight::from_ref_time(1_491_611 as u64).saturating_mul(b as u64))82 }69}83}708471// For backwards compatibility and tests85// For backwards compatibility and tests74 // Storage: System Account (r:1 w:0)88 // Storage: System Account (r:1 w:0)75 // Storage: EVM AccountCodes (r:1 w:0)89 // Storage: EVM AccountCodes (r:1 w:0)76 fn begin() -> Weight {90 fn begin() -> Weight {77 Weight::from_ref_time(8_035_000)91 Weight::from_ref_time(16_080_000 as u64)78 .saturating_add(RocksDbWeight::get().reads(3 as u64))92 .saturating_add(RocksDbWeight::get().reads(3 as u64))79 .saturating_add(RocksDbWeight::get().writes(1 as u64))93 .saturating_add(RocksDbWeight::get().writes(1 as u64))80 }94 }81 // Storage: EvmMigration MigrationPending (r:1 w:0)95 // Storage: EvmMigration MigrationPending (r:1 w:0)82 // Storage: EVM AccountStorages (r:0 w:1)96 // Storage: EVM AccountStorages (r:0 w:1)83 fn set_data(b: u32, ) -> Weight {97 fn set_data(b: u32, ) -> Weight {84 Weight::from_ref_time(3_076_000)98 Weight::from_ref_time(7_945_000 as u64)85 // Standard Error: 099 // Standard Error: 1_27286 .saturating_add(Weight::from_ref_time(828_000).saturating_mul(b as u64))100 .saturating_add(Weight::from_ref_time(1_056_832 as u64).saturating_mul(b as u64))87 .saturating_add(RocksDbWeight::get().reads(1 as u64))101 .saturating_add(RocksDbWeight::get().reads(1 as u64))88 .saturating_add(RocksDbWeight::get().writes((1 as u64).saturating_mul(b as u64)))102 .saturating_add(RocksDbWeight::get().writes((1 as u64).saturating_mul(b as u64)))89 }103 }90 // Storage: EvmMigration MigrationPending (r:1 w:1)104 // Storage: EvmMigration MigrationPending (r:1 w:1)91 // Storage: EVM AccountCodes (r:0 w:1)105 // Storage: EVM AccountCodes (r:0 w:1)92 fn finish(_b: u32, ) -> Weight {106 fn finish(b: u32, ) -> Weight {93 Weight::from_ref_time(6_591_000)107 Weight::from_ref_time(8_336_000 as u64)108 // Standard Error: 89109 .saturating_add(Weight::from_ref_time(6_411 as u64).saturating_mul(b as u64))94 .saturating_add(RocksDbWeight::get().reads(1 as u64))110 .saturating_add(RocksDbWeight::get().reads(1 as u64))95 .saturating_add(RocksDbWeight::get().writes(2 as u64))111 .saturating_add(RocksDbWeight::get().writes(2 as u64))96 }112 }113 fn insert_eth_logs(b: u32, ) -> Weight {114 Weight::from_ref_time(3_447_000 as u64)115 // Standard Error: 843116 .saturating_add(Weight::from_ref_time(901_039 as u64).saturating_mul(b as u64))117 }118 fn insert_events(b: u32, ) -> Weight {119 Weight::from_ref_time(3_457_000 as u64)120 // Standard Error: 1_460121 .saturating_add(Weight::from_ref_time(1_491_611 as u64).saturating_mul(b as u64))122 }97}123}98124runtime/common/config/ethereum.rsdiffbeforeafterboth91}91}929293impl pallet_evm_migration::Config for Runtime {93impl pallet_evm_migration::Config for Runtime {94 type RuntimeEvent = RuntimeEvent;94 type WeightInfo = pallet_evm_migration::weights::SubstrateWeight<Self>;95 type WeightInfo = pallet_evm_migration::weights::SubstrateWeight<Self>;95}96}9697runtime/common/construct_runtime/mod.rsdiffbeforeafterboth92 EvmCoderSubstrate: pallet_evm_coder_substrate::{Pallet, Storage} = 150,92 EvmCoderSubstrate: pallet_evm_coder_substrate::{Pallet, Storage} = 150,93 EvmContractHelpers: pallet_evm_contract_helpers::{Pallet, Storage, Event<T>} = 151,93 EvmContractHelpers: pallet_evm_contract_helpers::{Pallet, Storage, Event<T>} = 151,94 EvmTransactionPayment: pallet_evm_transaction_payment::{Pallet} = 152,94 EvmTransactionPayment: pallet_evm_transaction_payment::{Pallet} = 152,95 EvmMigration: pallet_evm_migration::{Pallet, Call, Storage} = 153,95 EvmMigration: pallet_evm_migration::{Pallet, Call, Storage, Event<T>} = 153,969697 Maintenance: pallet_maintenance::{Pallet, Call, Storage, Event<T>} = 154,97 Maintenance: pallet_maintenance::{Pallet, Call, Storage, Event<T>} = 154,9898tests/src/eth/migration.seqtest.tsdiffbeforeafterboth161617import {expect, itEth, usingEthPlaygrounds} from './util';17import {expect, itEth, usingEthPlaygrounds} from './util';18import {IKeyringPair} from '@polkadot/types/types';18import {IKeyringPair} from '@polkadot/types/types';19import {Struct} from '@polkadot/types';2021import {IEvent} from '../util/playgrounds/types';22import {ApiPromise} from '@polkadot/api';2324const encodeEvent = (api: ApiPromise, pallet: string, palletEvents: string, event: string, fields: any) => {25 const palletIndex = api.runtimeMetadata.asV14.pallets.find(p => p.name.toString() == pallet)!.index.toNumber();26 const eventMeta = api.events[palletEvents][event].meta;27 const eventIndex = eventMeta.index.toNumber();28 const data = [29 palletIndex, eventIndex,30 ];31 const metaEvent = api.registry.findMetaEvent(new Uint8Array(data));32 data.push(...new Struct(api.registry, {data: metaEvent}, {data: fields}).toU8a());3334 const typeName = api.registry.lookup.names.find(n => n.endsWith('RuntimeEvent'))!;35 return api.registry.createType(typeName, new Uint8Array(data)).toHex();36};193720describe('EVM Migrations', () => {38describe('EVM Migrations', () => {21 let superuser: IKeyringPair;39 let superuser: IKeyringPair;40 let charlie: IKeyringPair;224123 before(async function() {42 before(async function() {24 await usingEthPlaygrounds(async (_helper, privateKey) => {43 await usingEthPlaygrounds(async (_helper, privateKey) => {25 superuser = await privateKey('//Alice');44 superuser = await privateKey('//Alice');45 charlie = await privateKey('//Charlie');26 });46 });27 });47 });28 48105 expect(await contract.methods.get(i).call()).to.be.equal(i.toString());125 expect(await contract.methods.get(i).call()).to.be.equal(i.toString());106 }126 }107 });127 });128 itEth('Fake collection creation on substrate side', async ({helper}) => {129 const txInsertEvents = helper.constructApiCall('api.tx.evmMigration.insertEvents', [[130 encodeEvent(helper.api!, 'Common', 'common', 'CollectionCreated', [131 // Collection Id132 9999,133 // Collection mode: NFT134 1,135 // Owner136 charlie.address,137 ]),138 ]]);139 await helper.executeExtrinsic(superuser, 'api.tx.sudo.sudo', [txInsertEvents]);140 const event = helper.chainLog[helper.chainLog.length - 1].events as IEvent[];141 const eventStrings = event.map(e => `${e.section}.${e.method}`);142143 expect(eventStrings).to.contain('common.CollectionCreated');144 });145 itEth('Fake token creation on substrate side', async ({helper}) => {146 const txInsertEvents = helper.constructApiCall('api.tx.evmMigration.insertEvents', [[147 encodeEvent(helper.api!, 'Common', 'common', 'ItemCreated', [148 // Collection Id149 9999,150 // TokenId151 9999,152 // Owner153 {Substrate: charlie.address},154 // Amount155 1,156 ]),157 ]]);158 await helper.executeExtrinsic(superuser, 'api.tx.sudo.sudo', [txInsertEvents]);159 const event = helper.chainLog[helper.chainLog.length - 1].events as IEvent[];160 const eventStrings = event.map(e => `${e.section}.${e.method}`);161162 expect(eventStrings).to.contain('common.ItemCreated');163 });164 itEth('Fake token creation on ethereum side', async ({helper}) => {165 const collection = await helper.nft.mintCollection(superuser);166 const collectionAddress = helper.ethAddress.fromCollectionId(collection.collectionId);167 const caller = await helper.eth.createAccountWithBalance(superuser);168 const contract = helper.ethNativeContract.collection(collectionAddress, 'nft', caller);169170 const events: any = [];171 contract.events.allEvents((_: any, event: any) => {172 events.push(event);173 });174175 {176 const txInsertEthLogs = helper.constructApiCall('api.tx.evmMigration.insertEthLogs', [[177 {178 // Contract, which has emitted this log179 address: collectionAddress,180181 topics: [182 // First topic - event signature183 helper.getWeb3().eth.abi.encodeEventSignature('Transfer(address,address,uint256)'),184 // Rest of topics - indexed event fields in definition order185 helper.getWeb3().eth.abi.encodeParameter('address', '0x' + '00'.repeat(20)),186 helper.getWeb3().eth.abi.encodeParameter('address', caller),187 helper.getWeb3().eth.abi.encodeParameter('uint256', 9999),188 ],189190 // Every field coming from event, which is not marked as indexed, should be encoded here191 // NFT transfer has no such fields, but here is an example for some other possible event:192 // data: helper.getWeb3().eth.abi.encodeParameters(['uint256', 'address'], [22, collectionAddress])193 data: [],194 },195 ]]);196 await helper.executeExtrinsic(superuser, 'api.tx.sudo.sudo', [txInsertEthLogs]);197 }198199 if (events.length == 0) await helper.wait.newBlocks(1);200 const event = events[0];201202 expect(event.address).to.be.equal(collectionAddress);203 expect(event.returnValues.from).to.be.equal('0x' + '00'.repeat(20));204 expect(event.returnValues.to).to.be.equal(caller);205 expect(event.returnValues.tokenId).to.be.equal('9999');206 });108});207});109208