diff --git a/Cargo.lock b/Cargo.lock index ee94da9fd9f3b..556ba98e2ba6e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -13124,8 +13124,8 @@ dependencies = [ "pallet-utility", "parity-scale-codec", "paste", - "polkavm 0.26.0", - "polkavm-common 0.26.0", + "polkavm 0.27.0", + "polkavm-common 0.27.0", "pretty_assertions", "rand 0.8.5", "rand_pcg", @@ -13194,7 +13194,7 @@ dependencies = [ "anyhow", "cargo_metadata", "pallet-revive-uapi", - "polkavm-linker", + "polkavm-linker 0.27.0", "sp-core 38.0.0", "sp-io 42.0.0", "toml 0.8.19", @@ -13216,7 +13216,7 @@ dependencies = [ "bitflags 1.3.2", "pallet-revive-proc-macro", "parity-scale-codec", - "polkavm-derive 0.26.0", + "polkavm-derive 0.27.0", "scale-info", ] @@ -17162,6 +17162,19 @@ dependencies = [ "polkavm-linux-raw 0.26.0", ] +[[package]] +name = "polkavm" +version = "0.27.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ef5796e5aaa109df210fed7c6ff82e89c7bf94c28f6332d57bd0efb865fdc2a" +dependencies = [ + "libc", + "log", + "polkavm-assembler 0.27.0", + "polkavm-common 0.27.0", + "polkavm-linux-raw 0.27.0", +] + [[package]] name = "polkavm-assembler" version = "0.9.0" @@ -17180,6 +17193,15 @@ dependencies = [ "log", ] +[[package]] +name = "polkavm-assembler" +version = "0.27.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70bf3be2911acc089dfe54a92bfec22002f4fbf423b8fa771d1f7e7227f0195f" +dependencies = [ + "log", +] + [[package]] name = "polkavm-common" version = "0.9.0" @@ -17195,11 +17217,21 @@ version = "0.26.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49a5794b695626ba70d29e66e3f4f4835767452a6723f3a0bc20884b07088fe8" dependencies = [ - "blake3", "log", "polkavm-assembler 0.26.0", ] +[[package]] +name = "polkavm-common" +version = "0.27.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a19805789e7bf778ac5855f6fe9350353f6a1697c2aab9bfb6fc7c831be54fad" +dependencies = [ + "blake3", + "log", + "polkavm-assembler 0.27.0", +] + [[package]] name = "polkavm-derive" version = "0.9.1" @@ -17218,6 +17250,15 @@ dependencies = [ "polkavm-derive-impl-macro 0.26.0", ] +[[package]] +name = "polkavm-derive" +version = "0.27.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4eea46a17d87cbf3c0f3f6156f6300f60cec67cf9eaca296c770e0873f8389d6" +dependencies = [ + "polkavm-derive-impl-macro 0.27.0", +] + [[package]] name = "polkavm-derive-impl" version = "0.9.0" @@ -17242,6 +17283,18 @@ dependencies = [ "syn 2.0.98", ] +[[package]] +name = "polkavm-derive-impl" +version = "0.27.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8abdd1210d96b1dda9ac21199ec469448fd628cea102e2ff0e0df1667c4c3b5f" +dependencies = [ + "polkavm-common 0.27.0", + "proc-macro2 1.0.95", + "quote 1.0.40", + "syn 2.0.98", +] + [[package]] name = "polkavm-derive-impl-macro" version = "0.9.0" @@ -17262,6 +17315,16 @@ dependencies = [ "syn 2.0.98", ] +[[package]] +name = "polkavm-derive-impl-macro" +version = "0.27.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a45173d70138aa1879892c50777ed0d8b0c8556f7678372f09fa1d89bbbddb4" +dependencies = [ + "polkavm-derive-impl 0.27.0", + "syn 2.0.98", +] + [[package]] name = "polkavm-linker" version = "0.26.0" @@ -17278,6 +17341,22 @@ dependencies = [ "rustc-demangle", ] +[[package]] +name = "polkavm-linker" +version = "0.27.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "99fe3704d21e96c5d1e6a1b1a43ac57f9dce110d3331fbf8299e9f57d5884066" +dependencies = [ + "dirs", + "gimli 0.31.1", + "hashbrown 0.14.5", + "log", + "object 0.36.1", + "polkavm-common 0.27.0", + "regalloc2 0.9.3", + "rustc-demangle", +] + [[package]] name = "polkavm-linux-raw" version = "0.9.0" @@ -17290,6 +17369,12 @@ version = "0.26.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "28919f542476f4158cc71e6c072b1051f38f4b514253594ac3ad80e3c0211fc8" +[[package]] +name = "polkavm-linux-raw" +version = "0.27.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "061088785efd93e4367faf12f341bb356208c06bab43aa942d472068af80d1c4" + [[package]] name = "polling" version = "2.8.0" @@ -25115,7 +25200,7 @@ dependencies = [ "merkleized-metadata", "parity-scale-codec", "parity-wasm", - "polkavm-linker", + "polkavm-linker 0.26.0", "sc-executor 0.44.0", "shlex", "sp-core 38.0.0", diff --git a/cumulus/parachains/runtimes/assets/asset-hub-westend/src/lib.rs b/cumulus/parachains/runtimes/assets/asset-hub-westend/src/lib.rs index e12170c38dbb3..fb26ed2ee034e 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-westend/src/lib.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-westend/src/lib.rs @@ -1200,7 +1200,7 @@ parameter_types! { impl pallet_migrations::Config for Runtime { type RuntimeEvent = RuntimeEvent; #[cfg(not(feature = "runtime-benchmarks"))] - type Migrations = pallet_migrations::migrations::ResetPallet; + type Migrations = pallet_revive::migrations::v1::Migration; // Benchmarks need mocked migrations to guarantee that they succeed. #[cfg(feature = "runtime-benchmarks")] type Migrations = pallet_migrations::mock_helpers::MockedMigrations; diff --git a/cumulus/parachains/runtimes/assets/common/src/erc20_transactor.rs b/cumulus/parachains/runtimes/assets/common/src/erc20_transactor.rs index ec4e3adad3bae..29e40d1ab1cf8 100644 --- a/cumulus/parachains/runtimes/assets/common/src/erc20_transactor.rs +++ b/cumulus/parachains/runtimes/assets/common/src/erc20_transactor.rs @@ -18,10 +18,7 @@ use core::marker::PhantomData; use ethereum_standards::IERC20; -use frame_support::{ - pallet_prelude::Zero, - traits::{fungible::Inspect, OriginTrait}, -}; +use frame_support::traits::{fungible::Inspect, OriginTrait}; use pallet_revive::{ precompiles::alloy::{ primitives::{Address, U256 as EU256}, @@ -127,7 +124,7 @@ where pallet_revive::Pallet::::bare_call( T::RuntimeOrigin::signed(who.clone()), asset_id, - BalanceOf::::zero(), + U256::zero(), gas_limit, DepositLimit::Balance(StorageDepositLimit::get()), data, @@ -185,7 +182,7 @@ where pallet_revive::Pallet::::bare_call( T::RuntimeOrigin::signed(TransfersCheckingAccount::get()), asset_id, - BalanceOf::::zero(), + U256::zero(), gas_limit, DepositLimit::Balance(StorageDepositLimit::get()), data, diff --git a/polkadot/xcm/pallet-xcm/src/precompiles.rs b/polkadot/xcm/pallet-xcm/src/precompiles.rs index cee336081f348..b673a1183055e 100644 --- a/polkadot/xcm/pallet-xcm/src/precompiles.rs +++ b/polkadot/xcm/pallet-xcm/src/precompiles.rs @@ -184,11 +184,11 @@ mod test { }, H160, }, - DepositLimit, + DepositLimit, U256, }; use polkadot_parachain_primitives::primitives::Id as ParaId; use sp_runtime::traits::AccountIdConversion; - use xcm::prelude::*; + use xcm::{prelude::*, v3, v4}; const BOB: AccountId = AccountId::new([1u8; 32]); const CHARLIE: AccountId = AccountId::new([2u8; 32]); @@ -229,7 +229,7 @@ mod test { let result = pallet_revive::Pallet::::bare_call( RuntimeOrigin::signed(ALICE), xcm_precompile_addr, - 0u128, + U256::zero(), Weight::MAX, DepositLimit::UnsafeOnlyForDryRun, encoded_call, @@ -277,7 +277,7 @@ mod test { let result = pallet_revive::Pallet::::bare_call( RuntimeOrigin::signed(ALICE), xcm_precompile_addr, - 0u128, + U256::zero(), Weight::MAX, DepositLimit::UnsafeOnlyForDryRun, encoded_call, @@ -313,6 +313,81 @@ mod test { ]); let destination: VersionedLocation = VersionedLocation::from(Location::ancestor(8)); + let versioned_message: VersionedXcm<()> = VersionedXcm::from(message.clone()); + + let xcm_send_params = IXcm::sendCall { + destination: destination.encode().into(), + message: versioned_message.encode().into(), + }; + let call = IXcm::IXcmCalls::send(xcm_send_params); + let encoded_call = call.abi_encode(); + + let result = pallet_revive::Pallet::::bare_call( + RuntimeOrigin::signed(ALICE), + xcm_precompile_addr, + U256::zero(), + Weight::MAX, + DepositLimit::UnsafeOnlyForDryRun, + encoded_call, + ); + let return_value = match result.result { + Ok(value) => value, + Err(err) => panic!("XcmSendPrecompile call failed with error: {err:?}"), + }; + assert!(return_value.did_revert()); + }); + } + + #[test] + fn send_fails_on_old_location_version() { + use codec::Encode; + + let balances = vec![ + (ALICE, CUSTOM_INITIAL_BALANCE), + (ParaId::from(OTHER_PARA_ID).into_account_truncating(), CUSTOM_INITIAL_BALANCE), + ]; + new_test_ext_with_balances(balances).execute_with(|| { + let xcm_precompile_addr = H160::from( + hex::const_decode_to_array(b"00000000000000000000000000000000000A0000").unwrap(), + ); + + let sender: Location = AccountId32 { network: None, id: ALICE.into() }.into(); + let message = Xcm(vec![ + ReserveAssetDeposited((Parent, SEND_AMOUNT).into()), + ClearOrigin, + buy_execution((Parent, SEND_AMOUNT)), + DepositAsset { assets: AllCounted(1).into(), beneficiary: sender.clone() }, + ]); + + // V4 location is old and will fail. + let destination: VersionedLocation = + VersionedLocation::V4(v4::Junction::Parachain(OTHER_PARA_ID).into()); + let versioned_message: VersionedXcm = VersionedXcm::from(message.clone()); + + let xcm_send_params = IXcm::sendCall { + destination: destination.encode().into(), + message: versioned_message.encode().into(), + }; + let call = IXcm::IXcmCalls::send(xcm_send_params); + let encoded_call = call.abi_encode(); + + let result = pallet_revive::Pallet::::bare_call( + RuntimeOrigin::signed(ALICE), + xcm_precompile_addr, + U256::zero(), + Weight::MAX, + DepositLimit::UnsafeOnlyForDryRun, + encoded_call, + ); + let return_value = match result.result { + Ok(value) => value, + Err(err) => panic!("XcmSendPrecompile call failed with error: {err:?}"), + }; + assert!(return_value.did_revert()); + + // V3 also fails. + let destination: VersionedLocation = + VersionedLocation::V3(v3::Junction::Parachain(OTHER_PARA_ID).into()); let versioned_message: VersionedXcm = VersionedXcm::from(message); let xcm_send_params = IXcm::sendCall { @@ -325,7 +400,83 @@ mod test { let result = pallet_revive::Pallet::::bare_call( RuntimeOrigin::signed(ALICE), xcm_precompile_addr, - 0u128, + U256::zero(), + Weight::MAX, + DepositLimit::UnsafeOnlyForDryRun, + encoded_call, + ); + let return_value = match result.result { + Ok(value) => value, + Err(err) => panic!("XcmSendPrecompile call failed with error: {err:?}"), + }; + assert!(return_value.did_revert()); + }); + } + + #[test] + fn send_fails_on_old_xcm_version() { + use codec::Encode; + + let balances = vec![ + (ALICE, CUSTOM_INITIAL_BALANCE), + (ParaId::from(OTHER_PARA_ID).into_account_truncating(), CUSTOM_INITIAL_BALANCE), + ]; + new_test_ext_with_balances(balances).execute_with(|| { + let xcm_precompile_addr = H160::from( + hex::const_decode_to_array(b"00000000000000000000000000000000000A0000").unwrap(), + ); + + let sender: Location = AccountId32 { network: None, id: ALICE.into() }.into(); + let message = Xcm(vec![ + ReserveAssetDeposited((Parent, SEND_AMOUNT).into()), + ClearOrigin, + buy_execution((Parent, SEND_AMOUNT)), + DepositAsset { assets: AllCounted(1).into(), beneficiary: sender.clone() }, + ]); + // V4 is old and fails. + let v4_message: v4::Xcm = message.try_into().unwrap(); + + let destination: VersionedLocation = Parachain(OTHER_PARA_ID).into(); + let versioned_message: VersionedXcm = VersionedXcm::V4(v4_message.clone()); + + let xcm_send_params = IXcm::sendCall { + destination: destination.encode().into(), + message: versioned_message.encode().into(), + }; + let call = IXcm::IXcmCalls::send(xcm_send_params); + let encoded_call = call.abi_encode(); + + let result = pallet_revive::Pallet::::bare_call( + RuntimeOrigin::signed(ALICE), + xcm_precompile_addr, + U256::zero(), + Weight::MAX, + DepositLimit::UnsafeOnlyForDryRun, + encoded_call, + ); + let return_value = match result.result { + Ok(value) => value, + Err(err) => panic!("XcmSendPrecompile call failed with error: {err:?}"), + }; + assert!(return_value.did_revert()); + + // With V3 it also fails. + let v3_message: v3::Xcm = v4_message.try_into().unwrap(); + + let destination: VersionedLocation = Parachain(OTHER_PARA_ID).into(); + let versioned_message: VersionedXcm = VersionedXcm::V3(v3_message); + + let xcm_send_params = IXcm::sendCall { + destination: destination.encode().into(), + message: versioned_message.encode().into(), + }; + let call = IXcm::IXcmCalls::send(xcm_send_params); + let encoded_call = call.abi_encode(); + + let result = pallet_revive::Pallet::::bare_call( + RuntimeOrigin::signed(ALICE), + xcm_precompile_addr, + U256::zero(), Weight::MAX, DepositLimit::UnsafeOnlyForDryRun, encoded_call, @@ -367,7 +518,7 @@ mod test { let xcm_weight_results = pallet_revive::Pallet::::bare_call( RuntimeOrigin::signed(ALICE), xcm_precompile_addr, - 0u128, + U256::zero(), Weight::MAX, DepositLimit::UnsafeOnlyForDryRun, encoded_weight_call, @@ -389,7 +540,7 @@ mod test { let result = pallet_revive::Pallet::::bare_call( RuntimeOrigin::signed(ALICE), xcm_precompile_addr, - 0u128, + U256::zero(), Weight::MAX, DepositLimit::UnsafeOnlyForDryRun, encoded_call, @@ -427,7 +578,7 @@ mod test { let xcm_weight_results = pallet_revive::Pallet::::bare_call( RuntimeOrigin::signed(ALICE), xcm_precompile_addr, - 0u128, + U256::zero(), Weight::MAX, DepositLimit::UnsafeOnlyForDryRun, encoded_weight_call, @@ -449,7 +600,7 @@ mod test { let result = pallet_revive::Pallet::::bare_call( RuntimeOrigin::signed(ALICE), xcm_precompile_addr, - 0u128, + U256::zero(), Weight::MAX, DepositLimit::UnsafeOnlyForDryRun, encoded_call, @@ -495,7 +646,7 @@ mod test { let xcm_weight_results = pallet_revive::Pallet::::bare_call( RuntimeOrigin::signed(ALICE), xcm_precompile_addr, - 0u128, + U256::zero(), Weight::MAX, DepositLimit::UnsafeOnlyForDryRun, encoded_weight_call, @@ -517,7 +668,7 @@ mod test { let result = pallet_revive::Pallet::::bare_call( RuntimeOrigin::signed(ALICE), xcm_precompile_addr, - 0u128, + U256::zero(), Weight::MAX, DepositLimit::UnsafeOnlyForDryRun, encoded_call, @@ -531,4 +682,176 @@ mod test { assert_eq!(Balances::total_balance(&BOB), CUSTOM_INITIAL_BALANCE); }); } + + #[test] + fn execute_fails_on_old_version() { + use codec::Encode; + + let balances = vec![ + (ALICE, CUSTOM_INITIAL_BALANCE), + (ParaId::from(OTHER_PARA_ID).into_account_truncating(), CUSTOM_INITIAL_BALANCE), + ]; + new_test_ext_with_balances(balances).execute_with(|| { + let xcm_precompile_addr = H160::from( + hex::const_decode_to_array(b"00000000000000000000000000000000000A0000").unwrap(), + ); + + let dest: Location = Junction::AccountId32 { network: None, id: BOB.into() }.into(); + assert_eq!(Balances::total_balance(&ALICE), CUSTOM_INITIAL_BALANCE); + + let message = Xcm(vec![ + WithdrawAsset((Here, SEND_AMOUNT).into()), + buy_execution((Here, SEND_AMOUNT)), + DepositAsset { assets: AllCounted(1).into(), beneficiary: dest }, + ]); + let versioned_message = VersionedXcm::from(message.clone()); + + let weight_params = weighMessageCall { message: versioned_message.encode().into() }; + let weight_call = IXcm::IXcmCalls::weighMessage(weight_params); + let encoded_weight_call = weight_call.abi_encode(); + + let xcm_weight_results = pallet_revive::Pallet::::bare_call( + RuntimeOrigin::signed(ALICE), + xcm_precompile_addr, + U256::zero(), + Weight::MAX, + DepositLimit::UnsafeOnlyForDryRun, + encoded_weight_call, + ); + + let weight_result = match xcm_weight_results.result { + Ok(value) => value, + Err(err) => + panic!("XcmExecutePrecompile Failed to decode weight with error {err:?}"), + }; + + let weight: IXcm::Weight = IXcm::Weight::abi_decode(&weight_result.data[..]) + .expect("XcmExecutePrecompile Failed to decode weight"); + + // Using a V4 message to check that it fails. + let v4_message: v4::Xcm = message.clone().try_into().unwrap(); + let versioned_message = VersionedXcm::V4(v4_message.clone()); + + let xcm_execute_params = IXcm::executeCall { + message: versioned_message.encode().into(), + weight: weight.clone(), + }; + let call = IXcm::IXcmCalls::execute(xcm_execute_params); + let encoded_call = call.abi_encode(); + + let result = pallet_revive::Pallet::::bare_call( + RuntimeOrigin::signed(ALICE), + xcm_precompile_addr, + U256::zero(), + Weight::MAX, + DepositLimit::UnsafeOnlyForDryRun, + encoded_call, + ); + + let return_value = match result.result { + Ok(value) => value, + Err(err) => panic!("XcmExecutePrecompile call failed with error: {err:?}"), + }; + assert!(return_value.did_revert()); + assert_eq!(Balances::total_balance(&ALICE), CUSTOM_INITIAL_BALANCE); + assert_eq!(Balances::total_balance(&BOB), 0); + + // Now using a V3 message. + let v3_message: v3::Xcm = v4_message.try_into().unwrap(); + let versioned_message = VersionedXcm::V3(v3_message); + + let xcm_execute_params = + IXcm::executeCall { message: versioned_message.encode().into(), weight }; + let call = IXcm::IXcmCalls::execute(xcm_execute_params); + let encoded_call = call.abi_encode(); + + let result = pallet_revive::Pallet::::bare_call( + RuntimeOrigin::signed(ALICE), + xcm_precompile_addr, + U256::zero(), + Weight::MAX, + DepositLimit::UnsafeOnlyForDryRun, + encoded_call, + ); + + let return_value = match result.result { + Ok(value) => value, + Err(err) => panic!("XcmExecutePrecompile call failed with error: {err:?}"), + }; + assert!(return_value.did_revert()); + assert_eq!(Balances::total_balance(&ALICE), CUSTOM_INITIAL_BALANCE); + assert_eq!(Balances::total_balance(&BOB), 0); + }); + } + + #[test] + fn weight_fails_on_old_version() { + use codec::Encode; + + let balances = vec![ + (ALICE, CUSTOM_INITIAL_BALANCE), + (ParaId::from(OTHER_PARA_ID).into_account_truncating(), CUSTOM_INITIAL_BALANCE), + ]; + new_test_ext_with_balances(balances).execute_with(|| { + let xcm_precompile_addr = H160::from( + hex::const_decode_to_array(b"00000000000000000000000000000000000A0000").unwrap(), + ); + + let dest: Location = Junction::AccountId32 { network: None, id: BOB.into() }.into(); + assert_eq!(Balances::total_balance(&ALICE), CUSTOM_INITIAL_BALANCE); + + let message: Xcm = Xcm(vec![ + WithdrawAsset((Here, SEND_AMOUNT).into()), + buy_execution((Here, SEND_AMOUNT)), + DepositAsset { assets: AllCounted(1).into(), beneficiary: dest }, + ]); + // V4 version is old, fails. + let v4_message: v4::Xcm = message.try_into().unwrap(); + let versioned_message = VersionedXcm::V4(v4_message.clone()); + + let weight_params = weighMessageCall { message: versioned_message.encode().into() }; + let weight_call = IXcm::IXcmCalls::weighMessage(weight_params); + let encoded_weight_call = weight_call.abi_encode(); + + let xcm_weight_results = pallet_revive::Pallet::::bare_call( + RuntimeOrigin::signed(ALICE), + xcm_precompile_addr, + U256::zero(), + Weight::MAX, + DepositLimit::UnsafeOnlyForDryRun, + encoded_weight_call, + ); + + let result = match xcm_weight_results.result { + Ok(value) => value, + Err(err) => + panic!("XcmExecutePrecompile Failed to decode weight with error {err:?}"), + }; + assert!(result.did_revert()); + + // Now we also try V3. + let v3_message: v3::Xcm = v4_message.try_into().unwrap(); + let versioned_message = VersionedXcm::V3(v3_message); + + let weight_params = weighMessageCall { message: versioned_message.encode().into() }; + let weight_call = IXcm::IXcmCalls::weighMessage(weight_params); + let encoded_weight_call = weight_call.abi_encode(); + + let xcm_weight_results = pallet_revive::Pallet::::bare_call( + RuntimeOrigin::signed(ALICE), + xcm_precompile_addr, + U256::zero(), + Weight::MAX, + DepositLimit::UnsafeOnlyForDryRun, + encoded_weight_call, + ); + + let result = match xcm_weight_results.result { + Ok(value) => value, + Err(err) => + panic!("XcmExecutePrecompile Failed to decode weight with error {err:?}"), + }; + assert!(result.did_revert()); + }); + } } diff --git a/prdoc/pr_9101.prdoc b/prdoc/pr_9101.prdoc new file mode 100644 index 0000000000000..1996fab63dc04 --- /dev/null +++ b/prdoc/pr_9101.prdoc @@ -0,0 +1,27 @@ +title: '[revive] eth-decimals' +doc: +- audience: Runtime Dev + description: |- + On Ethereum, 1 ETH is represented as 10^18 wei (wei being the smallest unit). + On Polkadot 1 DOT is defined as 10^10 plancks. It means that any value smaller than 10^8 wei can not be expressed with the native balance. Any contract that attempts to use such a value currently reverts with a DecimalPrecisionLoss error. + + In theory, RPC can define a decimal representation different from Ethereum mainnet (10^18). In practice tools (frontend libraries, wallets, and compilers) ignore it and expect 18 decimals. + + The current behaviour breaks eth compatibility and needs to be updated. See issue #109 for more details. + + + Fix https://github.com/paritytech/contract-issues/issues/109 + [weights compare](https://weights.tasty.limo/compare?unit=weight&ignore_errors=true&threshold=10&method=asymptotic&repo=polkadot-sdk&old=master&new=pg/eth-decimals&path_pattern=substrate/frame/**/src/weights.rs,polkadot/runtime/*/src/weights/**/*.rs,polkadot/bridges/modules/*/src/weights.rs,cumulus/**/weights/*.rs,cumulus/**/weights/xcm/*.rs,cumulus/**/src/weights.rs) +crates: +- name: pallet-revive + bump: major +- name: pallet-revive-fixtures + bump: major +- name: assets-common + bump: major +- name: asset-hub-westend-runtime + bump: major +- name: pallet-xcm + bump: major +- name: pallet-assets + bump: major diff --git a/prdoc/pr_9112.prdoc b/prdoc/pr_9112.prdoc new file mode 100644 index 0000000000000..25eb3100cf67f --- /dev/null +++ b/prdoc/pr_9112.prdoc @@ -0,0 +1,7 @@ +title: Fix seal_call benchmark +doc: +- audience: Runtime Dev + description: Fix seal_call benchmark, ensure that the call actually succeed +crates: +- name: pallet-revive + bump: patch diff --git a/prdoc/pr_9126.prdoc b/prdoc/pr_9126.prdoc new file mode 100644 index 0000000000000..81d131cc75050 --- /dev/null +++ b/prdoc/pr_9126.prdoc @@ -0,0 +1,20 @@ +# Schema: Polkadot SDK PRDoc Schema (prdoc) v1.0.0 +# See doc at https://raw.githubusercontent.com/paritytech/polkadot-sdk/master/prdoc/schema_user.json + +title: XCM precompile - don't support older XCM versions (3 and 4) + +doc: + - audience: Runtime Dev + description: | + The latest XCM version is 5. + A lot of parachains are still running V3 or V4 which is why we haven't removed them, but the XCM precompile is new and should only have to deal with versions 5 and onwards. + No need to keep dragging 3 and 4 in contracts. + This is the default behavior, there's no need to configure anything in pallet-xcm. + - audience: Runtime User + description: | + The XCM precompile will only support XCM from version 5 (current) onwards. + Versions 3 and 4 won't be supported. + +crates: + - name: pallet-xcm + bump: patch diff --git a/prdoc/pr_9267.prdoc b/prdoc/pr_9267.prdoc new file mode 100644 index 0000000000000..478977931d49e --- /dev/null +++ b/prdoc/pr_9267.prdoc @@ -0,0 +1,38 @@ +title: 'pallet-revive: Raise contract size limit to one megabyte and raise call depth + to 25' +doc: +- audience: Runtime Dev + description: |- + This PR changes the contract code limit from roughly 100KiB to exactly 1MiB. It also raises the call stack depth from 5 to 25. + + Those limits were in place because of memory constraints within the runtime. We work around them in those ways: + 1) Removing the 4x safety margin for allocations which is no longer needed due to the new allocator. + 2) Limiting the size of the compilation cache to a fixed size. + 3) Resetting the compilation cache and flat map every time we call into a new contract. + 4) Limiting the size of calldata and return data to 128KiB (only capped by tx size and RAM before). While this is a breaking change nobody will be affected since Geth effectively limits the call data to 128KiB. + + ## 1MiB contracts + + This is large enough so that all known contracts won't fail for size issues anymore. + + The new limit is also much simpler to understand since it does not depend on the number of instructions. Just those two constraints: + ``` + PVM_BLOB.len() < 1 MiB + PVM_BLOB.len() + (rw/ro/stack) < 1MiB + 512KiB + ``` + + This means: + 1) A contract is guaranteed to have at least 512KiB of memory available. + 2) A contract that is smaller in code can use more memory. + 3) Limit is exactly 1MiB unless a user manually increase the memory usage of a contract to be larger than 512KiB. + + ## Call stack depth `5 -> 25` + + The limit of `5` was problematic because there are use cases which require deeper stacks. With the raise to `25` there should be no benign use cases anymore that won't work. + + Please note that even with the low limit of `25` contracts are not vulnerable to stack depth exhaustion attacks: We do trap the caller's context when the depth limit is reached. This is different from Eth where this error can be handled and failure to do so leaves the contract vulnerable. +crates: +- name: pallet-revive-fixtures + bump: patch +- name: pallet-revive + bump: patch diff --git a/prdoc/pr_9357.prdoc b/prdoc/pr_9357.prdoc new file mode 100644 index 0000000000000..381e7a19d7e49 --- /dev/null +++ b/prdoc/pr_9357.prdoc @@ -0,0 +1,11 @@ +title: "Fix dust balance handling in ETH transfers" + +doc: + - audience: Runtime Dev + description: |- + Fixed a bug in the eth-decimals implementation where ETH transfers were failing due to incorrect receiver dust balance handling. The condition for minting a new currency unit when transferring dust was checking `to_info.dust.saturating_add(dust) >= plank` which `to_info.dust` has been added twice, could lead to unexpected minting behavior. + This fix ensures that ETH transfers work correctly, enabling proper operation of DeFi protocols like Uniswap on PolkaVM. + +crates: + - name: pallet-revive + bump: patch diff --git a/prdoc/pr_9416.prdoc b/prdoc/pr_9416.prdoc new file mode 100644 index 0000000000000..ab2315d532583 --- /dev/null +++ b/prdoc/pr_9416.prdoc @@ -0,0 +1,10 @@ +title: 'pallet_revive: Enforce storage deposit limit on plain transfer' +doc: +- audience: Runtime Dev + description: |- + The existential deposit to create a new account is part of the storage deposit. Hence if the storage deposit limit is too low to create a new account we fail the transaction. However, this limit was not enforced for plain transfers. The reason is that we only enforce the limit at the end of each frame. But for plain transfers (transferring to a non contract) there is no frame. + + This PR fixes the situation by enforcing the limit when transferring the existential deposit in order to create a new account. +crates: +- name: pallet-revive + bump: patch diff --git a/prdoc/pr_9441.prdoc b/prdoc/pr_9441.prdoc new file mode 100644 index 0000000000000..35f15bd99abd4 --- /dev/null +++ b/prdoc/pr_9441.prdoc @@ -0,0 +1,12 @@ +title: '[pallet-revive] Implement basic `System` pre-compile, move `seal_hash_blake2_256` into it.' +doc: +- audience: Runtime Dev + description: Implements a basic `System` pre-compile and moves the unstable + host function `hash_blake2_256` in there. +crates: +- name: pallet-revive + bump: minor +- name: pallet-revive-fixtures + bump: major +- name: pallet-revive-uapi + bump: major diff --git a/substrate/frame/assets/src/precompiles.rs b/substrate/frame/assets/src/precompiles.rs index 6d0c08ba3eecb..107145a524d81 100644 --- a/substrate/frame/assets/src/precompiles.rs +++ b/substrate/frame/assets/src/precompiles.rs @@ -369,7 +369,7 @@ mod test { pallet_revive::Pallet::::bare_call( RuntimeOrigin::signed(1), H160::from(asset_addr), - 0u64, + 0u32.into(), Weight::MAX, DepositLimit::UnsafeOnlyForDryRun, data, @@ -405,7 +405,7 @@ mod test { let data = pallet_revive::Pallet::::bare_call( RuntimeOrigin::signed(1), H160::from(asset_addr), - 0u64, + 0u32.into(), Weight::MAX, DepositLimit::UnsafeOnlyForDryRun, data, @@ -436,7 +436,7 @@ mod test { let data = pallet_revive::Pallet::::bare_call( RuntimeOrigin::signed(1), H160::from(asset_addr), - 0u64, + 0u32.into(), Weight::MAX, DepositLimit::UnsafeOnlyForDryRun, data, @@ -482,7 +482,7 @@ mod test { pallet_revive::Pallet::::bare_call( RuntimeOrigin::signed(owner), H160::from(asset_addr), - 0u64, + 0u32.into(), Weight::MAX, DepositLimit::UnsafeOnlyForDryRun, data, @@ -506,7 +506,7 @@ mod test { let data = pallet_revive::Pallet::::bare_call( RuntimeOrigin::signed(owner), H160::from(asset_addr), - 0u64, + 0u32.into(), Weight::MAX, DepositLimit::UnsafeOnlyForDryRun, data, @@ -528,7 +528,7 @@ mod test { pallet_revive::Pallet::::bare_call( RuntimeOrigin::signed(spender), H160::from(asset_addr), - 0u64, + 0u32.into(), Weight::MAX, DepositLimit::UnsafeOnlyForDryRun, data, diff --git a/substrate/frame/revive/Cargo.toml b/substrate/frame/revive/Cargo.toml index a4c3f71a5cb06..c04becaada8ac 100644 --- a/substrate/frame/revive/Cargo.toml +++ b/substrate/frame/revive/Cargo.toml @@ -31,8 +31,8 @@ num-bigint = { workspace = true } num-integer = { workspace = true } num-traits = { workspace = true } paste = { workspace = true } -polkavm = { version = "0.26.0", default-features = false } -polkavm-common = { version = "0.26.0", default-features = false, optional = true } +polkavm = { version = "0.27.0", default-features = false } +polkavm-common = { version = "0.27.0", default-features = false, features = ["alloc"] } rand = { workspace = true, optional = true } rand_pcg = { workspace = true, optional = true } rlp = { workspace = true } @@ -62,7 +62,6 @@ subxt-signer = { workspace = true, optional = true, features = ["unstable-eth"] [dev-dependencies] array-bytes = { workspace = true, default-features = true } assert_matches = { workspace = true } -polkavm-common = { version = "0.26.0" } pretty_assertions = { workspace = true } secp256k1 = { workspace = true, features = ["recovery"] } serde_json = { workspace = true } @@ -93,7 +92,8 @@ std = [ "num-traits/std", "pallet-revive-fixtures?/std", "pallet-transaction-payment/std", - "polkavm-common?/std", + "pallet-utility/std", + "polkavm-common/std", "polkavm/std", "rand?/std", "ripemd/std", @@ -122,7 +122,6 @@ runtime-benchmarks = [ "pallet-timestamp/runtime-benchmarks", "pallet-transaction-payment/runtime-benchmarks", "pallet-utility/runtime-benchmarks", - "polkavm-common/alloc", "rand", "rand_pcg", "sp-consensus-aura", diff --git a/substrate/frame/revive/fixtures/Cargo.toml b/substrate/frame/revive/fixtures/Cargo.toml index 6b1d05f38793e..f6d0f2034d153 100644 --- a/substrate/frame/revive/fixtures/Cargo.toml +++ b/substrate/frame/revive/fixtures/Cargo.toml @@ -23,8 +23,8 @@ sp-io = { workspace = true, optional = true, default-features = true } [build-dependencies] anyhow = { workspace = true, default-features = true } cargo_metadata = { workspace = true } -pallet-revive-uapi.workspace = true -polkavm-linker = { version = "0.26.0" } +pallet-revive-uapi = { workspace = true } +polkavm-linker = { version = "0.27.0" } toml = { workspace = true } [features] diff --git a/substrate/frame/revive/fixtures/build/_Cargo.toml b/substrate/frame/revive/fixtures/build/_Cargo.toml index ac59ef071c4ea..af898cec525ef 100644 --- a/substrate/frame/revive/fixtures/build/_Cargo.toml +++ b/substrate/frame/revive/fixtures/build/_Cargo.toml @@ -14,7 +14,7 @@ edition = "2021" [dependencies] uapi = { package = 'pallet-revive-uapi', features = ["unstable-hostfn"], default-features = false } hex-literal = { version = "0.4.1", default-features = false } -polkavm-derive = { version = "0.25.0" } +polkavm-derive = { version = "0.27.0" } [profile.release] opt-level = 3 diff --git a/substrate/frame/revive/fixtures/contracts/call_and_returncode.rs b/substrate/frame/revive/fixtures/contracts/call_and_returncode.rs index 82d7dbdabf15c..939be006552ea 100644 --- a/substrate/frame/revive/fixtures/contracts/call_and_returncode.rs +++ b/substrate/frame/revive/fixtures/contracts/call_and_returncode.rs @@ -21,6 +21,8 @@ #![no_main] include!("../panic_handler.rs"); +polkavm_derive::min_stack_size!(256 * 1024); + use uapi::{input, u256_bytes, HostFn, HostFnImpl as api}; #[no_mangle] @@ -38,7 +40,7 @@ pub extern "C" fn call() { ); // the first 4 bytes are reserved for the return code - let mut output = [0u8; 512]; + let mut output = [0u8; 128 * 1024]; let output_ptr = &mut &mut output[4..]; let code = match api::call( diff --git a/substrate/frame/revive/fixtures/contracts/call_with_input_size.rs b/substrate/frame/revive/fixtures/contracts/call_with_input_size.rs new file mode 100644 index 0000000000000..b4fdfe7d836fa --- /dev/null +++ b/substrate/frame/revive/fixtures/contracts/call_with_input_size.rs @@ -0,0 +1,51 @@ +// This file is part of Substrate. + +// Copyright (C) Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#![no_std] +#![no_main] +include!("../panic_handler.rs"); + +polkavm_derive::min_stack_size!(512 * 1024); + +use uapi::{input, HostFn, HostFnImpl as api}; + +#[no_mangle] +#[polkavm_derive::polkavm_export] +pub extern "C" fn deploy() {} + +#[no_mangle] +#[polkavm_derive::polkavm_export] +pub extern "C" fn call() { + input!( + input_size: u32, + ); + + let input_buf = [0u8; 256 * 1024]; + let address = [1u8; 20]; + + // Call the callee + api::call( + uapi::CallFlags::empty(), + &address, + u64::MAX, // How much ref_time to devote for the execution. u64::MAX = use all. + u64::MAX, // How much proof_size to devote for the execution. u64::MAX = use all. + &[u8::MAX; 32], // No deposit limit. + &[0; 32], // Value transferred to the contract. + &input_buf[..input_size as usize], + None, + ).unwrap(); +} diff --git a/substrate/frame/revive/fixtures/contracts/call_with_value.rs b/substrate/frame/revive/fixtures/contracts/call_with_value.rs new file mode 100644 index 0000000000000..cc8958e1f7112 --- /dev/null +++ b/substrate/frame/revive/fixtures/contracts/call_with_value.rs @@ -0,0 +1,49 @@ +// This file is part of Substrate. + +// Copyright (C) Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//! This calls another contract as passed as its account id. +#![no_std] +#![no_main] +include!("../panic_handler.rs"); + +use uapi::{input, HostFn, HostFnImpl as api}; + +#[no_mangle] +#[polkavm_derive::polkavm_export] +pub extern "C" fn deploy() {} + +#[no_mangle] +#[polkavm_derive::polkavm_export] +pub extern "C" fn call() { + input!( + value: &[u8; 32], + callee_addr: &[u8; 20], + ); + + // Call the callee + api::call( + uapi::CallFlags::empty(), + callee_addr, + u64::MAX, // How much ref_time to devote for the execution. u64::MAX = use all. + u64::MAX, // How much proof_size to devote for the execution. u64::MAX = use all. + &[u8::MAX; 32], // No deposit limit. + value, // Value transferred to the contract. + &[0u8; 0], // input + None, + ) + .unwrap(); +} diff --git a/substrate/frame/revive/fixtures/contracts/caller_contract.rs b/substrate/frame/revive/fixtures/contracts/caller_contract.rs index 8e1ab82b63ba6..79e2a4ee9a5c7 100644 --- a/substrate/frame/revive/fixtures/contracts/caller_contract.rs +++ b/substrate/frame/revive/fixtures/contracts/caller_contract.rs @@ -35,7 +35,7 @@ pub extern "C" fn call() { // The value to transfer on instantiation and calls. Chosen to be greater than existential // deposit. - let value = u256_bytes(32768u64); + let value = u256_bytes(32_768_000_000u64); let salt = [0u8; 32]; // Callee will use the first 4 bytes of the input to return an exit status. diff --git a/substrate/frame/revive/fixtures/contracts/create_storage_and_instantiate.rs b/substrate/frame/revive/fixtures/contracts/create_storage_and_instantiate.rs index fa679886c5d55..a7345adba1543 100644 --- a/substrate/frame/revive/fixtures/contracts/create_storage_and_instantiate.rs +++ b/substrate/frame/revive/fixtures/contracts/create_storage_and_instantiate.rs @@ -43,7 +43,7 @@ pub extern "C" fn call() { key[0] = 1; api::set_storage(StorageFlags::empty(), &key, data); - let value = u256_bytes(10_000u64); + let value = u256_bytes(10_000_000_000u64); let salt = [0u8; 32]; let mut address = [0u8; 20]; let mut deploy_input = [0; 32 + 4]; diff --git a/substrate/frame/revive/fixtures/contracts/crypto_hashes.rs b/substrate/frame/revive/fixtures/contracts/crypto_hashes.rs index 751f0c065b8f7..69f534a0655f4 100644 --- a/substrate/frame/revive/fixtures/contracts/crypto_hashes.rs +++ b/substrate/frame/revive/fixtures/contracts/crypto_hashes.rs @@ -44,7 +44,6 @@ pub extern "C" fn deploy() {} /// | value | Algorithm | Bit Width | /// |-------|-----------|-----------| /// | 2 | KECCAK | 256 | -/// | 3 | BLAKE2 | 256 | /// | 4 | BLAKE2 | 128 | /// --------------------------------- @@ -63,11 +62,6 @@ pub extern "C" fn call() { api::hash_keccak_256(input, &mut output); api::return_value(uapi::ReturnFlags::empty(), &output); }, - 3 => { - let mut output = [0u8; 32]; - api::hash_blake2_256(input, &mut output); - api::return_value(uapi::ReturnFlags::empty(), &output); - }, 4 => { let mut output = [0u8; 16]; api::hash_blake2_128(input, &mut output); diff --git a/substrate/frame/revive/fixtures/contracts/delegate_call_lib.rs b/substrate/frame/revive/fixtures/contracts/delegate_call_lib.rs index 2a3364f46c4a5..97f883b8456e7 100644 --- a/substrate/frame/revive/fixtures/contracts/delegate_call_lib.rs +++ b/substrate/frame/revive/fixtures/contracts/delegate_call_lib.rs @@ -40,7 +40,7 @@ pub extern "C" fn call() { // Assert that `value_transferred` is equal to the value // passed to the `caller` contract: 1337. let value = u64_output!(api::value_transferred,); - assert_eq!(value, 1337); + assert_eq!(value, 1337_000_000); // Assert that ALICE is the caller of the contract. let mut caller = [0u8; 20]; diff --git a/substrate/frame/revive/fixtures/contracts/destroy_and_transfer.rs b/substrate/frame/revive/fixtures/contracts/destroy_and_transfer.rs index 919dded0f060d..4ca300fdb0dcf 100644 --- a/substrate/frame/revive/fixtures/contracts/destroy_and_transfer.rs +++ b/substrate/frame/revive/fixtures/contracts/destroy_and_transfer.rs @@ -22,7 +22,7 @@ include!("../panic_handler.rs"); use uapi::{input, u256_bytes, HostFn, HostFnImpl as api, StorageFlags}; const ADDRESS_KEY: [u8; 32] = [0u8; 32]; -const VALUE: [u8; 32] = u256_bytes(65536); +const VALUE: [u8; 32] = u256_bytes(65_536_000_000); #[no_mangle] #[polkavm_derive::polkavm_export] diff --git a/substrate/frame/revive/fixtures/contracts/instantiate_return_code.rs b/substrate/frame/revive/fixtures/contracts/instantiate_return_code.rs index a1904415e88f4..3475accb5bdd9 100644 --- a/substrate/frame/revive/fixtures/contracts/instantiate_return_code.rs +++ b/substrate/frame/revive/fixtures/contracts/instantiate_return_code.rs @@ -35,7 +35,7 @@ pub extern "C" fn call() { * all. */ u64::MAX, // How much proof_size weight to devote for the execution. u64::MAX = use all. &[u8::MAX; 32], // No deposit limit. - &u256_bytes(10_000u64), // Value to transfer. + &u256_bytes(10_000_000_000u64), // Value to transfer. buffer, None, None, diff --git a/substrate/frame/revive/fixtures/contracts/oom_ro.rs b/substrate/frame/revive/fixtures/contracts/oom_ro.rs index 78c524f4f13d2..810940daf1ffa 100644 --- a/substrate/frame/revive/fixtures/contracts/oom_ro.rs +++ b/substrate/frame/revive/fixtures/contracts/oom_ro.rs @@ -25,7 +25,7 @@ include!("../panic_handler.rs"); use uapi::{HostFn, HostFnImpl as api, ReturnFlags}; -static BUFFER: [u8; 1025 * 1024] = [0; 1025 * 1024]; +static BUFFER: [u8; 1024 * 1024] = [0; 1024 * 1024]; #[no_mangle] #[polkavm_derive::polkavm_export] diff --git a/substrate/frame/revive/fixtures/contracts/oom_rw_included.rs b/substrate/frame/revive/fixtures/contracts/oom_rw_included.rs index 21d1a4afe3a89..13c5e8bc58a86 100644 --- a/substrate/frame/revive/fixtures/contracts/oom_rw_included.rs +++ b/substrate/frame/revive/fixtures/contracts/oom_rw_included.rs @@ -25,9 +25,9 @@ include!("../panic_handler.rs"); use uapi::{HostFn, HostFnImpl as api, ReturnFlags}; -static mut BUFFER: [u8; 513 * 1024] = [42; 513 * 1024]; +static mut BUFFER: [u8; 1024 * 1024] = [42; 1024 * 1024]; -unsafe fn buffer() -> &'static [u8; 513 * 1024] { +unsafe fn buffer() -> &'static [u8; 1024 * 1024] { let ptr = core::ptr::addr_of!(BUFFER); &*ptr } diff --git a/substrate/frame/revive/fixtures/contracts/oom_rw_trailing.rs b/substrate/frame/revive/fixtures/contracts/oom_rw_trailing.rs index fdb45e9fdaf96..8e8b070a943bf 100644 --- a/substrate/frame/revive/fixtures/contracts/oom_rw_trailing.rs +++ b/substrate/frame/revive/fixtures/contracts/oom_rw_trailing.rs @@ -25,9 +25,9 @@ include!("../panic_handler.rs"); use uapi::{HostFn, HostFnImpl as api, ReturnFlags}; -static mut BUFFER: [u8; 2 * 1025 * 1024] = [0; 2 * 1025 * 1024]; +static mut BUFFER: [u8; 2 * 1024 * 1024] = [0; 2 * 1024 * 1024]; -unsafe fn buffer() -> &'static [u8; 2 * 1025 * 1024] { +unsafe fn buffer() -> &'static [u8; 2 * 1024 * 1024] { let ptr = core::ptr::addr_of!(BUFFER); &*ptr } diff --git a/substrate/frame/revive/fixtures/contracts/recurse.rs b/substrate/frame/revive/fixtures/contracts/recurse.rs index b59f140d4e60d..e2ab9ba2e4bfc 100644 --- a/substrate/frame/revive/fixtures/contracts/recurse.rs +++ b/substrate/frame/revive/fixtures/contracts/recurse.rs @@ -21,7 +21,7 @@ #![no_main] include!("../panic_handler.rs"); -use uapi::{input, HostFn, HostFnImpl as api}; +use uapi::{input, HostFn, ReturnFlags, HostFnImpl as api}; #[no_mangle] #[polkavm_derive::polkavm_export] @@ -36,19 +36,20 @@ pub extern "C" fn call() { let mut addr = [0u8; 20]; api::address(&mut addr); - if calls_left == 0 { - return + let mut return_buffer = calls_left.to_le_bytes(); + + if calls_left > 0 { + let _ = api::call( + uapi::CallFlags::ALLOW_REENTRY, + &addr, + u64::MAX, // How much ref_time to devote for the execution. u64::MAX = use all resources. + u64::MAX, // How much proof_size to devote for the execution. u64::MAX = use all resources. + &[u8::MAX; 32], // No deposit limit. + &[0u8; 32], // Value transferred to the contract. + &(calls_left - 1).to_le_bytes(), + Some(&mut &mut return_buffer[..]), + ); } - api::call( - uapi::CallFlags::ALLOW_REENTRY, - &addr, - u64::MAX, // How much ref_time to devote for the execution. u64::MAX = use all resources. - u64::MAX, // How much proof_size to devote for the execution. u64::MAX = use all resources. - &[u8::MAX; 32], // No deposit limit. - &[0u8; 32], // Value transferred to the contract. - &(calls_left - 1).to_le_bytes(), - None, - ) - .unwrap(); + api::return_value(ReturnFlags::empty(), &return_buffer); } diff --git a/substrate/frame/revive/fixtures/contracts/return_data_api.rs b/substrate/frame/revive/fixtures/contracts/return_data_api.rs index 4066531b602a0..d2225b16cd028 100644 --- a/substrate/frame/revive/fixtures/contracts/return_data_api.rs +++ b/substrate/frame/revive/fixtures/contracts/return_data_api.rs @@ -86,7 +86,7 @@ fn assert_balance_transfer_does_reset() { u64::MAX, u64::MAX, &[u8::MAX; 32], - &u256_bytes(128), + &u256_bytes(128_000_000), &[], None, ) diff --git a/substrate/frame/revive/fixtures/contracts/return_sized.rs b/substrate/frame/revive/fixtures/contracts/return_sized.rs new file mode 100644 index 0000000000000..aee1130ec2151 --- /dev/null +++ b/substrate/frame/revive/fixtures/contracts/return_sized.rs @@ -0,0 +1,40 @@ +// This file is part of Substrate. + +// Copyright (C) Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#![no_std] +#![no_main] +include!("../panic_handler.rs"); + +polkavm_derive::min_stack_size!(512 * 1024); + +use uapi::{ReturnFlags, input, HostFn, HostFnImpl as api}; + +#[no_mangle] +#[polkavm_derive::polkavm_export] +pub extern "C" fn deploy() {} + +#[no_mangle] +#[polkavm_derive::polkavm_export] +pub extern "C" fn call() { + input!( + return_size: u32, + ); + + let return_buf = [42u8; 256 * 1024]; + api::return_value(ReturnFlags::empty(), &return_buf[..return_size as usize]) + +} diff --git a/substrate/frame/revive/src/address.rs b/substrate/frame/revive/src/address.rs index 928397ec63635..fcba05c99771f 100644 --- a/substrate/frame/revive/src/address.rs +++ b/substrate/frame/revive/src/address.rs @@ -62,6 +62,11 @@ pub trait AddressMapper: private::Sealed { /// `account_id` instead of the fallback account id. fn map(account_id: &T::AccountId) -> DispatchResult; + #[cfg(feature = "runtime-benchmarks")] + fn bench_map(account_id: &T::AccountId) -> DispatchResult { + Self::map(account_id) + } + /// Remove the mapping in order to reclaim the deposit. /// /// There is no reason why one would unmap their `account_id` except @@ -140,6 +145,14 @@ where Ok(()) } + /// Convenience function for benchmarking, to map an account id without taking any deposit. + #[cfg(feature = "runtime-benchmarks")] + fn bench_map(account_id: &T::AccountId) -> DispatchResult { + ensure!(!Self::is_mapped(account_id), >::AccountAlreadyMapped); + >::insert(Self::to_address(account_id), account_id); + Ok(()) + } + fn unmap(account_id: &T::AccountId) -> DispatchResult { // will do nothing if address is not mapped so no check required >::remove(Self::to_address(account_id)); @@ -192,7 +205,7 @@ where /// /// This is a stateless check that just compares the last 12 bytes. Please note that it is /// theoretically possible to create an ed25519 keypair that passed this filter. However, -/// this can't be used for an attack. It also won't happen by accident since everbody is using +/// this can't be used for an attack. It also won't happen by accident since everybody is using /// sr25519 where this is not a valid public key. pub fn is_eth_derived(account_id: &AccountId32) -> bool { let account_bytes: &[u8; 32] = account_id.as_ref(); diff --git a/substrate/frame/revive/src/benchmarking.rs b/substrate/frame/revive/src/benchmarking.rs index ed426967ea009..7a5b1c52b40a7 100644 --- a/substrate/frame/revive/src/benchmarking.rs +++ b/substrate/frame/revive/src/benchmarking.rs @@ -18,7 +18,6 @@ //! Benchmarks for the revive pallet. #![cfg(feature = "runtime-benchmarks")] - use crate::{ call_builder::{caller_funding, default_deposit_limit, CallSetup, Contract, VmBinaryModule}, evm::runtime::GAS_PRICE, @@ -26,13 +25,14 @@ use crate::{ limits, precompiles::{self, run::builtin as run_builtin_precompile}, storage::WriteOutcome, - ConversionPrecision, Pallet as Contracts, *, + Pallet as Contracts, *, }; use alloc::{vec, vec::Vec}; use codec::{Encode, MaxEncodedLen}; use frame_benchmarking::v2::*; use frame_support::{ self, assert_ok, + migrations::SteppedMigration, storage::child, traits::fungible::InspectHold, weights::{Weight, WeightMeter}, @@ -45,7 +45,10 @@ use sp_consensus_babe::{ BABE_ENGINE_ID, }; use sp_consensus_slots::Slot; -use sp_runtime::generic::{Digest, DigestItem}; +use sp_runtime::{ + generic::{Digest, DigestItem}, + traits::Zero, +}; /// How many runs we do per API benchmark. /// @@ -124,9 +127,7 @@ mod benchmarks { // is not in the first basic block is never read. We are primarily interested in the // `proof_size` result of this benchmark. #[benchmark(pov_mode = Measured)] - fn call_with_code_per_byte( - c: Linear<0, { limits::code::STATIC_MEMORY_BYTES / limits::code::BYTES_PER_INSTRUCTION }>, - ) -> Result<(), BenchmarkError> { + fn call_with_code_per_byte(c: Linear<0, { 100 * 1024 }>) -> Result<(), BenchmarkError> { let instance = Contract::::with_caller(whitelisted_caller(), VmBinaryModule::sized(c), vec![])?; let value = Pallet::::min_balance(); @@ -184,8 +185,8 @@ mod benchmarks { // `i`: Size of the input in bytes. #[benchmark(pov_mode = Measured)] fn instantiate_with_code( - c: Linear<0, { limits::code::STATIC_MEMORY_BYTES / limits::code::BYTES_PER_INSTRUCTION }>, - i: Linear<0, { limits::code::BLOB_BYTES }>, + c: Linear<0, { 100 * 1024 }>, + i: Linear<0, { limits::CALLDATA_BYTES }>, ) { let input = vec![42u8; i as usize]; let salt = [42u8; 32]; @@ -220,10 +221,65 @@ mod benchmarks { assert_eq!(T::Currency::balance(&account_id), value + Pallet::::min_balance()); } + // `c`: Size of the code in bytes. + // `i`: Size of the input in bytes. + // `d`: with or without dust value to transfer + #[benchmark(pov_mode = Measured)] + fn eth_instantiate_with_code( + c: Linear<0, { 100 * 1024 }>, + i: Linear<0, { limits::CALLDATA_BYTES }>, + d: Linear<0, 1>, + ) { + let input = vec![42u8; i as usize]; + + let value = Pallet::::min_balance(); + let dust = 42u32 * d; + let evm_value = + Pallet::::convert_native_to_evm(BalanceWithDust::new_unchecked::(value, dust)); + + let caller = whitelisted_caller(); + T::Currency::set_balance(&caller, caller_funding::()); + let VmBinaryModule { code, .. } = VmBinaryModule::sized(c); + let origin = RawOrigin::Signed(caller.clone()); + Contracts::::map_account(origin.clone().into()).unwrap(); + let deployer = T::AddressMapper::to_address(&caller); + let nonce = System::::account_nonce(&caller).try_into().unwrap_or_default(); + let addr = crate::address::create1(&deployer, nonce); + let account_id = T::AddressMapper::to_fallback_account_id(&addr); + let storage_deposit = default_deposit_limit::(); + + assert!(AccountInfoOf::::get(&deployer).is_none()); + + #[extrinsic_call] + _(origin, evm_value, Weight::MAX, storage_deposit, code, input); + + let deposit = + T::Currency::balance_on_hold(&HoldReason::StorageDepositReserve.into(), &account_id); + // uploading the code reserves some balance in the callers account + let code_deposit = + T::Currency::balance_on_hold(&HoldReason::CodeUploadDepositReserve.into(), &caller); + let mapping_deposit = + T::Currency::balance_on_hold(&HoldReason::AddressMapping.into(), &caller); + + assert_eq!( + Pallet::::evm_balance(&deployer), + Pallet::::convert_native_to_evm( + caller_funding::() - + Pallet::::min_balance() - + Pallet::::min_balance() - + value - deposit - code_deposit - + mapping_deposit, + ) - dust, + ); + + // contract has the full value + assert_eq!(Pallet::::evm_balance(&addr), evm_value); + } + // `i`: Size of the input in bytes. // `s`: Size of e salt in bytes. #[benchmark(pov_mode = Measured)] - fn instantiate(i: Linear<0, { limits::code::BLOB_BYTES }>) -> Result<(), BenchmarkError> { + fn instantiate(i: Linear<0, { limits::CALLDATA_BYTES }>) -> Result<(), BenchmarkError> { let input = vec![42u8; i as usize]; let salt = [42u8; 32]; let value = Pallet::::min_balance(); @@ -306,13 +362,59 @@ mod benchmarks { Ok(()) } + // `d`: with or without dust value to transfer + #[benchmark(pov_mode = Measured)] + fn eth_call(d: Linear<0, 1>) -> Result<(), BenchmarkError> { + let data = vec![42u8; 1024]; + let instance = + Contract::::with_caller(whitelisted_caller(), VmBinaryModule::dummy(), vec![])?; + + let value = Pallet::::min_balance(); + let dust = 42u32 * d; + let evm_value = + Pallet::::convert_native_to_evm(BalanceWithDust::new_unchecked::(value, dust)); + + let caller_addr = T::AddressMapper::to_address(&instance.caller); + let origin = RawOrigin::Signed(instance.caller.clone()); + let before = Pallet::::evm_balance(&instance.address); + let storage_deposit = default_deposit_limit::(); + #[extrinsic_call] + _(origin, instance.address, evm_value, Weight::MAX, storage_deposit, data); + let deposit = T::Currency::balance_on_hold( + &HoldReason::StorageDepositReserve.into(), + &instance.account_id, + ); + let code_deposit = T::Currency::balance_on_hold( + &HoldReason::CodeUploadDepositReserve.into(), + &instance.caller, + ); + let mapping_deposit = + T::Currency::balance_on_hold(&HoldReason::AddressMapping.into(), &instance.caller); + // value and value transferred via call should be removed from the caller + assert_eq!( + Pallet::::evm_balance(&caller_addr), + Pallet::::convert_native_to_evm( + caller_funding::() - + Pallet::::min_balance() - + Pallet::::min_balance() - + value - deposit - code_deposit - + mapping_deposit, + ) - dust, + ); + + // contract should have received the value + assert_eq!(Pallet::::evm_balance(&instance.address), before + evm_value); + // contract should still exist + instance.info()?; + + Ok(()) + } + // This constructs a contract that is maximal expensive to instrument. // It creates a maximum number of metering blocks per byte. // `c`: Size of the code in bytes. #[benchmark(pov_mode = Measured)] - fn upload_code( - c: Linear<0, { limits::code::STATIC_MEMORY_BYTES / limits::code::BYTES_PER_INSTRUCTION }>, - ) { + fn upload_code(c: Linear<0, { 100 * 1024 }>) { let caller = whitelisted_caller(); T::Currency::set_balance(&caller, caller_funding::()); let VmBinaryModule { code, hash, .. } = VmBinaryModule::sized(c); @@ -601,23 +703,37 @@ mod benchmarks { #[benchmark(pov_mode = Measured)] fn seal_balance() { - build_runtime!(runtime, memory: [[0u8;32], ]); + build_runtime!(runtime, contract, memory: [[0u8;32], ]); + contract.set_balance(BalanceWithDust::new_unchecked::( + Pallet::::min_balance() * 2u32.into(), + 42u32, + )); + let result; #[block] { result = runtime.bench_balance(memory.as_mut_slice(), 0); } assert_ok!(result); - assert_eq!(U256::from_little_endian(&memory[..]), runtime.ext().balance()); + assert_eq!( + U256::from_little_endian(&memory[..]), + Pallet::::convert_native_to_evm(BalanceWithDust::new_unchecked::( + Pallet::::min_balance(), + 42 + )) + ); } #[benchmark(pov_mode = Measured)] fn seal_balance_of() { let len = ::max_encoded_len(); let account = account::("target", 0, 0); + ::AddressMapper::bench_map(&account).unwrap(); + let address = T::AddressMapper::to_address(&account); let balance = Pallet::::min_balance() * 2u32.into(); T::Currency::set_balance(&account, balance); + AccountInfoOf::::insert(&address, AccountInfo { dust: 42, ..Default::default() }); build_runtime!(runtime, memory: [vec![0u8; len], address.0, ]); @@ -628,7 +744,13 @@ mod benchmarks { } assert_ok!(result); - assert_eq!(U256::from_little_endian(&memory[..len]), runtime.ext().balance_of(&address)); + assert_eq!( + U256::from_little_endian(&memory[..len]), + Pallet::::convert_native_to_evm(BalanceWithDust::new_unchecked::( + Pallet::::min_balance(), + 42 + )) + ); } #[benchmark(pov_mode = Measured)] @@ -933,7 +1055,7 @@ mod benchmarks { } #[benchmark(pov_mode = Measured)] - fn seal_return(n: Linear<0, { limits::code::BLOB_BYTES - 4 }>) { + fn seal_return(n: Linear<0, { limits::CALLDATA_BYTES }>) { build_runtime!(runtime, memory: [n.to_le_bytes(), vec![42u8; n as usize], ]); let result; @@ -1543,16 +1665,21 @@ mod benchmarks { } // t: with or without some value to transfer + // d: with or without dust value to transfer // i: size of the input data #[benchmark(pov_mode = Measured)] - fn seal_call(t: Linear<0, 1>, i: Linear<0, { limits::code::BLOB_BYTES }>) { - let Contract { account_id: callee, .. } = + fn seal_call(t: Linear<0, 1>, d: Linear<0, 1>, i: Linear<0, { limits::code::BLOB_BYTES }>) { + let Contract { account_id: callee, address: callee_addr, .. } = Contract::::with_index(1, VmBinaryModule::dummy(), vec![]).unwrap(); + let callee_bytes = callee.encode(); let callee_len = callee_bytes.len() as u32; - let value: BalanceOf = (1_000_000 * t).into(); - let value_bytes = Into::::into(value).encode(); + let value: BalanceOf = (1_000_000u32 * t).into(); + let dust = 100u32 * d; + let evm_value = + Pallet::::convert_native_to_evm(BalanceWithDust::new_unchecked::(value, dust)); + let value_bytes = evm_value.encode(); let deposit: BalanceOf = (u32::MAX - 100).into(); let deposit_bytes = Into::::into(deposit).encode(); @@ -1564,6 +1691,7 @@ mod benchmarks { // This is why we set the input here instead of passig it as pointer to the `bench_call`. setup.set_data(vec![42; i as usize]); setup.set_origin(Origin::from_account_id(setup.contract().account_id.clone())); + setup.set_balance(value + 1u32.into() + Pallet::::min_balance()); let (mut ext, _) = setup.ext(); let mut runtime = crate::vm::Runtime::<_, [u8]>::new(&mut ext, vec![]); @@ -1583,13 +1711,18 @@ mod benchmarks { ); } - assert_ok!(result); + assert_eq!(result.unwrap(), ReturnErrorCode::Success); + assert_eq!( + Pallet::::evm_balance(&callee_addr), + evm_value, + "{callee_addr:?} balance should hold {evm_value:?}" + ); } // d: 1 if the associated pre-compile has a contract info that needs to be loaded // i: size of the input data #[benchmark(pov_mode = Measured)] - fn seal_call_precompile(d: Linear<0, 1>, i: Linear<0, { limits::code::BLOB_BYTES }>) { + fn seal_call_precompile(d: Linear<0, 1>, i: Linear<0, { limits::CALLDATA_BYTES - 100 }>) { use alloy_core::sol_types::SolInterface; use precompiles::{BenchmarkNoInfo, BenchmarkWithInfo, BuiltinPrecompile, IBenchmarking}; @@ -1609,7 +1742,7 @@ mod benchmarks { let value_len = value_bytes.len() as u32; let input_bytes = IBenchmarking::IBenchmarkingCalls::bench(IBenchmarking::benchCall { - input: vec![42; i as usize].into(), + input: vec![42_u8; i as usize].into(), }) .abi_encode(); let input_len = input_bytes.len() as u32; @@ -1681,20 +1814,28 @@ mod benchmarks { ); } - assert_ok!(result); + assert_eq!(result.unwrap(), ReturnErrorCode::Success); Ok(()) } - // t: value to transfer - // i: size of input in bytes + // t: with or without some value to transfer + // d: with or without dust value to transfer + // i: size of the input data #[benchmark(pov_mode = Measured)] - fn seal_instantiate(i: Linear<0, { limits::code::BLOB_BYTES }>) -> Result<(), BenchmarkError> { + fn seal_instantiate( + t: Linear<0, 1>, + d: Linear<0, 1>, + i: Linear<0, { limits::CALLDATA_BYTES }>, + ) -> Result<(), BenchmarkError> { let code = VmBinaryModule::dummy(); let hash = Contract::::with_index(1, VmBinaryModule::dummy(), vec![])?.info()?.code_hash; let hash_bytes = hash.encode(); - let value: BalanceOf = 1_000_000u32.into(); - let value_bytes = Into::::into(value).encode(); + let value: BalanceOf = (1_000_000u32 * t).into(); + let dust = 100u32 * d; + let evm_value = + Pallet::::convert_native_to_evm(BalanceWithDust::new_unchecked::(value, dust)); + let value_bytes = evm_value.encode(); let value_len = value_bytes.len() as u32; let deposit: BalanceOf = BalanceOf::::max_value(); @@ -1703,7 +1844,7 @@ mod benchmarks { let mut setup = CallSetup::::default(); setup.set_origin(Origin::from_account_id(setup.contract().account_id.clone())); - setup.set_balance(value + (Pallet::::min_balance() * 2u32.into())); + setup.set_balance(value + 1u32.into() + (Pallet::::min_balance() * 2u32.into())); let account_id = &setup.contract().account_id.clone(); let (mut ext, _) = setup.ext(); @@ -1714,7 +1855,6 @@ mod benchmarks { let salt = [42u8; 32]; let deployer = T::AddressMapper::to_address(&account_id); let addr = crate::address::create2(&deployer, &code.code, &input, &salt); - let account_id = T::AddressMapper::to_fallback_account_id(&addr); let mut memory = memory!(hash_bytes, input, deposit_bytes, value_bytes, salt,); let mut offset = { @@ -1725,7 +1865,7 @@ mod benchmarks { } }; - assert!(ContractInfoOf::::get(&addr).is_none()); + assert!(AccountInfoOf::::get(&addr).is_none()); let result; #[block] @@ -1734,20 +1874,20 @@ mod benchmarks { memory.as_mut_slice(), u64::MAX, // ref_time_limit u64::MAX, // proof_size_limit - pack_hi_lo(offset(input_len), offset(deposit_len)), // deopsit_ptr + value_ptr + pack_hi_lo(offset(input_len), offset(deposit_len)), // deposit_ptr + value_ptr pack_hi_lo(input_len, 0), // input_data_len + input_data pack_hi_lo(0, SENTINEL), // output_len_ptr + output_ptr pack_hi_lo(SENTINEL, offset(value_len)), // address_ptr + salt_ptr ); } - assert_ok!(result); - assert!(ContractInfoOf::::get(&addr).is_some()); + assert_eq!(result.unwrap(), ReturnErrorCode::Success); + assert!(AccountInfo::::load_contract(&addr).is_some()); + assert_eq!( - T::Currency::balance(&account_id), - Pallet::::min_balance() + - Pallet::::convert_evm_to_native(value.into(), ConversionPrecision::Exact) - .unwrap() + Pallet::::evm_balance(&addr), + evm_value, + "{addr:?} balance should hold {evm_value:?}" ); Ok(()) } @@ -1828,16 +1968,29 @@ mod benchmarks { // `n`: Input to hash in bytes #[benchmark(pov_mode = Measured)] - fn seal_hash_blake2_256(n: Linear<0, { limits::code::BLOB_BYTES }>) { - build_runtime!(runtime, memory: [[0u8; 32], vec![0u8; n as usize], ]); + fn hash_blake2_256(n: Linear<0, { limits::code::BLOB_BYTES }>) { + use crate::precompiles::{BenchmarkSystem, BuiltinPrecompile, ISystem}; + use alloy_core::sol_types::SolInterface; + + let input = vec![0u8; n as usize]; + let input_bytes = ISystem::ISystemCalls::hashBlake256(ISystem::hashBlake256Call { + input: input.clone().into(), + }) + .abi_encode(); + + let mut call_setup = CallSetup::::default(); + let (mut ext, _) = call_setup.ext(); let result; #[block] { - result = runtime.bench_hash_blake2_256(memory.as_mut_slice(), 32, n, 0); + result = run_builtin_precompile( + &mut ext, + H160(BenchmarkSystem::::MATCHER.base_address()).as_fixed_bytes(), + input_bytes, + ); } - assert_eq!(sp_io::hashing::blake2_256(&memory[32..]), &memory[0..32]); - assert_ok!(result); + assert_eq!(sp_io::hashing::blake2_256(&input).to_vec(), result.unwrap().data); } // `n`: Input to hash in bytes @@ -2130,6 +2283,28 @@ mod benchmarks { } } + #[benchmark] + fn v1_migration_step() { + use crate::migrations::v1; + let addr = H160::from([1u8; 20]); + let contract_info = ContractInfo::new(&addr, 1u32.into(), Default::default()).unwrap(); + + v1::old::ContractInfoOf::::insert(addr, contract_info.clone()); + let mut meter = WeightMeter::new(); + assert_eq!(AccountInfo::::load_contract(&addr), None); + + #[block] + { + v1::Migration::::step(None, &mut meter).unwrap(); + } + + assert_eq!(v1::old::ContractInfoOf::::get(&addr), None); + assert_eq!(AccountInfo::::load_contract(&addr).unwrap(), contract_info); + + // uses twice the weight once for migration and then for checking if there is another key. + assert_eq!(meter.consumed(), ::WeightInfo::v1_migration_step() * 2); + } + impl_benchmark_test_suite!( Contracts, crate::tests::ExtBuilder::default().build(), diff --git a/substrate/frame/revive/src/call_builder.rs b/substrate/frame/revive/src/call_builder.rs index af9e1e1ca8d07..683cd5d5db803 100644 --- a/substrate/frame/revive/src/call_builder.rs +++ b/substrate/frame/revive/src/call_builder.rs @@ -32,14 +32,15 @@ use crate::{ storage::meter::Meter, transient_storage::MeterEntry, vm::{PreparedCall, Runtime}, - BalanceOf, BumpNonce, Code, CodeInfoOf, Config, ContractBlob, ContractInfo, ContractInfoOf, - DepositLimit, Error, GasMeter, MomentOf, Origin, Pallet as Contracts, PristineCode, Weight, + AccountInfo, BalanceOf, BalanceWithDust, BumpNonce, Code, CodeInfoOf, Config, ContractBlob, + ContractInfo, DepositLimit, Error, GasMeter, MomentOf, Origin, Pallet as Contracts, + PristineCode, Weight, }; use alloc::{vec, vec::Vec}; use frame_support::{storage::child, traits::fungible::Mutate}; use frame_system::RawOrigin; use pallet_revive_fixtures::bench as bench_fixtures; -use sp_core::{Get, H160, H256, U256}; +use sp_core::{H160, H256, U256}; use sp_io::hashing::keccak_256; use sp_runtime::traits::{Bounded, Hash}; @@ -94,7 +95,7 @@ where // Whitelist the contract's contractInfo as it is already accounted for in the call // benchmark frame_benchmarking::benchmarking::add_to_whitelist( - crate::ContractInfoOf::::hashed_key_for(&T::AddressMapper::to_address( + crate::AccountInfoOf::::hashed_key_for(&T::AddressMapper::to_address( &contract.account_id, )) .into(), @@ -124,7 +125,7 @@ where } /// Set the contract's balance. - pub fn set_balance(&mut self, value: BalanceOf) { + pub fn set_balance(&mut self, value: impl Into>>) { self.contract.set_balance(value); } @@ -202,8 +203,7 @@ where /// The deposit limit we use for benchmarks. pub fn default_deposit_limit() -> BalanceOf { - (T::DepositPerByte::get() * 1024u32.into() * 1024u32.into()) + - T::DepositPerItem::get() * 1024u32.into() + >::max_value() } /// The funding that each account that either calls or instantiates contracts is funded with. @@ -264,7 +264,7 @@ where let outcome = Contracts::::bare_instantiate( origin, - 0u32.into(), + U256::zero(), Weight::MAX, DepositLimit::Balance(default_deposit_limit::()), Code::Upload(module.code), @@ -277,8 +277,7 @@ where let account_id = T::AddressMapper::to_fallback_account_id(&address); let result = Contract { caller, address, account_id }; - ContractInfoOf::::insert(&address, result.info()?); - + AccountInfo::::insert_contract(&address, result.info()?); Ok(result) } @@ -309,7 +308,8 @@ where info.write(&Key::Fix(item.0), Some(item.1.clone()), None, false) .map_err(|_| "Failed to write storage to restoration dest")?; } - >::insert(&self.address, info); + + AccountInfo::::insert_contract(&self.address, info); Ok(()) } @@ -351,7 +351,7 @@ where /// Get the `ContractInfo` of the `addr` or an error if it no longer exists. pub fn address_info(addr: &T::AccountId) -> Result, &'static str> { - ContractInfoOf::::get(T::AddressMapper::to_address(addr)) + >::load_contract(&T::AddressMapper::to_address(addr)) .ok_or("Expected contract to exist at this point.") } @@ -361,8 +361,12 @@ where } /// Set the balance of the contract to the supplied amount. - pub fn set_balance(&self, balance: BalanceOf) { - T::Currency::set_balance(&self.account_id, balance); + pub fn set_balance(&self, value: impl Into>>) { + let (value, dust) = value.into().deconstruct(); + T::Currency::set_balance(&self.account_id, value); + crate::AccountInfoOf::::mutate(&self.address, |account| { + account.as_mut().map(|a| a.dust = dust); + }); } /// Returns `true` iff all storage entries related to code storage exist. diff --git a/substrate/frame/revive/src/evm/runtime.rs b/substrate/frame/revive/src/evm/runtime.rs index 342b29f5158fa..48380f83899bd 100644 --- a/substrate/frame/revive/src/evm/runtime.rs +++ b/substrate/frame/revive/src/evm/runtime.rs @@ -20,8 +20,8 @@ use crate::{ api::{GenericTransaction, TransactionSigned}, GasEncoder, }, - AccountIdOf, AddressMapper, BalanceOf, Config, ConversionPrecision, MomentOf, - OnChargeTransactionBalanceOf, Pallet, LOG_TARGET, RUNTIME_PALLETS_ADDR, + AccountIdOf, AddressMapper, BalanceOf, Config, MomentOf, OnChargeTransactionBalanceOf, Pallet, + LOG_TARGET, RUNTIME_PALLETS_ADDR, }; use alloc::vec::Vec; use codec::{Decode, DecodeLimit, DecodeWithMemTracking, Encode}; @@ -313,15 +313,7 @@ pub trait EthExtra { return Err(InvalidTransaction::Call); } - let value = crate::Pallet::::convert_evm_to_native( - value.unwrap_or_default(), - ConversionPrecision::Exact, - ) - .map_err(|err| { - log::debug!(target: LOG_TARGET, "Failed to convert value to native: {err:?}"); - InvalidTransaction::Call - })?; - + let value = value.unwrap_or_default(); let data = input.to_vec(); let (gas_limit, storage_deposit_limit) = @@ -341,14 +333,14 @@ pub trait EthExtra { InvalidTransaction::Call })?; - if value != 0u32.into() { + if !value.is_zero() { log::debug!(target: LOG_TARGET, "Runtime pallets address cannot be called with value"); return Err(InvalidTransaction::Call) } call } else { - crate::Call::call:: { + crate::Call::eth_call:: { dest, value, gas_limit, @@ -604,9 +596,9 @@ mod test { assert_eq!( call, - crate::Call::call:: { + crate::Call::eth_call:: { dest: tx.to.unwrap(), - value: tx.value.unwrap_or_default().as_u64(), + value: tx.value.unwrap_or_default().as_u64().into(), data: tx.input.to_vec(), gas_limit, storage_deposit_limit @@ -627,7 +619,7 @@ mod test { assert_eq!( call, crate::Call::eth_instantiate_with_code:: { - value: tx.value.unwrap_or_default().as_u64(), + value: tx.value.unwrap_or_default().as_u64().into(), code, data, gas_limit, diff --git a/substrate/frame/revive/src/evm/tracing/prestate_tracing.rs b/substrate/frame/revive/src/evm/tracing/prestate_tracing.rs index ded073a5aa3b4..6afbf3dd56fc3 100644 --- a/substrate/frame/revive/src/evm/tracing/prestate_tracing.rs +++ b/substrate/frame/revive/src/evm/tracing/prestate_tracing.rs @@ -17,7 +17,7 @@ use crate::{ evm::{Bytes, PrestateTrace, PrestateTraceInfo, PrestateTracerConfig}, tracing::Tracing, - BalanceOf, Bounded, Code, Config, ContractInfoOf, ExecReturnValue, Key, MomentOf, Pallet, + AccountInfo, BalanceOf, Bounded, Code, Config, ExecReturnValue, Key, MomentOf, Pallet, PristineCode, Weight, }; use alloc::{collections::BTreeMap, vec::Vec}; @@ -140,7 +140,7 @@ where { /// Get the code of the contract. fn bytecode(address: &H160) -> Option { - let code_hash = ContractInfoOf::::get(address)?.code_hash; + let code_hash = AccountInfo::::load_contract(address)?.code_hash; let code: Vec = PristineCode::::get(&code_hash)?.into(); return Some(code.into()) } diff --git a/substrate/frame/revive/src/exec.rs b/substrate/frame/revive/src/exec.rs index 339e888b5aaba..6bf2f47d66940 100644 --- a/substrate/frame/revive/src/exec.rs +++ b/substrate/frame/revive/src/exec.rs @@ -22,11 +22,12 @@ use crate::{ precompiles::{All as AllPrecompiles, Instance as PrecompileInstance, Precompiles}, primitives::{BumpNonce, ExecReturnValue, StorageDeposit}, runtime_decl_for_revive_api::{Decode, Encode, RuntimeDebugNoBound, TypeInfo}, - storage::{self, meter::Diff, WriteOutcome}, + storage::{self, meter::Diff, AccountIdOrAddress, WriteOutcome}, tracing::if_tracing, transient_storage::TransientStorage, - BalanceOf, CodeInfo, CodeInfoOf, Config, ContractInfo, ContractInfoOf, ConversionPrecision, - Error, Event, ImmutableData, ImmutableDataOf, Pallet as Contracts, RuntimeCosts, + AccountInfo, AccountInfoOf, BalanceOf, BalanceWithDust, CodeInfo, CodeInfoOf, Config, + ContractInfo, Error, Event, ImmutableData, ImmutableDataOf, Pallet as Contracts, RuntimeCosts, + LOG_TARGET, }; use alloc::vec::Vec; use core::{fmt::Debug, marker::PhantomData, mem}; @@ -36,7 +37,7 @@ use frame_support::{ storage::{with_transaction, TransactionOutcome}, traits::{ fungible::{Inspect, Mutate}, - tokens::{Fortitude, Preservation}, + tokens::{Fortitude, Precision, Preservation}, Time, }, weights::Weight, @@ -49,7 +50,7 @@ use frame_system::{ use sp_core::{ ecdsa::Public as ECDSAPublic, sr25519::{Public as SR25519Public, Signature as SR25519Signature}, - ConstU32, H160, H256, U256, + ConstU32, Get, H160, H256, U256, }; use sp_io::{crypto::secp256k1_ecdsa_recover_compressed, hashing::blake2_256}; use sp_runtime::{ @@ -708,8 +709,9 @@ impl CachedContract { /// Load the `contract_info` from storage if necessary. fn load(&mut self, account_id: &T::AccountId) { if let CachedContract::Invalidated = self { - let contract = >::get(T::AddressMapper::to_address(account_id)); - if let Some(contract) = contract { + if let Some(contract) = + AccountInfo::::load_contract(&T::AddressMapper::to_address(account_id)) + { *self = CachedContract::Cached(contract); } } @@ -928,13 +930,13 @@ where let mut contract = match (cached_info, &precompile) { (Some(info), _) => CachedContract::Cached(info), (None, None) => - if let Some(info) = >::get(&address) { + if let Some(info) = AccountInfo::::load_contract(&address) { CachedContract::Cached(info) } else { return Ok(None); }, (None, Some(precompile)) if precompile.has_contract_info() => { - if let Some(info) = >::get(&address) { + if let Some(info) = AccountInfo::::load_contract(&address) { CachedContract::Cached(info) } else { let info = ContractInfo::new(&address, 0u32.into(), H256::zero())?; @@ -954,7 +956,8 @@ where _phantom: Default::default(), } } else { - let Some(info) = ContractInfoOf::::get(&delegated_call.callee) else { + let Some(info) = AccountInfo::::load_contract(&delegated_call.callee) + else { return Ok(None); }; let executable = E::from_storage(info.code_hash, gas_meter)?; @@ -1050,8 +1053,8 @@ where if let (CachedContract::Cached(contract), ExportedFunction::Call) = (&frame.contract_info, frame.entry_point) { - >::insert( - T::AddressMapper::to_address(&frame.account_id), + AccountInfo::::insert_contract( + &T::AddressMapper::to_address(&frame.account_id), contract.clone(), ); } @@ -1119,6 +1122,13 @@ where let frame = top_frame_mut!(self); let account_id = &frame.account_id.clone(); + if u32::try_from(input_data.len()) + .map(|len| len > limits::CALLDATA_BYTES) + .unwrap_or(true) + { + Err(>::CallDataTooLarge)?; + } + // We need to make sure that the contract's account exists before calling its // constructor. if entry_point == ExportedFunction::Constructor { @@ -1127,7 +1137,7 @@ where let origin = &self.origin.account_id()?; let ed = >::min_balance(); - frame.nested_storage.record_charge(&StorageDeposit::Charge(ed)); + frame.nested_storage.record_charge(&StorageDeposit::Charge(ed))?; if self.skip_transfer { T::Currency::set_balance(account_id, ed); } else { @@ -1201,6 +1211,15 @@ where ExecutableOrPrecompile::Precompile { instance, .. } => instance.call(input_data, self), } + .and_then(|output| { + if u32::try_from(output.data.len()) + .map(|len| len > limits::CALLDATA_BYTES) + .unwrap_or(true) + { + Err(>::ReturnDataTooLarge)?; + } + Ok(output) + }) .map_err(|e| ExecError { error: e.error, origin: ErrorOrigin::Callee })?; // Avoid useless work that would be reverted anyways. @@ -1278,6 +1297,8 @@ where self.transient_storage.rollback_transaction(); } + log::trace!(target: LOG_TARGET, "frame finished with: {output:?}"); + self.pop_frame(success); output.map(|output| { self.top_frame_mut().last_frame_output = output; @@ -1331,7 +1352,10 @@ where // because that case is already handled by the optimization above. Only the first // cache needs to be invalidated because that one will invalidate the next cache // when it is popped from the stack. - >::insert(T::AddressMapper::to_address(account_id), contract); + AccountInfo::::insert_contract( + &T::AddressMapper::to_address(account_id), + contract, + ); if let Some(f) = self.frames_mut().skip(1).find(|f| f.account_id == *account_id) { f.contract_info.invalidate(); } @@ -1348,9 +1372,9 @@ where contract.as_deref_mut(), ); if let Some(contract) = contract { - >::insert( - T::AddressMapper::to_address(&self.first_frame.account_id), - contract, + AccountInfo::::insert_contract( + &T::AddressMapper::to_address(&self.first_frame.account_id), + contract.clone(), ); } } @@ -1374,33 +1398,103 @@ where to: &T::AccountId, value: U256, storage_meter: &mut storage::meter::GenericMeter, - ) -> ExecResult { - let value = crate::Pallet::::convert_evm_to_native(value, ConversionPrecision::Exact)?; + ) -> DispatchResult { + fn transfer_with_dust( + from: &AccountIdOf, + to: &AccountIdOf, + value: BalanceWithDust>, + ) -> DispatchResult { + let (value, dust) = value.deconstruct(); + + fn transfer_balance( + from: &AccountIdOf, + to: &AccountIdOf, + value: BalanceOf, + ) -> DispatchResult { + T::Currency::transfer(from, to, value, Preservation::Preserve) + .map_err(|err| { + log::debug!(target: crate::LOG_TARGET, "Transfer failed: from {from:?} to {to:?} (value: ${value:?}). Err: {err:?}"); + Error::::TransferFailed + })?; + Ok(()) + } + + fn transfer_dust( + from: &mut AccountInfo, + to: &mut AccountInfo, + dust: u32, + ) -> DispatchResult { + from.dust = + from.dust.checked_sub(dust).ok_or_else(|| Error::::TransferFailed)?; + to.dust = to.dust.checked_add(dust).ok_or_else(|| Error::::TransferFailed)?; + Ok(()) + } + + if dust.is_zero() { + return transfer_balance::(from, to, value) + } + + let from_addr = >::to_address(from); + let mut from_info = AccountInfoOf::::get(&from_addr).unwrap_or_default(); + + let to_addr = >::to_address(to); + let mut to_info = AccountInfoOf::::get(&to_addr).unwrap_or_default(); + + let plank = T::NativeToEthRatio::get(); + + if from_info.dust < dust { + T::Currency::burn_from( + from, + 1u32.into(), + Preservation::Preserve, + Precision::Exact, + Fortitude::Polite, + ) + .map_err(|err| { + log::debug!(target: crate::LOG_TARGET, "Burning 1 plank from {from:?} failed. Err: {err:?}"); + Error::::TransferFailed + })?; + + from_info.dust = + from_info.dust.checked_add(plank).ok_or_else(|| Error::::TransferFailed)?; + } + + transfer_balance::(from, to, value)?; + transfer_dust::(&mut from_info, &mut to_info, dust)?; + + if to_info.dust >= plank { + T::Currency::mint_into(to, 1u32.into())?; + to_info.dust = + to_info.dust.checked_sub(plank).ok_or_else(|| Error::::TransferFailed)?; + } + + AccountInfoOf::::set(&from_addr, Some(from_info)); + AccountInfoOf::::set(&to_addr, Some(to_info)); + + Ok(()) + } + + let value = BalanceWithDust::>::from_value::(value)?; if value.is_zero() { - return Ok(Default::default()); + return Ok(()); } if >::account_exists(to) { - return T::Currency::transfer(from, to, value, Preservation::Preserve) - .map(|_| Default::default()) - .map_err(|_| Error::::TransferFailed.into()); + return transfer_with_dust::(from, to, value) } let origin = origin.account_id()?; let ed = ::Currency::minimum_balance(); - with_transaction(|| -> TransactionOutcome { - match T::Currency::transfer(origin, to, ed, Preservation::Preserve) - .map_err(|_| Error::::StorageDepositNotEnoughFunds.into()) + with_transaction(|| -> TransactionOutcome { + match storage_meter + .record_charge(&StorageDeposit::Charge(ed)) .and_then(|_| { - T::Currency::transfer(from, to, value, Preservation::Preserve) - .map_err(|_| Error::::TransferFailed.into()) - }) { - Ok(_) => { - // ed is taken from the transaction signer so it should be - // limited by the storage deposit - storage_meter.record_charge(&StorageDeposit::Charge(ed)); - TransactionOutcome::Commit(Ok(Default::default())) - }, + T::Currency::transfer(origin, to, ed, Preservation::Preserve) + .map_err(|_| Error::::StorageDepositNotEnoughFunds.into()) + }) + .and_then(|_| transfer_with_dust::(from, to, value)) + { + Ok(_) => TransactionOutcome::Commit(Ok(())), Err(err) => TransactionOutcome::Rollback(Err(err)), } }) @@ -1422,6 +1516,8 @@ where Origin::Root => return Err(DispatchError::RootNotAllowed.into()), }; Self::transfer(origin, from, to, value, storage_meter) + .map(|_| Default::default()) + .map_err(Into::into) } /// Reference to the current (top) frame. @@ -1459,11 +1555,8 @@ where /// Returns the *free* balance of the supplied AccountId. fn account_balance(&self, who: &T::AccountId) -> U256 { - crate::Pallet::::convert_native_to_evm(T::Currency::reducible_balance( - who, - Preservation::Preserve, - Fortitude::Polite, - )) + let balance = AccountInfo::::balance(AccountIdOrAddress::AccountId(who.clone())); + crate::Pallet::::convert_native_to_evm(balance) } /// Certain APIs, e.g. `{set,get}_immutable_data` behave differently depending @@ -1550,7 +1643,7 @@ where info.queue_trie_for_deletion(); let account_address = T::AddressMapper::to_address(&frame.account_id); - ContractInfoOf::::remove(&account_address); + AccountInfoOf::::remove(&account_address); ImmutableDataOf::::remove(&account_address); >::decrement_refcount(info.code_hash)?; @@ -1685,7 +1778,7 @@ where salt, input_data: input_data.as_ref(), }, - value.try_into().map_err(|_| Error::::BalanceConversionFailed)?, + value, gas_limit, deposit_limit.saturated_into::>(), self.is_read_only(), @@ -1741,8 +1834,6 @@ where return Err(>::ReentranceDenied.into()); } - let value = value.try_into().map_err(|_| Error::::BalanceConversionFailed)?; - // We ignore instantiate frames in our search for a cached contract. // Otherwise it would be possible to recursively call a contract from its own // constructor: We disallow calling not fully constructed contracts. @@ -1856,7 +1947,8 @@ where if let Some(code) = >::code(address.as_fixed_bytes()) { return sp_io::hashing::keccak_256(code).into() } - >::get(&address) + + >::load_contract(&address) .map(|contract| contract.code_hash) .unwrap_or_else(|| { if System::::account_exists(&T::AddressMapper::to_account_id(address)) { @@ -1870,7 +1962,8 @@ where if let Some(code) = >::code(address.as_fixed_bytes()) { return code.len() as u64 } - >::get(&address) + + >::load_contract(&address) .and_then(|contract| CodeInfoOf::::get(contract.code_hash)) .map(|info| info.code_len()) .unwrap_or_default() diff --git a/substrate/frame/revive/src/exec/tests.rs b/substrate/frame/revive/src/exec/tests.rs index d6249fea6eadd..eacf1353e8b32 100644 --- a/substrate/frame/revive/src/exec/tests.rs +++ b/substrate/frame/revive/src/exec/tests.rs @@ -30,7 +30,7 @@ use crate::{ test_utils::{get_balance, place_contract, set_balance}, ExtBuilder, RuntimeEvent as MetaEvent, Test, }, - AddressMapper, Error, + AddressMapper, Error, Pallet, }; use assert_matches::assert_matches; use frame_support::{assert_err, assert_ok, parameter_types}; @@ -238,7 +238,15 @@ fn transfer_works() { let value = 55; let origin = Origin::from_account_id(ALICE); let mut storage_meter = storage::meter::Meter::new(u64::MAX); - MockStack::transfer(&origin, &ALICE, &BOB, value.into(), &mut storage_meter).unwrap(); + + MockStack::transfer( + &origin, + &ALICE, + &BOB, + Pallet::::convert_native_to_evm(value), + &mut storage_meter, + ) + .unwrap(); let min_balance = ::Currency::minimum_balance(); assert!(min_balance > 0); @@ -254,14 +262,15 @@ fn transfer_works() { #[test] fn transfer_to_nonexistent_account_works() { // This test verifies that a contract is able to transfer - // some funds to a nonexistant account and that those transfers + // some funds to a nonexistent account and that those transfers // are not able to reap accounts. ExtBuilder::default().build().execute_with(|| { let ed = ::Currency::minimum_balance(); let value = 1024; + let evm_value = Pallet::::convert_native_to_evm(value); let mut storage_meter = storage::meter::Meter::new(u64::MAX); - // Transfers to nonexistant accounts should work + // Transfers to nonexistent accounts should work set_balance(&ALICE, ed * 2); set_balance(&BOB, ed + value); @@ -269,7 +278,7 @@ fn transfer_to_nonexistent_account_works() { &Origin::from_account_id(ALICE), &BOB, &CHARLIE, - value.into(), + evm_value, &mut storage_meter, )); assert_eq!(get_balance(&ALICE), ed); @@ -284,7 +293,7 @@ fn transfer_to_nonexistent_account_works() { &Origin::from_account_id(ALICE), &BOB, &DJANGO, - value.into(), + evm_value, &mut storage_meter ), >::StorageDepositNotEnoughFunds, @@ -298,7 +307,7 @@ fn transfer_to_nonexistent_account_works() { &Origin::from_account_id(ALICE), &BOB, &EVE, - value.into(), + evm_value, &mut storage_meter ), >::TransferFailed @@ -311,9 +320,10 @@ fn transfer_to_nonexistent_account_works() { #[test] fn correct_transfer_on_call() { let value = 55; + let evm_value = Pallet::::convert_native_to_evm(value); let success_ch = MockLoader::insert(Call, move |ctx, _| { - assert_eq!(ctx.ext.value_transferred(), U256::from(value)); + assert_eq!(ctx.ext.value_transferred(), evm_value); Ok(ExecReturnValue { flags: ReturnFlags::empty(), data: Vec::new() }) }); @@ -329,7 +339,7 @@ fn correct_transfer_on_call() { BOB_ADDR, &mut GasMeter::::new(GAS_LIMIT), &mut storage_meter, - value.into(), + evm_value.as_u64().into(), vec![], false, ) @@ -343,14 +353,15 @@ fn correct_transfer_on_call() { #[test] fn correct_transfer_on_delegate_call() { let value = 35; + let evm_value = Pallet::::convert_native_to_evm(value); let success_ch = MockLoader::insert(Call, move |ctx, _| { - assert_eq!(ctx.ext.value_transferred(), U256::from(value)); + assert_eq!(ctx.ext.value_transferred(), evm_value); Ok(ExecReturnValue { flags: ReturnFlags::empty(), data: Vec::new() }) }); let delegate_ch = MockLoader::insert(Call, move |ctx, _| { - assert_eq!(ctx.ext.value_transferred(), U256::from(value)); + assert_eq!(ctx.ext.value_transferred(), evm_value); ctx.ext.delegate_call(Weight::zero(), U256::zero(), CHARLIE_ADDR, Vec::new())?; Ok(ExecReturnValue { flags: ReturnFlags::empty(), data: Vec::new() }) }); @@ -368,7 +379,7 @@ fn correct_transfer_on_delegate_call() { BOB_ADDR, &mut GasMeter::::new(GAS_LIMIT), &mut storage_meter, - value.into(), + evm_value.as_u64().into(), vec![], false, )); @@ -471,7 +482,7 @@ fn balance_too_low() { &Origin::from_account_id(ALICE), &from, &dest, - 100u64.into(), + Pallet::::convert_native_to_evm(100u64).as_u64().into(), &mut storage_meter, ); @@ -1098,7 +1109,7 @@ fn instantiation_work_with_success_output() { executable, &mut gas_meter, &mut storage_meter, - min_balance.into(), + Pallet::::convert_native_to_evm(min_balance), vec![], Some(&[0 ;32]), false, @@ -1150,7 +1161,7 @@ fn instantiation_fails_with_failing_output() { executable, &mut gas_meter, &mut storage_meter, - min_balance.into(), + Pallet::::convert_native_to_evm(min_balance), vec![], Some(&[0; 32]), false, @@ -1178,13 +1189,14 @@ fn instantiation_from_contract() { let instantiated_contract_address = Rc::clone(&instantiated_contract_address); move |ctx, _| { // Instantiate a contract and save it's address in `instantiated_contract_address`. + let min_balance = ::Currency::minimum_balance(); let (address, output) = ctx .ext .instantiate( Weight::MAX, U256::MAX, dummy_ch, - ::Currency::minimum_balance().into(), + Pallet::::convert_native_to_evm(min_balance), vec![], Some(&[48; 32]), ) @@ -1213,7 +1225,7 @@ fn instantiation_from_contract() { BOB_ADDR, &mut GasMeter::::new(GAS_LIMIT), &mut storage_meter, - (min_balance * 10).into(), + Pallet::::convert_native_to_evm(min_balance * 10), vec![], false, ), @@ -1243,12 +1255,15 @@ fn instantiation_traps() { let instantiator_ch = MockLoader::insert(Call, { move |ctx, _| { // Instantiate a contract and save it's address in `instantiated_contract_address`. + let min_balance = ::Currency::minimum_balance(); + let value = Pallet::::convert_native_to_evm(min_balance); + assert_matches!( ctx.ext.instantiate( Weight::zero(), U256::zero(), dummy_ch, - ::Currency::minimum_balance().into(), + value, vec![], Some(&[0; 32]), ), @@ -1311,7 +1326,7 @@ fn termination_from_instantiate_fails() { executable, &mut gas_meter, &mut storage_meter, - 100u64.into(), + Pallet::::convert_native_to_evm(100u64), vec![], Some(&[0; 32]), false, @@ -2340,7 +2355,8 @@ fn last_frame_output_works_on_instantiate() { let trap_ch = MockLoader::insert(Constructor, |_, _| Err("It's a trap!".into())); let instantiator_ch = MockLoader::insert(Call, { move |ctx, _| { - let value = ::Currency::minimum_balance().into(); + let min_balance = ::Currency::minimum_balance(); + let value = Pallet::::convert_native_to_evm(min_balance); // Successful instantiation should set the output let address = @@ -2352,7 +2368,15 @@ fn last_frame_output_works_on_instantiate() { // Balance transfers should reset the output ctx.ext - .call(Weight::MAX, U256::MAX, &address, U256::from(1), vec![], true, false) + .call( + Weight::MAX, + U256::MAX, + &address, + Pallet::::convert_native_to_evm(1), + vec![], + true, + false, + ) .unwrap(); assert_eq!(ctx.ext.last_frame_output(), &Default::default()); @@ -2547,7 +2571,8 @@ fn immutable_data_access_checks_work() { }); let instantiator_ch = MockLoader::insert(Call, { move |ctx, _| { - let value = ::Currency::minimum_balance().into(); + let min_balance = ::Currency::minimum_balance(); + let value = Pallet::::convert_native_to_evm(min_balance); assert_eq!( ctx.ext.set_immutable_data(vec![0, 1, 2, 3].try_into().unwrap()), @@ -2719,7 +2744,9 @@ fn immutable_data_set_errors_with_empty_data() { }); let instantiator_ch = MockLoader::insert(Call, { move |ctx, _| { - let value = ::Currency::minimum_balance().into(); + let min_balance = ::Currency::minimum_balance(); + let value = Pallet::::convert_native_to_evm(min_balance); + ctx.ext .instantiate(Weight::MAX, U256::MAX, dummy_ch, value, vec![], None) .unwrap(); diff --git a/substrate/frame/revive/src/impl_fungibles.rs b/substrate/frame/revive/src/impl_fungibles.rs index 75c3ae59e98d1..55c42a5091098 100644 --- a/substrate/frame/revive/src/impl_fungibles.rs +++ b/substrate/frame/revive/src/impl_fungibles.rs @@ -39,10 +39,7 @@ use frame_support::{ PalletId, }; use sp_core::{H160, H256, U256}; -use sp_runtime::{ - traits::{AccountIdConversion, Zero}, - DispatchError, -}; +use sp_runtime::{traits::AccountIdConversion, DispatchError}; use super::{ address::AddressMapper, pallet, BalanceOf, Bounded, Config, ContractResult, DepositLimit, @@ -78,7 +75,7 @@ where let ContractResult { result, .. } = Self::bare_call( T::RuntimeOrigin::signed(Self::checking_account()), asset_id, - BalanceOf::::zero(), + U256::zero(), GAS_LIMIT, DepositLimit::Balance( <::Currency as fungible::Inspect<_>>::total_issuance(), @@ -114,7 +111,7 @@ where let ContractResult { result, .. } = Self::bare_call( T::RuntimeOrigin::signed(account_id.clone()), asset_id, - BalanceOf::::zero(), + U256::zero(), GAS_LIMIT, DepositLimit::Balance( <::Currency as fungible::Inspect<_>>::total_issuance(), @@ -189,7 +186,7 @@ where let ContractResult { result, gas_consumed, .. } = Self::bare_call( T::RuntimeOrigin::signed(who.clone()), asset_id, - BalanceOf::::zero(), + U256::zero(), GAS_LIMIT, DepositLimit::Balance( <::Currency as fungible::Inspect<_>>::total_issuance(), @@ -226,7 +223,7 @@ where let ContractResult { result, .. } = Self::bare_call( T::RuntimeOrigin::signed(Self::checking_account()), asset_id, - BalanceOf::::zero(), + U256::zero(), GAS_LIMIT, DepositLimit::Balance( <::Currency as fungible::Inspect<_>>::total_issuance(), @@ -302,7 +299,7 @@ mod tests { use crate::{ test_utils::{builder::*, ALICE}, tests::{Contracts, ExtBuilder, RuntimeOrigin, Test}, - Code, ContractInfoOf, + AccountInfoOf, Code, }; use frame_support::assert_ok; @@ -327,7 +324,7 @@ mod tests { EU256::abi_decode_validate(&result.data).expect("Failed to decode ABI response"); assert_eq!(balance, EU256::from(amount)); // Contract is uploaded. - assert_eq!(ContractInfoOf::::contains_key(&addr), true); + assert_eq!(AccountInfoOf::::contains_key(&addr), true); }); } diff --git a/substrate/frame/revive/src/lib.rs b/substrate/frame/revive/src/lib.rs index b6a91ce9395bd..0e4a78505707f 100644 --- a/substrate/frame/revive/src/lib.rs +++ b/substrate/frame/revive/src/lib.rs @@ -37,6 +37,7 @@ mod transient_storage; mod vm; pub mod evm; +pub mod migrations; pub mod precompiles; pub mod test_utils; pub mod tracing; @@ -49,7 +50,9 @@ use crate::{ }, exec::{AccountIdOf, ExecError, Executable, Key, Stack as ExecStack}, gas::GasMeter, - storage::{meter::Meter as StorageMeter, ContractInfo, DeletionQueueManager}, + storage::{ + meter::Meter as StorageMeter, AccountInfo, AccountType, ContractInfo, DeletionQueueManager, + }, tracing::if_tracing, vm::{CodeInfo, ContractBlob, RuntimeCosts}, }; @@ -65,7 +68,6 @@ use frame_support::{ pallet_prelude::DispatchClass, traits::{ fungible::{Inspect, Mutate, MutateHold}, - tokens::{Fortitude::Polite, Preservation::Preserve}, ConstU32, ConstU64, EnsureOrigin, Get, IsType, OriginTrait, Time, }, weights::WeightMeter, @@ -79,7 +81,7 @@ use frame_system::{ use pallet_transaction_payment::OnChargeTransaction; use scale_info::TypeInfo; use sp_runtime::{ - traits::{BadOrigin, Bounded, Convert, Dispatchable, Saturating, Zero}, + traits::{BadOrigin, Bounded, Convert, Dispatchable, Saturating}, AccountId32, DispatchError, }; @@ -342,7 +344,7 @@ pub mod pallet { type RuntimeMemory = ConstU32<{ 128 * 1024 * 1024 }>; type PVFMemory = ConstU32<{ 512 * 1024 * 1024 }>; type ChainId = ConstU64<42>; - type NativeToEthRatio = ConstU32<1>; + type NativeToEthRatio = ConstU32<1_000_000>; type EthGasEncoder = (); type FindAuthor = (); } @@ -393,7 +395,7 @@ pub mod pallet { DecodingFailed = 0x0A, /// Contract trapped during execution. ContractTrapped = 0x0B, - /// The size defined in `T::MaxValueSize` was exceeded. + /// Event body or storage item exceeds [`limits::PAYLOAD_BYTES`]. ValueTooLarge = 0x0C, /// Termination of a contract is not allowed while the contract is already /// on the call stack. Can be triggered by `seal_terminate`. @@ -432,8 +434,7 @@ pub mod pallet { CodeRejected = 0x1B, /// The code blob supplied is larger than [`limits::code::BLOB_BYTES`]. BlobTooLarge = 0x1C, - /// The static memory consumption of the blob will be larger than - /// [`limits::code::STATIC_MEMORY_BYTES`]. + /// The contract declares too much memory (ro + rw + stack). StaticMemoryTooLarge = 0x1D, /// The program contains a basic block that is larger than allowed. BasicBlockTooLarge = 0x1E, @@ -457,8 +458,6 @@ pub mod pallet { ExecutionFailed = 0x27, /// Failed to convert a U256 to a Balance. BalanceConversionFailed = 0x28, - /// Failed to convert an EVM balance to a native balance. - DecimalPrecisionLoss = 0x29, /// Immutable data can only be set during deploys and only be read during calls. /// Additionally, it is only valid to set the data once and it must not be empty. InvalidImmutableAccess = 0x2A, @@ -472,8 +471,12 @@ pub mod pallet { InvalidGenericTransaction = 0x2D, /// The refcount of a code either over or underflowed. RefcountOverOrUnderflow = 0x2E, - /// Unsupported precompile address + /// Unsupported precompile address. UnsupportedPrecompileAddress = 0x2F, + /// The calldata exceeds [`limits::CALLDATA_BYTES`]. + CallDataTooLarge = 0x30, + /// The return data exceeds [`limits::CALLDATA_BYTES`]. + ReturnDataTooLarge = 0x31, } /// A reason for the pallet contracts placing a hold on funds. @@ -495,9 +498,9 @@ pub mod pallet { #[pallet::storage] pub(crate) type CodeInfoOf = StorageMap<_, Identity, H256, CodeInfo>; - /// The code associated with a given account. + /// The data associated to a contract or externally owned account. #[pallet::storage] - pub(crate) type ContractInfoOf = StorageMap<_, Identity, H160, ContractInfo>; + pub(crate) type AccountInfoOf = StorageMap<_, Identity, H160, AccountInfo>; /// The immutable data associated with a given account. #[pallet::storage] @@ -552,51 +555,29 @@ pub mod pallet { } fn integrity_test() { - use limits::code::STATIC_MEMORY_BYTES; - assert!(T::ChainId::get() > 0, "ChainId must be greater than 0"); // The memory available in the block building runtime let max_runtime_mem: u32 = T::RuntimeMemory::get(); - // The root frame is not accounted in CALL_STACK_DEPTH - let max_call_depth = - limits::CALL_STACK_DEPTH.checked_add(1).expect("CallStack size is too big"); - // Transient storage uses a BTreeMap, which has overhead compared to the raw size of - // key-value data. To ensure safety, a margin of 2x the raw key-value size is used. - let max_transient_storage_size = limits::TRANSIENT_STORAGE_BYTES - .checked_mul(2) - .expect("MaxTransientStorageSize is too large"); // We only allow 50% of the runtime memory to be utilized by the contracts call // stack, keeping the rest for other facilities, such as PoV, etc. const TOTAL_MEMORY_DEVIDER: u32 = 2; - // The inefficiencies of the freeing-bump allocator - // being used in the client for the runtime memory allocations, could lead to possible - // memory allocations grow up to `x4` times in some extreme cases. - const MEMORY_ALLOCATOR_INEFFICENCY_DEVIDER: u32 = 4; - - // Check that the configured `STATIC_MEMORY_BYTES` fits into runtime memory. - // - // `STATIC_MEMORY_BYTES` is the amount of memory that a contract can consume - // in memory and is enforced at upload time. + // Check that the configured memory limits fit into runtime memory. // - // Dynamic allocations are not available, yet. Hence are not taken into consideration - // here. - let static_memory_limit = max_runtime_mem - .saturating_div(TOTAL_MEMORY_DEVIDER) - .saturating_sub(max_transient_storage_size) - .saturating_div(max_call_depth) - .saturating_sub(STATIC_MEMORY_BYTES) - .saturating_div(MEMORY_ALLOCATOR_INEFFICENCY_DEVIDER); + // Dynamic allocations are not available, yet. Hence they are not taken into + // consideration here. + let memory_left = i64::from(max_runtime_mem) + .saturating_div(TOTAL_MEMORY_DEVIDER.into()) + .saturating_sub(limits::MEMORY_REQUIRED.into()); + + log::debug!(target: LOG_TARGET, "Integrity check: memory_left={} KB", memory_left / 1024); assert!( - STATIC_MEMORY_BYTES < static_memory_limit, - "Given `CallStack` height {:?}, `STATIC_MEMORY_LIMIT` should be set less than {:?} \ - (current value is {:?}), to avoid possible runtime oom issues.", - max_call_depth, - static_memory_limit, - STATIC_MEMORY_BYTES, + memory_left >= 0, + "Runtime does not have enough memory for current limits. Additional runtime memory required: {} KB", + memory_left.saturating_mul(TOTAL_MEMORY_DEVIDER.into()).abs() / 1024 ); // Validators are configured to be able to use more memory than block builders. This is @@ -730,7 +711,7 @@ pub mod pallet { let mut output = Self::bare_call( origin, dest, - value, + Pallet::::convert_native_to_evm(value), gas_limit, DepositLimit::Balance(storage_deposit_limit), data, @@ -765,7 +746,7 @@ pub mod pallet { let data_len = data.len() as u32; let mut output = Self::bare_instantiate( origin, - value, + Pallet::::convert_native_to_evm(value), gas_limit, DepositLimit::Balance(storage_deposit_limit), Code::Existing(code_hash), @@ -830,7 +811,7 @@ pub mod pallet { let data_len = data.len() as u32; let mut output = Self::bare_instantiate( origin, - value, + Pallet::::convert_native_to_evm(value), gas_limit, DepositLimit::Balance(storage_deposit_limit), Code::Upload(code), @@ -859,12 +840,12 @@ pub mod pallet { /// times within a batch call transaction. #[pallet::call_index(10)] #[pallet::weight( - T::WeightInfo::instantiate_with_code(code.len() as u32, data.len() as u32) + T::WeightInfo::eth_instantiate_with_code(code.len() as u32, data.len() as u32, Pallet::::has_dust(*value).into()) .saturating_add(*gas_limit) )] pub fn eth_instantiate_with_code( origin: OriginFor, - #[pallet::compact] value: BalanceOf, + value: U256, gas_limit: Weight, #[pallet::compact] storage_deposit_limit: BalanceOf, code: Vec, @@ -891,7 +872,44 @@ pub mod pallet { dispatch_result( output.result.map(|result| result.result), output.gas_consumed, - T::WeightInfo::instantiate_with_code(code_len, data_len), + T::WeightInfo::eth_instantiate_with_code( + code_len, + data_len, + Pallet::::has_dust(value).into(), + ), + ) + } + + /// Same as [`Self::call`], but intended to be dispatched **only** + /// by an EVM transaction through the EVM compatibility layer. + #[pallet::call_index(11)] + #[pallet::weight(T::WeightInfo::eth_call(Pallet::::has_dust(*value).into()).saturating_add(*gas_limit))] + pub fn eth_call( + origin: OriginFor, + dest: H160, + value: U256, + gas_limit: Weight, + #[pallet::compact] storage_deposit_limit: BalanceOf, + data: Vec, + ) -> DispatchResultWithPostInfo { + let mut output = Self::bare_call( + origin, + dest, + value, + gas_limit, + DepositLimit::Balance(storage_deposit_limit), + data, + ); + + if let Ok(return_value) = &output.result { + if return_value.did_revert() { + output.result = Err(>::ContractReverted.into()); + } + } + dispatch_result( + output.result, + output.gas_consumed, + T::WeightInfo::eth_call(Pallet::::has_dust(value).into()), ) } @@ -951,12 +969,15 @@ pub mod pallet { code_hash: sp_core::H256, ) -> DispatchResult { ensure_root(origin)?; - >::try_mutate(&dest, |contract| { - let contract = if let Some(contract) = contract { - contract - } else { + >::try_mutate(&dest, |account| { + let Some(account) = account else { + return Err(>::ContractNotFound.into()); + }; + + let AccountType::Contract(ref mut contract) = account.account_type else { return Err(>::ContractNotFound.into()); }; + >::increment_refcount(code_hash)?; >::decrement_refcount(contract.code_hash)?; contract.code_hash = code_hash; @@ -1043,7 +1064,7 @@ where pub fn bare_call( origin: OriginFor, dest: H160, - value: BalanceOf, + evm_value: U256, gas_limit: Weight, storage_deposit_limit: DepositLimit>, data: Vec, @@ -1053,17 +1074,13 @@ where let try_call = || { let origin = Origin::from_runtime_origin(origin)?; - let mut storage_meter = match storage_deposit_limit { - DepositLimit::Balance(limit) => StorageMeter::new(limit), - DepositLimit::UnsafeOnlyForDryRun => - StorageMeter::new_unchecked(BalanceOf::::max_value()), - }; + let mut storage_meter = StorageMeter::new(storage_deposit_limit.limit()); let result = ExecStack::>::run_call( origin.clone(), dest, &mut gas_meter, &mut storage_meter, - Self::convert_native_to_evm(value), + evm_value, data, storage_deposit_limit.is_unchecked(), )?; @@ -1101,7 +1118,7 @@ where /// more information to the caller useful to estimate the cost of the operation. pub fn bare_instantiate( origin: OriginFor, - value: BalanceOf, + evm_value: U256, gas_limit: Weight, storage_deposit_limit: DepositLimit>, code: Code, @@ -1112,11 +1129,7 @@ where let mut gas_meter = GasMeter::new(gas_limit); let mut storage_deposit = Default::default(); let unchecked_deposit_limit = storage_deposit_limit.is_unchecked(); - let mut storage_deposit_limit = match storage_deposit_limit { - DepositLimit::Balance(limit) => limit, - DepositLimit::UnsafeOnlyForDryRun => BalanceOf::::max_value(), - }; - + let mut storage_deposit_limit = storage_deposit_limit.limit(); let try_instantiate = || { let instantiate_account = T::InstantiateOrigin::ensure_origin(origin.clone())?; @@ -1137,18 +1150,13 @@ where (ContractBlob::from_storage(code_hash, &mut gas_meter)?, Default::default()), }; let instantiate_origin = Origin::from_account_id(instantiate_account.clone()); - let mut storage_meter = if unchecked_deposit_limit { - StorageMeter::new_unchecked(storage_deposit_limit) - } else { - StorageMeter::new(storage_deposit_limit) - }; - + let mut storage_meter = StorageMeter::new(storage_deposit_limit); let result = ExecStack::>::run_instantiate( instantiate_account, executable, &mut gas_meter, &mut storage_meter, - Self::convert_native_to_evm(value), + evm_value, data, salt.as_ref(), unchecked_deposit_limit, @@ -1228,13 +1236,7 @@ where } // Convert the value to the native balance type. - let evm_value = tx.value.unwrap_or_default(); - let native_value = match Self::convert_evm_to_native(evm_value, ConversionPrecision::Exact) - { - Ok(v) => v, - Err(_) => return Err(EthTransactError::Message("Failed to convert value".into())), - }; - + let value = tx.value.unwrap_or_default(); let input = tx.input.clone().to_vec(); let extract_error = |err| { @@ -1285,7 +1287,7 @@ where let result = crate::Pallet::::bare_call( T::RuntimeOrigin::signed(origin), dest, - native_value, + value, gas_limit, storage_deposit_limit, input.clone(), @@ -1315,9 +1317,9 @@ where result.gas_required, result.storage_deposit, ); - let dispatch_call: ::RuntimeCall = crate::Call::::call { + let dispatch_call: ::RuntimeCall = crate::Call::::eth_call { dest, - value: native_value, + value, gas_limit, storage_deposit_limit, data: input.clone(), @@ -1344,7 +1346,7 @@ where // Dry run the call. let result = crate::Pallet::::bare_instantiate( T::RuntimeOrigin::signed(origin), - native_value, + value, gas_limit, storage_deposit_limit, Code::Upload(code.to_vec()), @@ -1380,7 +1382,7 @@ where ); let dispatch_call: ::RuntimeCall = crate::Call::::eth_instantiate_with_code { - value: native_value, + value, gas_limit, storage_deposit_limit, code: code.to_vec(), @@ -1409,8 +1411,8 @@ where /// Get the balance with EVM decimals of the given `address`. pub fn evm_balance(address: &H160) -> U256 { - let account = T::AddressMapper::to_account_id(&address); - Self::convert_native_to_evm(T::Currency::reducible_balance(&account, Preserve, Polite)) + let balance = AccountInfo::::balance((*address).into()); + Self::convert_native_to_evm(balance) } /// Get the nonce for the given `address`. @@ -1438,7 +1440,8 @@ where /// Convert a gas value into a substrate fee fn evm_gas_to_fee(gas: U256, gas_price: U256) -> Result, Error> { let fee = gas.saturating_mul(gas_price); - Self::convert_evm_to_native(fee, ConversionPrecision::RoundUp) + let value = BalanceWithDust::>::from_value::(fee)?; + Ok(value.into_rounded_balance()) } /// Convert a weight to a gas value. @@ -1505,7 +1508,7 @@ where /// Query storage of a specified contract under a specified key. pub fn get_storage(address: H160, key: [u8; 32]) -> GetStorageResult { let contract_info = - ContractInfoOf::::get(&address).ok_or(ContractAccessError::DoesntExist)?; + AccountInfo::::load_contract(&address).ok_or(ContractAccessError::DoesntExist)?; let maybe_value = contract_info.read(&Key::from_fixed(key)); Ok(maybe_value) @@ -1514,7 +1517,7 @@ where /// Query storage of a specified contract under a specified variable-sized key. pub fn get_storage_var_key(address: H160, key: Vec) -> GetStorageResult { let contract_info = - ContractInfoOf::::get(&address).ok_or(ContractAccessError::DoesntExist)?; + AccountInfo::::load_contract(&address).ok_or(ContractAccessError::DoesntExist)?; let maybe_value = contract_info.read( &Key::try_from_var(key) @@ -1557,32 +1560,26 @@ where } /// Convert a native balance to EVM balance. - fn convert_native_to_evm(value: BalanceOf) -> U256 { - value.into().saturating_mul(T::NativeToEthRatio::get().into()) + pub fn convert_native_to_evm(value: impl Into>>) -> U256 { + let (value, dust) = value.into().deconstruct(); + value + .into() + .saturating_mul(T::NativeToEthRatio::get().into()) + .saturating_add(dust.into()) } +} - /// Convert an EVM balance to a native balance. - fn convert_evm_to_native( - value: U256, - precision: ConversionPrecision, - ) -> Result, Error> { - if value.is_zero() { - return Ok(Zero::zero()); - } +impl Pallet { + /// Returns true if the evm value carries dust. + fn has_dust(value: U256) -> bool { + value % U256::from(::NativeToEthRatio::get()) != U256::zero() + } - let (quotient, remainder) = value.div_mod(T::NativeToEthRatio::get().into()); - match (precision, remainder.is_zero()) { - (ConversionPrecision::Exact, false) => Err(Error::::DecimalPrecisionLoss), - (_, true) => quotient.try_into().map_err(|_| Error::::BalanceConversionFailed), - (_, false) => quotient - .saturating_add(U256::one()) - .try_into() - .map_err(|_| Error::::BalanceConversionFailed), - } + /// Returns true if the evm value carries balance. + fn has_balance(value: U256) -> bool { + value >= U256::from(::NativeToEthRatio::get()) } -} -impl Pallet { /// Return the existential deposit of [`Config::Currency`]. fn min_balance() -> BalanceOf { >>::minimum_balance() @@ -1612,7 +1609,7 @@ impl Pallet { if let Some(code) = >::code(address.as_fixed_bytes()) { return code.into() } - >::get(&address) + AccountInfo::::load_contract(&address) .and_then(|contract| >::get(contract.code_hash)) .map(|code| code.into()) .unwrap_or_default() @@ -1844,7 +1841,7 @@ macro_rules! impl_runtime_apis_plus_revive { $crate::Pallet::::bare_call( ::RuntimeOrigin::signed(origin), dest, - value, + $crate::Pallet::::convert_native_to_evm(value), gas_limit.unwrap_or(blockweights.max_block), $crate::DepositLimit::Balance(storage_deposit_limit.unwrap_or(u128::MAX)), input_data, @@ -1867,7 +1864,7 @@ macro_rules! impl_runtime_apis_plus_revive { $crate::Pallet::::prepare_dry_run(&origin); $crate::Pallet::::bare_instantiate( ::RuntimeOrigin::signed(origin), - value, + $crate::Pallet::::convert_native_to_evm(value), gas_limit.unwrap_or(blockweights.max_block), $crate::DepositLimit::Balance(storage_deposit_limit.unwrap_or(u128::MAX)), code, diff --git a/substrate/frame/revive/src/limits.rs b/substrate/frame/revive/src/limits.rs index 09c611a9b640f..1a88f73749f17 100644 --- a/substrate/frame/revive/src/limits.rs +++ b/substrate/frame/revive/src/limits.rs @@ -32,11 +32,16 @@ //! can change those limits without breaking existing contracts. Please keep in mind that we should //! only ever **increase** those values but never decrease. +/// The amount of total memory we require to safely operate. +/// +/// This is not a config knob but derived from the limits in this file. +pub const MEMORY_REQUIRED: u32 = memory_required(); + /// The maximum depth of the call stack. /// /// A 0 means that no callings of other contracts are possible. In other words only the origin /// called "root contract" is allowed to execute then. -pub const CALL_STACK_DEPTH: u32 = 5; +pub const CALL_STACK_DEPTH: u32 = 25; /// The maximum number of topics a call to [`crate::SyscallDoc::deposit_event`] can emit. /// @@ -46,6 +51,11 @@ pub const NUM_EVENT_TOPICS: u32 = 4; /// Maximum size of events (including topics) and storage values. pub const PAYLOAD_BYTES: u32 = 416; +/// The maximum size for calldata and return data. +/// +/// Please note that the calldata is limited to 128KB on geth anyways. +pub const CALLDATA_BYTES: u32 = 128 * 1024; + /// The maximum size of the transient storage in bytes. /// /// This includes keys, values, and previous entries used for storage rollback. @@ -79,17 +89,11 @@ pub mod code { /// The maximum length of a code blob in bytes. /// /// This mostly exist to prevent parsing too big blobs and to - /// have a maximum encoded length. The actual memory calculation - /// is purely based off [`STATIC_MEMORY_BYTES`]. - pub const BLOB_BYTES: u32 = 256 * 1024; + /// have a maximum encoded length. + pub const BLOB_BYTES: u32 = 1024 * 1024; - /// Maximum size the program is allowed to take in memory. - /// - /// This includes data and code. Increasing this limit will allow - /// for more code or more data. However, since code will decompress - /// into a bigger representation on compilation it will only increase - /// the allowed code size by [`BYTE_PER_INSTRUCTION`]. - pub const STATIC_MEMORY_BYTES: u32 = 2 * 1024 * 1024; + /// The maximum amount of memory the interpreter is allowed to use for compilation artifacts. + pub const INTERPRETER_CACHE_BYTES: u32 = 1024 * 1024; /// The maximum size of a basic block in number of instructions. /// @@ -98,26 +102,30 @@ pub mod code { /// of the whole program by creating one giant basic block otherwise. pub const BASIC_BLOCK_SIZE: u32 = 1000; - /// How much memory each instruction will take in-memory after compilation. + /// The limit for memory that can be purged on demand. /// - /// This is `size_of() + 16`. But we don't use `usize` here so it isn't - /// different on the native runtime (used for testing). - pub const BYTES_PER_INSTRUCTION: u32 = 20; + /// We purge this memory every time we call into another contract. + /// Hence we effectively only need to hold it once in RAM. + pub const PURGABLE_MEMORY_LIMIT: u32 = INTERPRETER_CACHE_BYTES + 2 * 1024 * 1024; - /// The code is stored multiple times as part of the compiled program. - const EXTRA_OVERHEAD_PER_CODE_BYTE: u32 = 4; + /// The limit for memory that needs to be kept alive for a contracts whole life time. + /// + /// This means tuning this number affects the call stack depth. + pub const BASELINE_MEMORY_LIMIT: u32 = BLOB_BYTES + 512 * 1024; /// Make sure that the various program parts are within the defined limits. pub fn enforce( blob: Vec, available_syscalls: &[&[u8]], ) -> Result { - fn round_page(n: u32) -> u64 { - // performing the rounding in u64 in order to prevent overflow - u64::from(n).next_multiple_of(PAGE_SIZE.into()) - } + use polkavm::program::ISA64_V1 as ISA; + use polkavm_common::program::EstimateInterpreterMemoryUsageArgs; - let blob: CodeVec = blob.try_into().map_err(|_| >::BlobTooLarge)?; + let len: u64 = blob.len() as u64; + let blob: CodeVec = blob.try_into().map_err(|_| { + log::debug!(target: LOG_TARGET, "contract blob too large: {len} limit: {}", BLOB_BYTES); + >::BlobTooLarge + })?; #[cfg(feature = "std")] if std::env::var_os("REVIVE_SKIP_VALIDATION").is_some() { @@ -158,17 +166,18 @@ pub mod code { // This scans the whole program but we only do it once on code deployment. // It is safe to do unchecked math in u32 because the size of the program // was already checked above. - use polkavm::program::ISA64_V1 as ISA; - let mut num_instructions: u32 = 0; - let mut max_basic_block_size: u32 = 0; - let mut basic_block_size: u32 = 0; + let mut max_block_size: u32 = 0; + let mut block_size: u32 = 0; + let mut basic_block_count: u32 = 0; + let mut instruction_count: u32 = 0; for inst in program.instructions(ISA) { use polkavm::program::Instruction; - num_instructions += 1; - basic_block_size += 1; + block_size += 1; + instruction_count += 1; if inst.kind.opcode().starts_new_basic_block() { - max_basic_block_size = max_basic_block_size.max(basic_block_size); - basic_block_size = 0; + max_block_size = max_block_size.max(block_size); + block_size = 0; + basic_block_count += 1; } match inst.kind { Instruction::invalid => { @@ -190,37 +199,62 @@ pub mod code { _ => (), } } + max_block_size = max_block_size.max(block_size); - if max_basic_block_size > BASIC_BLOCK_SIZE { - log::debug!(target: LOG_TARGET, "basic block too large: {max_basic_block_size} limit: {BASIC_BLOCK_SIZE}"); + if max_block_size > BASIC_BLOCK_SIZE { + log::debug!(target: LOG_TARGET, "basic block too large: {max_block_size} limit: {BASIC_BLOCK_SIZE}"); return Err(Error::::BasicBlockTooLarge.into()) } - // The memory consumptions is the byte size of the whole blob, - // minus the RO data payload in the blob, - // minus the RW data payload in the blob, - // plus the RO data in memory (which is always equal or bigger than the RO payload), - // plus RW data in memory, plus stack size in memory. - // plus the overhead of instructions in memory which is derived from the code - // size itself and the number of instruction - let memory_size = (blob.len() as u64) - .saturating_add(round_page(program.ro_data_size())) - .saturating_sub(program.ro_data().len() as u64) - .saturating_add(round_page(program.rw_data_size())) - .saturating_sub(program.rw_data().len() as u64) - .saturating_add(round_page(program.stack_size())) - .saturating_add( - u64::from(num_instructions).saturating_mul(BYTES_PER_INSTRUCTION.into()), - ) - .saturating_add( - (program.code().len() as u64).saturating_mul(EXTRA_OVERHEAD_PER_CODE_BYTE.into()), + let usage_args = EstimateInterpreterMemoryUsageArgs::BoundedCache { + max_cache_size_bytes: INTERPRETER_CACHE_BYTES, + instruction_count, + max_block_size, + basic_block_count, + page_size: PAGE_SIZE, + }; + + let program_info = + program.estimate_interpreter_memory_usage(usage_args).map_err(|err| { + log::debug!(target: LOG_TARGET, "failed to estimate memory usage of program: {err:?}"); + Error::::CodeRejected + })?; + + log::debug!( + target: LOG_TARGET, "Contract memory usage: purgable={}/{} KB baseline={}/{}", + program_info.purgeable_ram_consumption, PURGABLE_MEMORY_LIMIT, + program_info.baseline_ram_consumption, BASELINE_MEMORY_LIMIT, + ); + + if program_info.purgeable_ram_consumption > PURGABLE_MEMORY_LIMIT { + log::debug!(target: LOG_TARGET, "contract uses too much purgeable memory: {} limit: {}", + program_info.purgeable_ram_consumption, + PURGABLE_MEMORY_LIMIT, ); + return Err(Error::::StaticMemoryTooLarge.into()) + } - if memory_size > STATIC_MEMORY_BYTES.into() { - log::debug!(target: LOG_TARGET, "static memory too large: {memory_size} limit: {STATIC_MEMORY_BYTES}"); + if program_info.baseline_ram_consumption > BASELINE_MEMORY_LIMIT { + log::debug!(target: LOG_TARGET, "contract uses too much baseline memory: {} limit: {}", + program_info.baseline_ram_consumption, + BASELINE_MEMORY_LIMIT, + ); return Err(Error::::StaticMemoryTooLarge.into()) } Ok(blob) } } + +/// The amount of total memory we require. +/// +/// Unchecked math is okay since we evaluate at compile time. +const fn memory_required() -> u32 { + // The root frame is not accounted for in CALL_STACK_DEPTH + let max_call_depth = CALL_STACK_DEPTH + 1; + + let per_stack_memory = code::PURGABLE_MEMORY_LIMIT + TRANSIENT_STORAGE_BYTES * 2; + let per_frame_memory = code::BASELINE_MEMORY_LIMIT + CALLDATA_BYTES * 2; + + per_stack_memory + max_call_depth * per_frame_memory +} diff --git a/substrate/frame/revive/src/migrations.rs b/substrate/frame/revive/src/migrations.rs new file mode 100644 index 0000000000000..694ecfd75d2f3 --- /dev/null +++ b/substrate/frame/revive/src/migrations.rs @@ -0,0 +1,24 @@ +// This file is part of Substrate. + +// Copyright (C) Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/// # Multi-Block Migrations Module + +/// Migrations from the old `ContractInfoOf` to the new `AccountInfoOf` storage +pub mod v1; + +/// A unique identifier across all pallets. +const PALLET_MIGRATIONS_ID: &[u8; 17] = b"pallet-revive-mbm"; diff --git a/substrate/frame/revive/src/migrations/v1.rs b/substrate/frame/revive/src/migrations/v1.rs new file mode 100644 index 0000000000000..f86a436173918 --- /dev/null +++ b/substrate/frame/revive/src/migrations/v1.rs @@ -0,0 +1,156 @@ +// This file is part of Substrate. + +// Copyright (C) Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//! # Multi-Block Migration v1 +//! +//! This migrate the old `ContractInfoOf` storage to the new `AccountInfoOf`. + +extern crate alloc; + +use super::PALLET_MIGRATIONS_ID; +use crate::{weights::WeightInfo, AccountInfo, AccountInfoOf, Config, H160}; +use frame_support::{ + migrations::{MigrationId, SteppedMigration, SteppedMigrationError}, + pallet_prelude::PhantomData, + weights::WeightMeter, +}; + +#[cfg(feature = "try-runtime")] +use alloc::collections::btree_map::BTreeMap; + +#[cfg(feature = "try-runtime")] +use alloc::vec::Vec; + +/// Module containing the old storage items. +pub mod old { + use super::Config; + use crate::{pallet::Pallet, ContractInfo, H160}; + use frame_support::{storage_alias, Identity}; + + #[storage_alias] + /// The storage item that is being migrated from. + pub type ContractInfoOf = StorageMap, Identity, H160, ContractInfo>; +} + +/// Migrates the items of the [`old::ContractInfoOf`] map into [`crate::AccountInfoOf`]. +pub struct Migration(PhantomData); + +impl SteppedMigration for Migration { + type Cursor = H160; + type Identifier = MigrationId<17>; + + fn id() -> Self::Identifier { + MigrationId { pallet_id: *PALLET_MIGRATIONS_ID, version_from: 0, version_to: 1 } + } + + fn step( + mut cursor: Option, + meter: &mut WeightMeter, + ) -> Result, SteppedMigrationError> { + let required = ::WeightInfo::v1_migration_step(); + if meter.remaining().any_lt(required) { + return Err(SteppedMigrationError::InsufficientWeight { required }); + } + + loop { + if meter.try_consume(required).is_err() { + break; + } + + let iter = if let Some(last_key) = cursor { + old::ContractInfoOf::::iter_from(old::ContractInfoOf::::hashed_key_for( + last_key, + )) + } else { + old::ContractInfoOf::::iter() + }; + + if let Some((last_key, value)) = iter.drain().next() { + AccountInfoOf::::insert( + last_key, + AccountInfo { account_type: value.into(), ..Default::default() }, + ); + cursor = Some(last_key) + } else { + cursor = None; + break + } + } + Ok(cursor) + } + + #[cfg(feature = "try-runtime")] + fn pre_upgrade() -> Result, frame_support::sp_runtime::TryRuntimeError> { + use codec::Encode; + + // Return the state of the storage before the migration. + Ok(old::ContractInfoOf::::iter().collect::>().encode()) + } + + #[cfg(feature = "try-runtime")] + fn post_upgrade(prev: Vec) -> Result<(), frame_support::sp_runtime::TryRuntimeError> { + use codec::Decode; + + // Check the state of the storage after the migration. + let prev_map = BTreeMap::>::decode(&mut &prev[..]) + .expect("Failed to decode the previous storage state"); + + // Check the len of prev and post are the same. + assert_eq!( + AccountInfoOf::::iter().count(), + prev_map.len(), + "Migration failed: the number of items in the storage after the migration is not the same as before" + ); + + for (key, value) in prev_map { + let new_value = AccountInfo::::load_contract(&key); + assert_eq!( + Some(value), + new_value, + "Migration failed: the value after the migration is not the same as before" + ); + } + + Ok(()) + } +} + +#[test] +fn migrate_to_v1() { + use crate::{ + tests::{ExtBuilder, Test}, + ContractInfo, + }; + ExtBuilder::default().build().execute_with(|| { + for i in 0..10u8 { + let addr = H160::from([i; 20]); + old::ContractInfoOf::::insert( + addr, + ContractInfo::new(&addr, 1u32.into(), Default::default()).unwrap(), + ); + } + + let mut cursor = None; + let mut weight_meter = WeightMeter::new(); + while let Some(new_cursor) = Migration::::step(cursor, &mut weight_meter).unwrap() { + cursor = Some(new_cursor); + } + + assert_eq!(old::ContractInfoOf::::iter().count(), 0); + assert_eq!(AccountInfoOf::::iter().count(), 10); + }) +} diff --git a/substrate/frame/revive/src/precompiles.rs b/substrate/frame/revive/src/precompiles.rs index 8eae8ef6375e7..b827caa27c09c 100644 --- a/substrate/frame/revive/src/precompiles.rs +++ b/substrate/frame/revive/src/precompiles.rs @@ -50,7 +50,10 @@ use pallet_revive_uapi::ReturnFlags; use sp_runtime::DispatchError; #[cfg(feature = "runtime-benchmarks")] -pub(crate) use builtin::{IBenchmarking, NoInfo as BenchmarkNoInfo, WithInfo as BenchmarkWithInfo}; +pub(crate) use builtin::{ + IBenchmarking, ISystem, NoInfo as BenchmarkNoInfo, System as BenchmarkSystem, + WithInfo as BenchmarkWithInfo, +}; const UNIMPLEMENTED: &str = "A precompile must either implement `call` or `call_with_info`"; diff --git a/substrate/frame/revive/src/precompiles/builtin.rs b/substrate/frame/revive/src/precompiles/builtin.rs index 2c33718bc7d24..34fab30802096 100644 --- a/substrate/frame/revive/src/precompiles/builtin.rs +++ b/substrate/frame/revive/src/precompiles/builtin.rs @@ -23,6 +23,7 @@ mod modexp; mod point_eval; mod ripemd160; mod sha256; +mod system; #[cfg(feature = "runtime-benchmarks")] mod benchmarking; @@ -34,7 +35,10 @@ use crate::{ }; #[cfg(feature = "runtime-benchmarks")] -pub use benchmarking::{IBenchmarking, NoInfo, WithInfo}; +pub use self::{ + benchmarking::{IBenchmarking, NoInfo, WithInfo}, + system::{ISystem, System}, +}; #[cfg(not(feature = "runtime-benchmarks"))] pub type Builtin = Production; @@ -53,6 +57,7 @@ type Production = ( bn128::Bn128Pairing, blake2f::Blake2F, point_eval::PointEval, + system::System, ); #[cfg(feature = "runtime-benchmarks")] diff --git a/substrate/frame/revive/src/precompiles/builtin/system.rs b/substrate/frame/revive/src/precompiles/builtin/system.rs new file mode 100644 index 0000000000000..668e84a6f5e00 --- /dev/null +++ b/substrate/frame/revive/src/precompiles/builtin/system.rs @@ -0,0 +1,69 @@ +// This file is part of Substrate. + +// Copyright (C) Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +use crate::{ + precompiles::{BuiltinAddressMatcher, BuiltinPrecompile, Error, Ext}, + vm::RuntimeCosts, + Config, +}; +use alloc::vec::Vec; +use alloy_core::sol; +use core::{marker::PhantomData, num::NonZero}; +use sp_core::hexdisplay::AsBytesRef; + +pub struct System(PhantomData); + +sol! { + interface ISystem { + /// Computes the BLAKE2 256-bit hash on the given input. + function hashBlake256(bytes memory input) external pure returns (bytes32 digest); + } +} + +impl BuiltinPrecompile for System { + type T = T; + type Interface = ISystem::ISystemCalls; + const MATCHER: BuiltinAddressMatcher = + BuiltinAddressMatcher::Fixed(NonZero::new(0x900).unwrap()); + const HAS_CONTRACT_INFO: bool = false; + + fn call( + _address: &[u8; 20], + input: &Self::Interface, + env: &mut impl Ext, + ) -> Result, Error> { + use ISystem::ISystemCalls; + match input { + ISystemCalls::hashBlake256(ISystem::hashBlake256Call { input }) => { + env.gas_meter_mut().charge(RuntimeCosts::HashBlake256(input.len() as u32))?; + let output = sp_io::hashing::blake2_256(input.as_bytes_ref()); + Ok(output.to_vec()) + }, + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::{precompiles::tests::run_test_vectors, tests::Test}; + + #[test] + fn test_system_precompile() { + run_test_vectors::>(include_str!("testdata/900-blake2_256.json")); + } +} diff --git a/substrate/frame/revive/src/precompiles/builtin/testdata/900-blake2_256.json b/substrate/frame/revive/src/precompiles/builtin/testdata/900-blake2_256.json new file mode 100644 index 0000000000000..1082f9dfff0c2 --- /dev/null +++ b/substrate/frame/revive/src/precompiles/builtin/testdata/900-blake2_256.json @@ -0,0 +1,9 @@ +[ + { + "Input": "c7dff68600000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000", + "Expected": "03170a2e7597b7b7e3d84c05391d139a62b157e78786d8c082f29dcf4c111314", + "Name": "vector 1", + "Gas": 8000000, + "NoBenchmark": false + } +] diff --git a/substrate/frame/revive/src/primitives.rs b/substrate/frame/revive/src/primitives.rs index 32e333d1689d3..5bebe36b444ea 100644 --- a/substrate/frame/revive/src/primitives.rs +++ b/substrate/frame/revive/src/primitives.rs @@ -17,14 +17,16 @@ //! A crate that hosts a common definitions that are relevant for the pallet-revive. -use crate::{H160, U256}; +use crate::{BalanceOf, Config, Error, H160, U256}; use alloc::{string::String, vec::Vec}; use codec::{Decode, Encode, MaxEncodedLen}; use frame_support::weights::Weight; use pallet_revive_uapi::ReturnFlags; use scale_info::TypeInfo; +use sp_arithmetic::traits::Bounded; +use sp_core::Get; use sp_runtime::{ - traits::{Saturating, Zero}, + traits::{One, Saturating, Zero}, DispatchError, RuntimeDebug, }; @@ -52,6 +54,15 @@ impl From for DepositLimit { } } +impl DepositLimit { + pub fn limit(&self) -> T { + match self { + Self::UnsafeOnlyForDryRun => T::max_value(), + Self::Balance(limit) => *limit, + } + } +} + /// Result type of a `bare_call` or `bare_instantiate` call as well as `ContractsApi::call` and /// `ContractsApi::instantiate`. /// @@ -108,12 +119,66 @@ pub enum EthTransactError { Message(String), } -/// Precision used for converting between Native and EVM balances. -pub enum ConversionPrecision { - /// Exact conversion without any rounding. - Exact, - /// Conversion that rounds up to the nearest whole number. - RoundUp, +/// A Balance amount along with some "dust" to represent the lowest decimals that can't be expressed +/// in the native currency +#[derive(Default, Clone, Copy, Eq, PartialEq, Debug)] +pub struct BalanceWithDust { + /// The value expressed in the native currency + value: Balance, + /// The dust, representing up to 1 unit of the native currency. + /// The dust is bounded between 0 and `crate::Config::NativeToEthRatio` + dust: u32, +} + +impl From for BalanceWithDust { + fn from(value: Balance) -> Self { + Self { value, dust: 0 } + } +} + +impl BalanceWithDust { + /// Deconstructs the `BalanceWithDust` into its components. + pub fn deconstruct(self) -> (Balance, u32) { + (self.value, self.dust) + } + + /// Creates a new `BalanceWithDust` with the given value and dust. + pub fn new_unchecked(value: Balance, dust: u32) -> Self { + debug_assert!(dust < T::NativeToEthRatio::get()); + Self { value, dust } + } + + /// Creates a new `BalanceWithDust` from the given EVM value. + pub fn from_value(value: U256) -> Result>, Error> + where + BalanceOf: TryFrom, + { + if value.is_zero() { + return Ok(Default::default()) + } + + let (quotient, remainder) = value.div_mod(T::NativeToEthRatio::get().into()); + let value = quotient.try_into().map_err(|_| Error::::BalanceConversionFailed)?; + let dust = remainder.try_into().map_err(|_| Error::::BalanceConversionFailed)?; + + Ok(BalanceWithDust { value, dust }) + } +} + +impl BalanceWithDust { + /// Returns true if both the value and dust are zero. + pub fn is_zero(&self) -> bool { + self.value.is_zero() && self.dust == 0 + } + + /// Returns the Balance rounded to the nearest whole unit if the dust is non-zero. + pub fn into_rounded_balance(self) -> Balance { + if self.dust == 0 { + self.value + } else { + self.value.saturating_add(Balance::one()) + } + } } /// Result type of a `bare_code_upload` call. diff --git a/substrate/frame/revive/src/storage.rs b/substrate/frame/revive/src/storage.rs index 7084647971a04..80f957b500b9a 100644 --- a/substrate/frame/revive/src/storage.rs +++ b/substrate/frame/revive/src/storage.rs @@ -25,8 +25,8 @@ use crate::{ storage::meter::Diff, tracing::if_tracing, weights::WeightInfo, - BalanceOf, Config, ContractInfoOf, DeletionQueue, DeletionQueueCounter, Error, TrieId, - SENTINEL, + AccountInfoOf, BalanceOf, BalanceWithDust, Config, DeletionQueue, DeletionQueueCounter, Error, + TrieId, SENTINEL, }; use alloc::vec::Vec; use codec::{Decode, Encode, MaxEncodedLen}; @@ -34,7 +34,7 @@ use core::marker::PhantomData; use frame_support::{ storage::child::{self, ChildInfo}, weights::{Weight, WeightMeter}, - CloneNoBound, DefaultNoBound, + CloneNoBound, DebugNoBound, DefaultNoBound, }; use scale_info::TypeInfo; use sp_core::{Get, H160}; @@ -44,9 +44,60 @@ use sp_runtime::{ DispatchError, RuntimeDebug, }; +pub enum AccountIdOrAddress { + /// An account that is a contract. + AccountId(AccountIdOf), + /// An externally owned account (EOA). + Address(H160), +} + +/// Represents the account information for a contract or an externally owned account (EOA). +#[derive( + DefaultNoBound, + Encode, + Decode, + CloneNoBound, + PartialEq, + Eq, + RuntimeDebug, + TypeInfo, + MaxEncodedLen, +)] +#[scale_info(skip_type_params(T))] +pub struct AccountInfo { + /// The type of the account. + pub account_type: AccountType, + + // The amount that was transferred to this account that is less than the + // NativeToEthRatio, and can be represented in the native currency + pub dust: u32, +} + +/// The account type is used to distinguish between contracts and externally owned accounts. +#[derive( + DefaultNoBound, + Encode, + Decode, + CloneNoBound, + PartialEq, + Eq, + RuntimeDebug, + TypeInfo, + MaxEncodedLen, +)] +#[scale_info(skip_type_params(T))] +pub enum AccountType { + /// An account that is a contract. + Contract(ContractInfo), + + /// An account that is an externally owned account (EOA). + #[default] + EOA, +} + /// Information for managing an account and its sub trie abstraction. /// This is the required info to cache for an account. -#[derive(Encode, Decode, CloneNoBound, PartialEq, Eq, RuntimeDebug, TypeInfo, MaxEncodedLen)] +#[derive(Encode, Decode, CloneNoBound, PartialEq, Eq, DebugNoBound, TypeInfo, MaxEncodedLen)] #[scale_info(skip_type_params(T))] pub struct ContractInfo { /// Unique ID for the subtree encoded as a bytes vector. @@ -70,6 +121,73 @@ pub struct ContractInfo { immutable_data_len: u32, } +impl From for AccountIdOrAddress { + fn from(address: H160) -> Self { + AccountIdOrAddress::Address(address) + } +} + +impl AccountIdOrAddress { + pub fn address(&self) -> H160 { + match self { + AccountIdOrAddress::AccountId(id) => + >::to_address(id), + AccountIdOrAddress::Address(address) => *address, + } + } + + pub fn account_id(&self) -> AccountIdOf { + match self { + AccountIdOrAddress::AccountId(id) => id.clone(), + AccountIdOrAddress::Address(address) => T::AddressMapper::to_account_id(address), + } + } +} + +impl From> for AccountType { + fn from(contract_info: ContractInfo) -> Self { + AccountType::Contract(contract_info) + } +} + +impl AccountInfo { + /// Returns true if the account is a contract. + fn is_contract(address: &H160) -> bool { + let Some(info) = >::get(address) else { return false }; + matches!(info.account_type, AccountType::Contract(_)) + } + + /// Returns the balance of the account at the given address. + pub fn balance(account: AccountIdOrAddress) -> BalanceWithDust> { + use frame_support::traits::{ + fungible::Inspect, + tokens::{Fortitude::Polite, Preservation::Preserve}, + }; + + let value = T::Currency::reducible_balance(&account.account_id(), Preserve, Polite); + let dust = >::get(account.address()).map(|a| a.dust).unwrap_or_default(); + BalanceWithDust::new_unchecked::(value, dust) + } + + /// Loads the contract information for a given address. + pub fn load_contract(address: &H160) -> Option> { + let Some(info) = >::get(address) else { return None }; + let AccountType::Contract(contract_info) = info.account_type else { return None }; + Some(contract_info) + } + + /// Insert a contract, existing dust if any will be unchanged. + pub fn insert_contract(address: &H160, contract: ContractInfo) { + AccountInfoOf::::mutate(address, |account| { + if let Some(account) = account { + account.account_type = contract.clone().into(); + } else { + *account = Some(AccountInfo { account_type: contract.clone().into(), dust: 0 }); + } + }); + } +} + impl ContractInfo { /// Constructs a new contract info **without** writing it to storage. /// @@ -80,7 +198,7 @@ impl ContractInfo { nonce: T::Nonce, code_hash: sp_core::H256, ) -> Result { - if >::contains_key(address) { + if >::is_contract(address) { return Err(Error::::DuplicateContract.into()); } @@ -321,7 +439,7 @@ impl ContractInfo { /// Returns the code hash of the contract specified by `account` ID. pub fn load_code_hash(account: &AccountIdOf) -> Option { - >::get(&T::AddressMapper::to_address(account)).map(|i| i.code_hash) + >::load_contract(&T::AddressMapper::to_address(account)).map(|i| i.code_hash) } /// Returns the amount of immutable bytes of this contract. diff --git a/substrate/frame/revive/src/storage/meter.rs b/substrate/frame/revive/src/storage/meter.rs index 6a4738a6c1df8..f002b1f8b108d 100644 --- a/substrate/frame/revive/src/storage/meter.rs +++ b/substrate/frame/revive/src/storage/meter.rs @@ -33,7 +33,7 @@ use frame_support::{ }; use sp_runtime::{ traits::{Saturating, Zero}, - DispatchError, FixedPointNumber, FixedU128, + DispatchError, DispatchResult, FixedPointNumber, FixedU128, }; /// Deposit that uses the native fungible's balance type. @@ -104,6 +104,10 @@ pub struct RawMeter { /// We only have one charge per contract hence the size of this vector is /// limited by the maximum call depth. charges: Vec>, + /// True if this is the root meter. + /// + /// Sometimes we cannot know at compile time. + is_root: bool, /// Type parameter only used in impls. _phantom: PhantomData<(E, S)>, } @@ -308,8 +312,18 @@ where /// /// This will not perform a charge. It just records it to reflect it in the /// total amount of storage required for a transaction. - pub fn record_charge(&mut self, amount: &DepositOf) { - self.total_deposit = self.total_deposit.saturating_add(&amount); + pub fn record_charge(&mut self, amount: &DepositOf) -> DispatchResult { + let total_deposit = self.total_deposit.saturating_add(&amount); + + // Limits are enforced at the end of each frame. But plain balance transfers + // do not sapwn a frame. This is specifically to enforce the limit for those. + if self.is_root && total_deposit.charge_or_zero() > self.limit { + log::debug!( target: LOG_TARGET, "Storage deposit limit exhausted: {:?} > {:?}", amount, self.limit); + return Err(>::StorageDepositLimitExhausted.into()) + } + + self.total_deposit = total_deposit; + Ok(()) } /// The amount of balance that is still available from the original `limit`. @@ -338,12 +352,7 @@ where /// If the limit larger then what the origin can afford we will just fail /// when collecting the deposits in `try_into_deposit`. pub fn new(limit: BalanceOf) -> Self { - Self { limit, ..Default::default() } - } - - /// Create new storage meter without checking the limit. - pub fn new_unchecked(limit: BalanceOf) -> Self { - return Self { limit, ..Default::default() } + Self { limit, is_root: true, ..Default::default() } } /// The total amount of deposit that should change hands as result of the execution @@ -401,7 +410,8 @@ impl> RawMeter { /// If this functions is used the amount of the charge has to be stored by the caller somewhere /// alese in order to be able to refund it. pub fn charge_deposit(&mut self, contract: T::AccountId, amount: DepositOf) { - self.record_charge(&amount); + // will not fail in a nested meter + self.record_charge(&amount).ok(); self.charges.push(Charge { contract, amount, state: ContractState::Alive }); } diff --git a/substrate/frame/revive/src/test_utils/builder.rs b/substrate/frame/revive/src/test_utils/builder.rs index 6764607da015a..2769484c68558 100644 --- a/substrate/frame/revive/src/test_utils/builder.rs +++ b/substrate/frame/revive/src/test_utils/builder.rs @@ -18,7 +18,7 @@ use super::{deposit_limit, GAS_LIMIT}; use crate::{ address::AddressMapper, AccountIdOf, BalanceOf, BumpNonce, Code, Config, ContractResult, - DepositLimit, ExecReturnValue, InstantiateReturnValue, OriginFor, Pallet, Weight, + DepositLimit, ExecReturnValue, InstantiateReturnValue, OriginFor, Pallet, Weight, U256, }; use alloc::{vec, vec::Vec}; use frame_support::pallet_prelude::DispatchResultWithPostInfo; @@ -132,7 +132,7 @@ builder!( builder!( bare_instantiate( origin: OriginFor, - value: BalanceOf, + evm_value: U256, gas_limit: Weight, storage_deposit_limit: DepositLimit>, code: Code, @@ -141,6 +141,12 @@ builder!( bump_nonce: BumpNonce, ) -> ContractResult>; + /// Set the call's evm_value using a native_value amount. + pub fn native_value(mut self, value: BalanceOf) -> Self { + self.evm_value = Pallet::::convert_native_to_evm(value); + self + } + /// Build the instantiate call and unwrap the result. pub fn build_and_unwrap_result(self) -> InstantiateReturnValue { self.build().result.unwrap() @@ -160,7 +166,7 @@ builder!( pub fn bare_instantiate(origin: OriginFor, code: Code) -> Self { Self { origin, - value: 0u32.into(), + evm_value: Default::default(), gas_limit: GAS_LIMIT, storage_deposit_limit: DepositLimit::Balance(deposit_limit::()), code, @@ -198,12 +204,18 @@ builder!( bare_call( origin: OriginFor, dest: H160, - value: BalanceOf, + evm_value: U256, gas_limit: Weight, storage_deposit_limit: DepositLimit>, data: Vec, ) -> ContractResult>; + /// Set the call's evm_value using a native_value amount. + pub fn native_value(mut self, value: BalanceOf) -> Self { + self.evm_value = Pallet::::convert_native_to_evm(value); + self + } + /// Build the call and unwrap the result. pub fn build_and_unwrap_result(self) -> ExecReturnValue { self.build().result.unwrap() @@ -214,10 +226,33 @@ builder!( Self { origin, dest, - value: 0u32.into(), + evm_value: Default::default(), gas_limit: GAS_LIMIT, storage_deposit_limit: DepositLimit::Balance(deposit_limit::()), data: vec![], } } ); + +builder!( + eth_call( + origin: OriginFor, + dest: H160, + value: U256, + gas_limit: Weight, + storage_deposit_limit: BalanceOf, + data: Vec, + ) -> DispatchResultWithPostInfo; + + /// Create a [`EthCallBuilder`] with default values. + pub fn eth_call(origin: OriginFor, dest: H160) -> Self { + Self { + origin, + dest, + value: 0u32.into(), + gas_limit: GAS_LIMIT, + storage_deposit_limit: deposit_limit::(), + data: vec![], + } + } +); diff --git a/substrate/frame/revive/src/tests.rs b/substrate/frame/revive/src/tests.rs index a41d3afa5f21b..b3f7f94333c6b 100644 --- a/substrate/frame/revive/src/tests.rs +++ b/substrate/frame/revive/src/tests.rs @@ -26,16 +26,14 @@ use crate::{ exec::Key, limits, storage::DeletionQueueManager, - test_utils::*, + test_utils::{builder::Contract, *}, tests::test_utils::{get_contract, get_contract_checked}, tracing::trace, weights::WeightInfo, - AccountId32Mapper, BalanceOf, BumpNonce, Code, CodeInfoOf, Config, ContractInfo, - ContractInfoOf, DeletionQueueCounter, DepositLimit, Error, EthTransactError, HoldReason, - Origin, Pallet, PristineCode, H160, + AccountId32Mapper, AccountInfo, AccountInfoOf, BalanceOf, BalanceWithDust, BumpNonce, Code, + CodeInfoOf, Config, ContractInfo, DeletionQueueCounter, DepositLimit, Error, EthTransactError, + HoldReason, Origin, Pallet, PristineCode, StorageDeposit, H160, }; - -use crate::test_utils::builder::Contract; use assert_matches::assert_matches; use codec::Encode; use frame_support::{ @@ -55,12 +53,12 @@ use pallet_revive_fixtures::compile_module; use pallet_revive_uapi::{ReturnErrorCode as RuntimeReturnCode, ReturnFlags}; use pallet_transaction_payment::{ConstFeeMultiplier, Multiplier}; use pretty_assertions::{assert_eq, assert_ne}; -use sp_core::U256; +use sp_core::{Get, U256}; use sp_io::hashing::blake2_256; use sp_keystore::{testing::MemoryKeystore, KeystoreExt}; use sp_runtime::{ testing::H256, - traits::{BlakeTwo256, Convert, IdentityLookup, One}, + traits::{BlakeTwo256, Convert, IdentityLookup, One, Zero}, AccountId32, BuildStorage, DispatchError, Perbill, TokenError, }; @@ -94,10 +92,13 @@ macro_rules! assert_refcount { } pub mod test_utils { - use super::{CodeHashLockupDepositPercent, Contracts, DepositPerByte, DepositPerItem, Test}; + use super::{ + BalanceWithDust, CodeHashLockupDepositPercent, Contracts, DepositPerByte, DepositPerItem, + Test, + }; use crate::{ - address::AddressMapper, exec::AccountIdOf, BalanceOf, CodeInfo, CodeInfoOf, Config, - ContractInfo, ContractInfoOf, PristineCode, + address::AddressMapper, exec::AccountIdOf, AccountInfo, AccountInfoOf, BalanceOf, CodeInfo, + CodeInfoOf, Config, ContractInfo, PristineCode, }; use codec::{Encode, MaxEncodedLen}; use frame_support::traits::fungible::{InspectHold, Mutate}; @@ -109,7 +110,7 @@ pub mod test_utils { let address = <::AddressMapper as AddressMapper>::to_address(&address); let contract = >::new(&address, 0, code_hash).unwrap(); - >::insert(address, contract); + AccountInfo::::insert_contract(&address, contract); } pub fn set_balance(who: &AccountIdOf, amount: u64) { let _ = ::Currency::set_balance(who, amount); @@ -127,7 +128,7 @@ pub mod test_utils { get_contract_checked(addr).unwrap() } pub fn get_contract_checked(addr: &H160) -> Option> { - ContractInfoOf::::get(addr) + AccountInfo::::load_contract(addr) } pub fn get_code_deposit(code_hash: &sp_core::H256) -> BalanceOf { crate::CodeInfoOf::::get(code_hash).unwrap().deposit() @@ -174,6 +175,23 @@ pub mod test_utils { buffer[..8].copy_from_slice(&bytes); buffer } + + pub fn set_balance_with_dust(address: &H160, value: BalanceWithDust>) { + use frame_support::traits::Currency; + let ed = ::Currency::minimum_balance(); + let (value, dust) = value.deconstruct(); + let account_id = ::AddressMapper::to_account_id(&address); + ::Currency::set_balance(&account_id, ed + value); + if dust > 0 { + AccountInfoOf::::mutate(&address, |account| { + if let Some(account) = account { + account.dust = dust; + } else { + *account = Some(AccountInfo { dust, ..Default::default() }); + } + }); + } + } } mod builder { @@ -207,6 +225,10 @@ mod builder { pub fn call(dest: H160) -> CallBuilder { CallBuilder::::call(RuntimeOrigin::signed(ALICE), dest) } + + pub fn eth_call(dest: H160) -> EthCallBuilder { + EthCallBuilder::::eth_call(RuntimeOrigin::signed(ALICE), dest) + } } impl Test { @@ -393,12 +415,15 @@ impl ExtBuilder { self.set_associated_consts(); let mut t = frame_system::GenesisConfig::::default().build_storage().unwrap(); let checking_account = Pallet::::checking_account(); + pallet_balances::GenesisConfig:: { balances: vec![(checking_account.clone(), 1_000_000_000_000)], ..Default::default() } .assimilate_storage(&mut t) .unwrap(); + + crate::GenesisConfig::::default().assimilate_storage(&mut t).unwrap(); let mut ext = sp_io::TestExternalities::new(t); ext.register_extension(KeystoreExt::new(MemoryKeystore::new())); ext.execute_with(|| { @@ -434,17 +459,191 @@ impl Default for Origin { } #[test] -fn calling_plain_account_is_balance_transfer() { - ExtBuilder::default().build().execute_with(|| { - let _ = ::Currency::set_balance(&ALICE, 100_000_000); - assert!(!>::contains_key(BOB_ADDR)); - assert_eq!(test_utils::get_balance(&BOB_FALLBACK), 0); - let result = builder::bare_call(BOB_ADDR).value(42).build_and_unwrap_result(); - assert_eq!( - test_utils::get_balance(&BOB_FALLBACK), - 42 + ::Currency::minimum_balance() - ); - assert_eq!(result, Default::default()); +fn transfer_with_dust_works() { + struct TestCase { + description: &'static str, + from_balance: BalanceWithDust, + to_balance: BalanceWithDust, + amount: BalanceWithDust, + expected_from_balance: BalanceWithDust, + expected_to_balance: BalanceWithDust, + total_issuance_diff: i64, + } + + let plank: u32 = ::NativeToEthRatio::get(); + + let test_cases = vec![ + TestCase { + description: "without dust", + from_balance: BalanceWithDust::new_unchecked::(100, 0), + to_balance: BalanceWithDust::new_unchecked::(0, 0), + amount: BalanceWithDust::new_unchecked::(1, 0), + expected_from_balance: BalanceWithDust::new_unchecked::(99, 0), + expected_to_balance: BalanceWithDust::new_unchecked::(1, 0), + total_issuance_diff: 0, + }, + TestCase { + description: "with dust", + from_balance: BalanceWithDust::new_unchecked::(100, 0), + to_balance: BalanceWithDust::new_unchecked::(0, 0), + amount: BalanceWithDust::new_unchecked::(1, 10), + expected_from_balance: BalanceWithDust::new_unchecked::(98, plank - 10), + expected_to_balance: BalanceWithDust::new_unchecked::(1, 10), + total_issuance_diff: 1, + }, + TestCase { + description: "just dust", + from_balance: BalanceWithDust::new_unchecked::(100, 0), + to_balance: BalanceWithDust::new_unchecked::(0, 0), + amount: BalanceWithDust::new_unchecked::(0, 10), + expected_from_balance: BalanceWithDust::new_unchecked::(99, plank - 10), + expected_to_balance: BalanceWithDust::new_unchecked::(0, 10), + total_issuance_diff: 1, + }, + TestCase { + description: "with existing dust", + from_balance: BalanceWithDust::new_unchecked::(100, 5), + to_balance: BalanceWithDust::new_unchecked::(0, plank - 5), + amount: BalanceWithDust::new_unchecked::(1, 10), + expected_from_balance: BalanceWithDust::new_unchecked::(98, plank - 5), + expected_to_balance: BalanceWithDust::new_unchecked::(2, 5), + total_issuance_diff: 0, + }, + TestCase { + description: "with enough existing dust", + from_balance: BalanceWithDust::new_unchecked::(100, 10), + to_balance: BalanceWithDust::new_unchecked::(0, plank - 10), + amount: BalanceWithDust::new_unchecked::(1, 10), + expected_from_balance: BalanceWithDust::new_unchecked::(99, 0), + expected_to_balance: BalanceWithDust::new_unchecked::(2, 0), + total_issuance_diff: -1, + }, + TestCase { + description: "receiver dust less than 1 plank", + from_balance: BalanceWithDust::new_unchecked::(100, plank / 10), + to_balance: BalanceWithDust::new_unchecked::(0, plank / 2), + amount: BalanceWithDust::new_unchecked::(1, plank / 10 * 3), + expected_from_balance: BalanceWithDust::new_unchecked::(98, plank / 10 * 8), + expected_to_balance: BalanceWithDust::new_unchecked::(1, plank / 10 * 8), + total_issuance_diff: 1, + }, + ]; + + for TestCase { + description, + from_balance, + to_balance, + amount, + expected_from_balance, + expected_to_balance, + total_issuance_diff, + } in test_cases.into_iter() + { + ExtBuilder::default().build().execute_with(|| { + test_utils::set_balance_with_dust(&ALICE_ADDR, from_balance); + test_utils::set_balance_with_dust(&BOB_ADDR, to_balance); + + let total_issuance = ::Currency::total_issuance(); + let evm_value = Pallet::::convert_native_to_evm(amount); + + let (value, dust) = amount.deconstruct(); + assert_eq!(Pallet::::has_dust(evm_value), !dust.is_zero()); + assert_eq!(Pallet::::has_balance(evm_value), !value.is_zero()); + + let result = + builder::bare_call(BOB_ADDR).evm_value(evm_value).build_and_unwrap_result(); + assert_eq!(result, Default::default(), "{description} tx failed"); + + assert_eq!( + Pallet::::evm_balance(&ALICE_ADDR), + Pallet::::convert_native_to_evm(expected_from_balance), + "{description}: invalid from balance" + ); + + assert_eq!( + Pallet::::evm_balance(&BOB_ADDR), + Pallet::::convert_native_to_evm(expected_to_balance), + "{description}: invalid to balance" + ); + + assert_eq!( + total_issuance as i64 - total_issuance_diff, + ::Currency::total_issuance() as i64, + "{description}: total issuance should match" + ); + }); + } +} + +#[test] +fn eth_call_transfer_with_dust_works() { + let (binary, _) = compile_module("dummy").unwrap(); + ExtBuilder::default().existential_deposit(200).build().execute_with(|| { + let _ = ::Currency::set_balance(&ALICE, 1_000_000); + let Contract { addr, .. } = + builder::bare_instantiate(Code::Upload(binary)).build_and_unwrap_contract(); + + let balance = + Pallet::::convert_native_to_evm(BalanceWithDust::new_unchecked::(100, 10)); + assert_ok!(builder::eth_call(addr).value(balance).build()); + + assert_eq!(Pallet::::evm_balance(&addr), balance); + }); +} + +#[test] +fn contract_call_transfer_with_dust_works() { + let (binary_caller, _code_hash_caller) = compile_module("call_with_value").unwrap(); + let (binary_callee, _code_hash_callee) = compile_module("dummy").unwrap(); + ExtBuilder::default().existential_deposit(200).build().execute_with(|| { + let _ = ::Currency::set_balance(&ALICE, 1_000_000); + let Contract { addr: addr_caller, .. } = + builder::bare_instantiate(Code::Upload(binary_caller)) + .native_value(200) + .build_and_unwrap_contract(); + let Contract { addr: addr_callee, .. } = + builder::bare_instantiate(Code::Upload(binary_callee)).build_and_unwrap_contract(); + + let balance = + Pallet::::convert_native_to_evm(BalanceWithDust::new_unchecked::(100, 10)); + assert_ok!(builder::call(addr_caller).data((balance, addr_callee).encode()).build()); + + assert_eq!(Pallet::::evm_balance(&addr_callee), balance); + }); +} + +#[test] +fn deposit_limit_enforced_on_plain_transfer() { + ExtBuilder::default().existential_deposit(200).build().execute_with(|| { + let _ = ::Currency::set_balance(&ALICE, 1_000_000); + let _ = ::Currency::set_balance(&BOB, 1_000_000); + + // sending balance to a new account should fail when the limit is lower than the ed + let result = builder::bare_call(CHARLIE_ADDR) + .native_value(1) + .storage_deposit_limit(190.into()) + .build(); + assert_err!(result.result, >::StorageDepositLimitExhausted); + assert_eq!(result.storage_deposit, StorageDeposit::Charge(0)); + assert_eq!(test_utils::get_balance(&CHARLIE), 0); + + // works when the account is prefunded + let result = builder::bare_call(BOB_ADDR) + .native_value(1) + .storage_deposit_limit(0.into()) + .build(); + assert_ok!(result.result); + assert_eq!(result.storage_deposit, StorageDeposit::Charge(0)); + assert_eq!(test_utils::get_balance(&BOB), 1_000_001); + + // also works allowing enough deposit + let result = builder::bare_call(CHARLIE_ADDR) + .native_value(1) + .storage_deposit_limit(200.into()) + .build(); + assert_ok!(result.result); + assert_eq!(result.storage_deposit, StorageDeposit::Charge(200)); + assert_eq!(test_utils::get_balance(&CHARLIE), 201); }); } @@ -470,9 +669,9 @@ fn instantiate_and_call_and_deposit_event() { // Check at the end to get hash on error easily let Contract { addr, account_id } = builder::bare_instantiate(Code::Existing(code_hash)) - .value(value) + .native_value(value) .build_and_unwrap_contract(); - assert!(ContractInfoOf::::contains_key(&addr)); + assert!(AccountInfoOf::::contains_key(&addr)); assert_eq!( System::events(), @@ -552,7 +751,7 @@ fn create1_address_from_extrinsic() { let Contract { addr, .. } = builder::bare_instantiate(Code::Existing(code_hash)) .salt(None) .build_and_unwrap_contract(); - assert!(ContractInfoOf::::contains_key(&addr)); + assert!(AccountInfoOf::::contains_key(&addr)); assert_eq!( addr, create1(&::AddressMapper::to_address(&ALICE), nonce - 1) @@ -564,7 +763,7 @@ fn create1_address_from_extrinsic() { let Contract { addr, .. } = builder::bare_instantiate(Code::Upload(binary.clone())) .salt(None) .build_and_unwrap_contract(); - assert!(ContractInfoOf::::contains_key(&addr)); + assert!(AccountInfoOf::::contains_key(&addr)); assert_eq!( addr, create1(&::AddressMapper::to_address(&ALICE), nonce - 1) @@ -582,7 +781,7 @@ fn deposit_event_max_value_limit() { // Create let _ = ::Currency::set_balance(&ALICE, 1_000_000); let Contract { addr, .. } = builder::bare_instantiate(Code::Upload(binary)) - .value(30_000) + .native_value(30_000) .build_and_unwrap_contract(); // Call contract with allowed storage value. @@ -608,7 +807,7 @@ fn run_out_of_fuel_engine() { let _ = ::Currency::set_balance(&ALICE, 1_000_000); let Contract { addr, .. } = builder::bare_instantiate(Code::Upload(binary)) - .value(100 * min_balance) + .native_value(100 * min_balance) .build_and_unwrap_contract(); // Call the contract with a fixed gas limit. It must run out of gas because it just @@ -709,7 +908,7 @@ fn storage_work() { let _ = ::Currency::set_balance(&ALICE, 1_000_000); let min_balance = Contracts::min_balance(); let Contract { addr, .. } = builder::bare_instantiate(Code::Upload(code)) - .value(min_balance * 100) + .native_value(min_balance * 100) .build_and_unwrap_contract(); builder::bare_call(addr).build_and_unwrap_result(); @@ -724,7 +923,7 @@ fn storage_max_value_limit() { // Create let _ = ::Currency::set_balance(&ALICE, 1_000_000); let Contract { addr, .. } = builder::bare_instantiate(Code::Upload(binary)) - .value(30_000) + .native_value(30_000) .build_and_unwrap_contract(); get_contract(&addr); @@ -750,7 +949,7 @@ fn clear_storage_on_zero_value() { let _ = ::Currency::set_balance(&ALICE, 1_000_000); let min_balance = Contracts::min_balance(); let Contract { addr, .. } = builder::bare_instantiate(Code::Upload(code)) - .value(min_balance * 100) + .native_value(min_balance * 100) .build_and_unwrap_contract(); builder::bare_call(addr).build_and_unwrap_result(); @@ -765,7 +964,7 @@ fn transient_storage_work() { let _ = ::Currency::set_balance(&ALICE, 1_000_000); let min_balance = Contracts::min_balance(); let Contract { addr, .. } = builder::bare_instantiate(Code::Upload(code)) - .value(min_balance * 100) + .native_value(min_balance * 100) .build_and_unwrap_contract(); builder::bare_call(addr).build_and_unwrap_result(); @@ -825,7 +1024,7 @@ fn deploy_and_call_other_contract() { let _ = ::Currency::set_balance(&ALICE, 1_000_000); let Contract { addr: caller_addr, account_id: caller_account } = builder::bare_instantiate(Code::Upload(caller_binary)) - .value(100_000) + .native_value(100_000) .build_and_unwrap_contract(); let callee_addr = create2( @@ -916,13 +1115,13 @@ fn delegate_call() { // Instantiate the 'caller' let Contract { addr: caller_addr, .. } = builder::bare_instantiate(Code::Upload(caller_binary)) - .value(300_000) + .native_value(300_000) .build_and_unwrap_contract(); // Instantiate the 'callee' let Contract { addr: callee_addr, .. } = builder::bare_instantiate(Code::Upload(callee_binary)) - .value(100_000) + .native_value(100_000) .build_and_unwrap_contract(); assert_ok!(builder::call(caller_addr) @@ -942,7 +1141,7 @@ fn delegate_call_non_existant_is_noop() { // Instantiate the 'caller' let Contract { addr: caller_addr, .. } = builder::bare_instantiate(Code::Upload(caller_binary)) - .value(300_000) + .native_value(300_000) .build_and_unwrap_contract(); assert_ok!(builder::call(caller_addr) @@ -965,19 +1164,19 @@ fn delegate_call_with_weight_limit() { // Instantiate the 'caller' let Contract { addr: caller_addr, .. } = builder::bare_instantiate(Code::Upload(caller_binary)) - .value(300_000) + .native_value(300_000) .build_and_unwrap_contract(); // Instantiate the 'callee' let Contract { addr: callee_addr, .. } = builder::bare_instantiate(Code::Upload(callee_binary)) - .value(100_000) + .native_value(100_000) .build_and_unwrap_contract(); // fails, not enough weight assert_err!( builder::bare_call(caller_addr) - .value(1337) + .native_value(1337) .data((callee_addr, 100u64, 100u64).encode()) .build() .result, @@ -1002,20 +1201,20 @@ fn delegate_call_with_deposit_limit() { // Instantiate the 'caller' let Contract { addr: caller_addr, .. } = builder::bare_instantiate(Code::Upload(caller_binary)) - .value(300_000) + .native_value(300_000) .build_and_unwrap_contract(); // Instantiate the 'callee' let Contract { addr: callee_addr, .. } = builder::bare_instantiate(Code::Upload(callee_binary)) - .value(100_000) + .native_value(100_000) .build_and_unwrap_contract(); // Delegate call will write 1 storage and deposit of 2 (1 item) + 32 (bytes) is required. // + 32 + 16 for blake2_128concat // Fails, not enough deposit let ret = builder::bare_call(caller_addr) - .value(1337) + .native_value(1337) .data((callee_addr, 81u64).encode()) .build_and_unwrap_result(); assert_return_code!(ret, RuntimeReturnCode::OutOfResources); @@ -1035,7 +1234,7 @@ fn transfer_expendable_cannot_kill_account() { // Instantiate the BOB contract. let Contract { addr, .. } = builder::bare_instantiate(Code::Upload(binary)) - .value(1_000) + .native_value(1_000) .build_and_unwrap_contract(); // Check that the BOB contract has been instantiated. @@ -1074,7 +1273,7 @@ fn cannot_self_destruct_through_draining() { // Instantiate the BOB contract. let Contract { addr, .. } = builder::bare_instantiate(Code::Upload(binary)) - .value(value) + .native_value(value) .build_and_unwrap_contract(); let account = ::AddressMapper::to_account_id(&addr); @@ -1142,7 +1341,7 @@ fn cannot_self_destruct_while_live() { // Instantiate the BOB contract. let Contract { addr, .. } = builder::bare_instantiate(Code::Upload(binary)) - .value(100_000) + .native_value(100_000) .build_and_unwrap_contract(); // Check that the BOB contract has been instantiated. @@ -1170,7 +1369,7 @@ fn self_destruct_works() { // Instantiate the BOB contract. let contract = builder::bare_instantiate(Code::Upload(binary)) - .value(100_000) + .native_value(100_000) .build_and_unwrap_contract(); // Check that the BOB contract has been instantiated. @@ -1247,7 +1446,7 @@ fn destroy_contract_and_transfer_funds() { // construction. let Contract { addr: addr_bob, .. } = builder::bare_instantiate(Code::Upload(caller_binary)) - .value(200_000) + .native_value(200_000) .data(callee_code_hash.as_ref().to_vec()) .build_and_unwrap_contract(); @@ -1287,7 +1486,7 @@ fn crypto_hashes() { // Instantiate the CRYPTO_HASHES contract. let Contract { addr, .. } = builder::bare_instantiate(Code::Upload(binary)) - .value(100_000) + .native_value(100_000) .build_and_unwrap_contract(); // Perform the call. let input = b"_DEAD_BEEF"; @@ -1299,11 +1498,8 @@ fn crypto_hashes() { }; } // All hash functions and their associated output byte lengths. - let test_cases: &[(u8, Box Box<[u8]>>, usize)] = &[ - (2, dyn_hash_fn!(keccak_256), 32), - (3, dyn_hash_fn!(blake2_256), 32), - (4, dyn_hash_fn!(blake2_128), 16), - ]; + let test_cases: &[(u8, Box Box<[u8]>>, usize)] = + &[(2, dyn_hash_fn!(keccak_256), 32), (4, dyn_hash_fn!(blake2_128), 16)]; // Test the given hash functions for the input: "_DEAD_BEEF" for (n, hash_fn, expected_size) in test_cases.iter() { let mut params = vec![*n]; @@ -1324,7 +1520,7 @@ fn transfer_return_code() { let _ = ::Currency::set_balance(&ALICE, 1000 * min_balance); let contract = builder::bare_instantiate(Code::Upload(binary)) - .value(min_balance * 100) + .native_value(min_balance * 100) .build_and_unwrap_contract(); // Contract has only the minimal balance so any transfer will fail. @@ -1346,7 +1542,7 @@ fn call_return_code() { let _ = ::Currency::set_balance(&CHARLIE, 1000 * min_balance); let bob = builder::bare_instantiate(Code::Upload(caller_code)) - .value(min_balance * 100) + .native_value(min_balance * 100) .build_and_unwrap_contract(); // BOB cannot pay the ed which is needed to pull DJANGO into existence @@ -1362,11 +1558,12 @@ fn call_return_code() { // Contract calls into Django which is no valid contract // This will be a balance transfer into a new account // with more than the contract has which will make the transfer fail + let value = Pallet::::convert_native_to_evm(min_balance * 200); let result = builder::bare_call(bob.addr) .data( AsRef::<[u8]>::as_ref(&DJANGO_ADDR) .iter() - .chain(&u256_bytes(min_balance * 200)) + .chain(&value.to_little_endian()) .cloned() .collect(), ) @@ -1377,11 +1574,13 @@ fn call_return_code() { // The ED is charged from the call origin. let alice_before = test_utils::get_balance(&ALICE_FALLBACK); assert_eq!(test_utils::get_balance(&DJANGO_FALLBACK), 0); + + let value = Pallet::::convert_native_to_evm(1u64); let result = builder::bare_call(bob.addr) .data( AsRef::<[u8]>::as_ref(&DJANGO_ADDR) .iter() - .chain(&u256_bytes(1)) + .chain(&value.to_little_endian()) .cloned() .collect(), ) @@ -1392,15 +1591,16 @@ fn call_return_code() { let django = builder::bare_instantiate(Code::Upload(callee_code)) .origin(RuntimeOrigin::signed(CHARLIE)) - .value(min_balance * 100) + .native_value(min_balance * 100) .build_and_unwrap_contract(); // Sending more than the contract has will make the transfer fail. + let value = Pallet::::convert_native_to_evm(min_balance * 300); let result = builder::bare_call(bob.addr) .data( AsRef::<[u8]>::as_ref(&django.addr) .iter() - .chain(&u256_bytes(min_balance * 300)) + .chain(&value.to_little_endian()) .chain(&0u32.to_le_bytes()) .cloned() .collect(), @@ -1410,11 +1610,12 @@ fn call_return_code() { // Contract has enough balance but callee reverts because "1" is passed. ::Currency::set_balance(&bob.account_id, min_balance + 1000); + let value = Pallet::::convert_native_to_evm(5u64); let result = builder::bare_call(bob.addr) .data( AsRef::<[u8]>::as_ref(&django.addr) .iter() - .chain(&u256_bytes(5)) + .chain(&value.to_little_endian()) .chain(&1u32.to_le_bytes()) .cloned() .collect(), @@ -1427,7 +1628,7 @@ fn call_return_code() { .data( AsRef::<[u8]>::as_ref(&django.addr) .iter() - .chain(&u256_bytes(5)) + .chain(&value.to_little_endian()) .chain(&2u32.to_le_bytes()) .cloned() .collect(), @@ -1450,7 +1651,7 @@ fn instantiate_return_code() { assert_ok!(builder::instantiate_with_code(callee_code).value(min_balance * 100).build()); let contract = builder::bare_instantiate(Code::Upload(caller_code)) - .value(min_balance * 100) + .native_value(min_balance * 100) .build_and_unwrap_contract(); // bob cannot pay the ED to create the contract as he has no money @@ -1507,7 +1708,7 @@ fn lazy_removal_works() { let _ = ::Currency::set_balance(&ALICE, 1000 * min_balance); let contract = builder::bare_instantiate(Code::Upload(code)) - .value(min_balance * 100) + .native_value(min_balance * 100) .build_and_unwrap_contract(); let info = get_contract(&contract.addr); @@ -1520,7 +1721,7 @@ fn lazy_removal_works() { assert_ok!(builder::call(contract.addr).build()); // Contract info should be gone - assert!(!>::contains_key(&contract.addr)); + assert!(!>::contains_key(&contract.addr)); // But value should be still there as the lazy removal did not run, yet. assert_matches!(child::get(trie, &[99]), Some(42)); @@ -1543,7 +1744,7 @@ fn lazy_batch_removal_works() { for i in 0..3u8 { let contract = builder::bare_instantiate(Code::Upload(code.clone())) - .value(min_balance * 100) + .native_value(min_balance * 100) .salt(Some([i; 32])) .build_and_unwrap_contract(); @@ -1557,7 +1758,7 @@ fn lazy_batch_removal_works() { // there as the lazy removal did not run, yet. assert_ok!(builder::call(contract.addr).build()); - assert!(!>::contains_key(&contract.addr)); + assert!(!>::contains_key(&contract.addr)); assert_matches!(child::get(trie, &[99]), Some(42)); tries.push(trie.clone()) @@ -1613,7 +1814,7 @@ fn lazy_removal_partial_remove_works() { let _ = ::Currency::set_balance(&ALICE, 1000 * min_balance); let Contract { addr, .. } = builder::bare_instantiate(Code::Upload(code)) - .value(min_balance * 100) + .native_value(min_balance * 100) .build_and_unwrap_contract(); let info = get_contract(&addr); @@ -1622,13 +1823,13 @@ fn lazy_removal_partial_remove_works() { for val in &vals { info.write(&Key::Fix(val.0), Some(val.2.clone()), None, false).unwrap(); } - >::insert(&addr, info.clone()); + AccountInfo::::insert_contract(&addr, info.clone()); // Terminate the contract assert_ok!(builder::call(addr).build()); // Contract info should be gone - assert!(!>::contains_key(&addr)); + assert!(!>::contains_key(&addr)); let trie = info.child_trie_info(); @@ -1677,7 +1878,7 @@ fn lazy_removal_does_no_run_on_low_remaining_weight() { let _ = ::Currency::set_balance(&ALICE, 1000 * min_balance); let Contract { addr, .. } = builder::bare_instantiate(Code::Upload(code)) - .value(min_balance * 100) + .native_value(min_balance * 100) .build_and_unwrap_contract(); let info = get_contract(&addr); @@ -1690,7 +1891,7 @@ fn lazy_removal_does_no_run_on_low_remaining_weight() { assert_ok!(builder::call(addr).build()); // Contract info should be gone - assert!(!>::contains_key(&addr)); + assert!(!>::contains_key(&addr)); // But value should be still there as the lazy removal did not run, yet. assert_matches!(child::get(trie, &[99]), Some(42)); @@ -1731,7 +1932,7 @@ fn lazy_removal_does_not_use_all_weight() { let _ = ::Currency::set_balance(&ALICE, 1000 * min_balance); let Contract { addr, .. } = builder::bare_instantiate(Code::Upload(code)) - .value(min_balance * 100) + .native_value(min_balance * 100) .build_and_unwrap_contract(); let info = get_contract(&addr); @@ -1747,13 +1948,13 @@ fn lazy_removal_does_not_use_all_weight() { for val in &vals { info.write(&Key::Fix(val.0), Some(val.2.clone()), None, false).unwrap(); } - >::insert(&addr, info.clone()); + AccountInfo::::insert_contract(&addr, info.clone()); // Terminate the contract assert_ok!(builder::call(addr).build()); // Contract info should be gone - assert!(!>::contains_key(&addr)); + assert!(!>::contains_key(&addr)); let trie = info.child_trie_info(); @@ -1805,7 +2006,7 @@ fn deletion_queue_ring_buffer_overflow() { // add 3 contracts to the deletion queue for i in 0..3u8 { let Contract { addr, .. } = builder::bare_instantiate(Code::Upload(code.clone())) - .value(min_balance * 100) + .native_value(min_balance * 100) .salt(Some([i; 32])) .build_and_unwrap_contract(); @@ -1819,7 +2020,7 @@ fn deletion_queue_ring_buffer_overflow() { // there as the lazy removal did not run, yet. assert_ok!(builder::call(addr).build()); - assert!(!>::contains_key(&addr)); + assert!(!>::contains_key(&addr)); assert_matches!(child::get(trie, &[99]), Some(42)); tries.push(trie.clone()) @@ -1846,18 +2047,18 @@ fn refcounter() { // Create two contracts with the same code and check that they do in fact share it. let Contract { addr: addr0, .. } = builder::bare_instantiate(Code::Upload(binary.clone())) - .value(min_balance * 100) + .native_value(min_balance * 100) .salt(Some([0; 32])) .build_and_unwrap_contract(); let Contract { addr: addr1, .. } = builder::bare_instantiate(Code::Upload(binary.clone())) - .value(min_balance * 100) + .native_value(min_balance * 100) .salt(Some([1; 32])) .build_and_unwrap_contract(); assert_refcount!(code_hash, 2); // Sharing should also work with the usual instantiate call let Contract { addr: addr2, .. } = builder::bare_instantiate(Code::Existing(code_hash)) - .value(min_balance * 100) + .native_value(min_balance * 100) .salt(Some([2; 32])) .build_and_unwrap_contract(); assert_refcount!(code_hash, 3); @@ -1892,11 +2093,11 @@ fn gas_estimation_for_subcalls() { let Contract { addr: addr_caller, .. } = builder::bare_instantiate(Code::Upload(caller_code)) - .value(min_balance * 100) + .native_value(min_balance * 100) .build_and_unwrap_contract(); let Contract { addr: addr_dummy, .. } = builder::bare_instantiate(Code::Upload(dummy_code)) - .value(min_balance * 100) + .native_value(min_balance * 100) .build_and_unwrap_contract(); // Run the test for all of those weight limits for the subcall @@ -1968,7 +2169,7 @@ fn call_runtime_reentrancy_guarded() { let Contract { addr: addr_callee, .. } = builder::bare_instantiate(Code::Upload(callee_code)) - .value(min_balance * 100) + .native_value(min_balance * 100) .salt(Some([1; 32])) .build_and_unwrap_contract(); @@ -2004,7 +2205,7 @@ fn sr25519_verify() { // Instantiate the sr25519_verify contract. let Contract { addr, .. } = builder::bare_instantiate(Code::Upload(binary)) - .value(100_000) + .native_value(100_000) .build_and_unwrap_contract(); let call_with = |message: &[u8; 11]| { @@ -2254,7 +2455,7 @@ fn instantiate_with_below_existential_deposit_works() { // Instantiate the BOB contract. let Contract { addr, account_id } = builder::bare_instantiate(Code::Upload(binary)) - .value(value) + .native_value(value) .build_and_unwrap_contract(); // Ensure the contract was stored and get expected deposit amount to be reserved. @@ -2371,12 +2572,11 @@ fn storage_deposit_callee_works() { let (binary_callee, _code_hash_callee) = compile_module("store_call").unwrap(); ExtBuilder::default().existential_deposit(200).build().execute_with(|| { let _ = ::Currency::set_balance(&ALICE, 1_000_000); - let min_balance = Contracts::min_balance(); // Create both contracts: Constructors do nothing. let Contract { addr: addr_caller, .. } = builder::bare_instantiate(Code::Upload(binary_caller)).build_and_unwrap_contract(); - let Contract { addr: addr_callee, account_id } = + let Contract { addr: addr_callee, .. } = builder::bare_instantiate(Code::Upload(binary_callee)).build_and_unwrap_contract(); assert_ok!(builder::call(addr_caller).data((100u32, &addr_callee).encode()).build()); @@ -2384,7 +2584,7 @@ fn storage_deposit_callee_works() { let callee = get_contract(&addr_callee); let deposit = DepositPerByte::get() * 100 + DepositPerItem::get() * 1 + 48; - assert_eq!(test_utils::get_balance(&account_id), min_balance); + assert_eq!(Pallet::::evm_balance(&addr_caller), U256::zero()); assert_eq!( callee.total_deposit(), deposit + test_utils::contract_base_deposit(&addr_callee) @@ -2465,7 +2665,7 @@ fn slash_cannot_kill_account() { let min_balance = Contracts::min_balance(); let Contract { addr, account_id } = builder::bare_instantiate(Code::Upload(binary)) - .value(value) + .native_value(value) .build_and_unwrap_contract(); // Drop previous events @@ -2536,7 +2736,7 @@ fn contract_reverted() { .build_and_unwrap_result(); assert_eq!(result.result.flags, flags); assert_eq!(result.result.data, buffer); - assert!(!>::contains_key(result.addr)); + assert!(!>::contains_key(result.addr)); // Pass empty flags and therefore successfully instantiate the contract for later use. let Contract { addr, .. } = builder::bare_instantiate(Code::Existing(code_hash)) @@ -2566,7 +2766,7 @@ fn set_code_hash() { // Instantiate the 'caller' let Contract { addr: contract_addr, .. } = builder::bare_instantiate(Code::Upload(binary)) - .value(300_000) + .native_value(300_000) .build_and_unwrap_contract(); // upload new code assert_ok!(Contracts::upload_code( @@ -2747,7 +2947,7 @@ fn deposit_limit_in_nested_instantiate() { // Create caller contract let Contract { addr: addr_caller, account_id: caller_id } = builder::bare_instantiate(Code::Upload(binary_caller)) - .value(10_000u64) // this balance is later passed to the deployed contract + .native_value(10_000) // this balance is later passed to the deployed contract .build_and_unwrap_contract(); // Deploy a contract to get its occupied storage size let Contract { addr, .. } = builder::bare_instantiate(Code::Upload(binary_callee)) @@ -2762,7 +2962,8 @@ fn deposit_limit_in_nested_instantiate() { // - 2 for the storage item of 0 bytes being created in the callee constructor // - 48 for the key let callee_min_deposit = { - let callee_info_len = ContractInfoOf::::get(&addr).unwrap().encoded_size() as u64; + let callee_info_len = + AccountInfo::::load_contract(&addr).unwrap().encoded_size() as u64; let code_deposit = test_utils::lockup_deposit(&code_hash_callee); callee_info_len + code_deposit + 2 + ED + 2 + 48 }; @@ -3232,6 +3433,35 @@ fn balance_api_returns_free_balance() { }); } +#[test] +fn call_depth_is_enforced() { + let (binary, _code_hash) = compile_module("recurse").unwrap(); + ExtBuilder::default().existential_deposit(200).build().execute_with(|| { + let _ = ::Currency::set_balance(&ALICE, 1_000_000); + + let extra_recursions = 1024; + + let Contract { addr, .. } = + builder::bare_instantiate(Code::Upload(binary.to_vec())).build_and_unwrap_contract(); + + // takes the number of recursions + // returns the number of left over recursions + assert_eq!( + u32::from_le_bytes( + builder::bare_call(addr) + .data((limits::CALL_STACK_DEPTH + extra_recursions).encode()) + .build_and_unwrap_result() + .data + .try_into() + .unwrap() + ), + // + 1 because when the call depth is reached the caller contract is trapped without + // the ability to return any data. hence the last call frame is untracked. + extra_recursions + 1, + ); + }); +} + #[test] fn gas_consumed_is_linear_for_nested_calls() { let (code, _code_hash) = compile_module("recurse").unwrap(); @@ -3246,7 +3476,10 @@ fn gas_consumed_is_linear_for_nested_calls() { .iter() .map(|i| { let result = builder::bare_call(addr).data(i.encode()).build(); - assert_ok!(result.result); + assert_eq!( + u32::from_le_bytes(result.result.unwrap().data.try_into().unwrap()), + 0 + ); result.gas_consumed }) .collect::>() @@ -4084,7 +4317,7 @@ fn tracing_works_for_transfers() { let _ = ::Currency::set_balance(&ALICE, 100_000_000); let mut tracer = CallTracer::new(Default::default(), |_| U256::zero()); trace(&mut tracer, || { - builder::bare_call(BOB_ADDR).value(10_000_000).build_and_unwrap_result(); + builder::bare_call(BOB_ADDR).evm_value(10.into()).build_and_unwrap_result(); }); let trace = tracer.collect_trace(); @@ -4093,7 +4326,7 @@ fn tracing_works_for_transfers() { Some(CallTrace { from: ALICE_ADDR, to: BOB_ADDR, - value: Some(U256::from(10_000_000)), + value: Some(U256::from(10)), call_type: CallType::Call, ..Default::default() }) @@ -4114,7 +4347,7 @@ fn call_tracing_works() { builder::bare_instantiate(Code::Upload(binary_callee)).build_and_unwrap_contract(); let Contract { addr, .. } = - builder::bare_instantiate(Code::Upload(code)).value(10_000_000).build_and_unwrap_contract(); + builder::bare_instantiate(Code::Upload(code)).evm_value(10_000_000.into()).build_and_unwrap_contract(); let tracer_configs = vec![ @@ -4269,7 +4502,7 @@ fn create_call_tracing_works() { let Contract { addr, .. } = trace(&mut tracer, || { builder::bare_instantiate(Code::Upload(code.clone())) - .value(100) + .evm_value(100.into()) .salt(None) .build_and_unwrap_contract() }); @@ -4334,7 +4567,7 @@ fn prestate_tracing_works() { .build_and_unwrap_contract(); let Contract { addr, .. } = builder::bare_instantiate(Code::Upload(code.clone())) - .value(10_000_000) + .native_value(10) .build_and_unwrap_contract(); // redact balance so that tests are resilient to weight changes @@ -4536,68 +4769,67 @@ fn pure_precompile_works() { let cases = vec![ ( - // ECRecover + "ECRecover", H160::from_low_u64_be(1), hex!("18c547e4f7b0f325ad1e56f57e26c745b09a3e503d86e00e5255ff7f715d3d1c000000000000000000000000000000000000000000000000000000000000001c73b1693892219d736caba55bdb67216e485557ea6b6af75f37096c9aa6a5a75feeb940b1d03b21e36b0e47e79769f095fe2ab855bd91e3a38756b7d75a9c4549").to_vec(), hex!("000000000000000000000000a94f5374fce5edbc8e2a8697c15331677e6ebf0b").to_vec(), ), ( - // Sha256 + "Sha256", H160::from_low_u64_be(2), hex!("ec07171c4f0f0e2b").to_vec(), hex!("d0591ea667763c69a5f5a3bae657368ea63318b2c9c8349cccaf507e3cbd7c7a").to_vec(), ), ( - // Ripemd160 + "Ripemd160", H160::from_low_u64_be(3), hex!("ec07171c4f0f0e2b").to_vec(), hex!("000000000000000000000000a9c5ebaf7589fd8acfd542c3a008956de84fbeb7").to_vec(), ), ( - // Identity + "Identity", H160::from_low_u64_be(4), [42u8; 128].to_vec(), [42u8; 128].to_vec(), ), ( - // Modexp + "Modexp", H160::from_low_u64_be(5), hex!("00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002003fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2efffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f").to_vec(), hex!("0000000000000000000000000000000000000000000000000000000000000001").to_vec(), ), ( - // Bn128Add + "Bn128Add", H160::from_low_u64_be(6), hex!("18b18acfb4c2c30276db5411368e7185b311dd124691610c5d3b74034e093dc9063c909c4720840cb5134cb9f59fa749755796819658d32efc0d288198f3726607c2b7f58a84bd6145f00c9c2bc0bb1a187f20ff2c92963a88019e7c6a014eed06614e20c147e940f2d70da3f74c9a17df361706a4485c742bd6788478fa17d7").to_vec(), hex!("2243525c5efd4b9c3d3c45ac0ca3fe4dd85e830a4ce6b65fa1eeaee202839703301d1d33be6da8e509df21cc35964723180eed7532537db9ae5e7d48f195c915").to_vec(), ), ( - // Bn128Mul + "Bn128Mul", H160::from_low_u64_be(7), hex!("2bd3e6d0f3b142924f5ca7b49ce5b9d54c4703d7ae5648e61d02268b1a0a9fb721611ce0a6af85915e2f1d70300909ce2e49dfad4a4619c8390cae66cefdb20400000000000000000000000000000000000000000000000011138ce750fa15c2").to_vec(), hex!("070a8d6a982153cae4be29d434e8faef8a47b274a053f5a4ee2a6c9c13c31e5c031b8ce914eba3a9ffb989f9cdd5b0f01943074bf4f0f315690ec3cec6981afc").to_vec(), ), ( - // Bn128Pairing + "Bn128Pairing", H160::from_low_u64_be(8), hex!("1c76476f4def4bb94541d57ebba1193381ffa7aa76ada664dd31c16024c43f593034dd2920f673e204fee2811c678745fc819b55d3e9d294e45c9b03a76aef41209dd15ebff5d46c4bd888e51a93cf99a7329636c63514396b4a452003a35bf704bf11ca01483bfa8b34b43561848d28905960114c8ac04049af4b6315a416782bb8324af6cfc93537a2ad1a445cfd0ca2a71acd7ac41fadbf933c2a51be344d120a2a4cf30c1bf9845f20c6fe39e07ea2cce61f0c9bb048165fe5e4de877550111e129f1cf1097710d41c4ac70fcdfa5ba2023c6ff1cbeac322de49d1b6df7c2032c61a830e3c17286de9462bf242fca2883585b93870a73853face6a6bf411198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa").to_vec(), hex!("0000000000000000000000000000000000000000000000000000000000000001").to_vec(), ), ( - // Blake2F + "Blake2F", H160::from_low_u64_be(9), hex!("0000000048c9bdf267e6096a3ba7ca8485ae67bb2bf894fe72f36e3cf1361d5f3af54fa5d182e6ad7f520e511f6c3e2b8c68059b6bbd41fbabd9831f79217e1319cde05b61626300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000001").to_vec(), hex!("08c9bcf367e6096a3ba7ca8485ae67bb2bf894fe72f36e3cf1361d5f3af54fa5d282e6ad7f520e511f6c3e2b8c68059b9442be0454267ce079217e1319cde05b").to_vec(), ), ]; - for (precompile_addr, input, output) in cases { + for (description, precompile_addr, input, output) in cases { let (code, _code_hash) = compile_module("call_and_return").unwrap(); ExtBuilder::default().build().execute_with(|| { - let id = ::AddressMapper::to_account_id(&precompile_addr); let _ = ::Currency::set_balance(&ALICE, 100_000_000_000); let Contract { addr, .. } = builder::bare_instantiate(Code::Upload(code)) - .value(1000) + .native_value(1_000) .build_and_unwrap_contract(); let result = builder::bare_call(addr) @@ -4610,11 +4842,15 @@ fn pure_precompile_works() { ) .build_and_unwrap_result(); - assert_eq!(test_utils::get_balance(&id), 101u64); + assert_eq!( + Pallet::::evm_balance(&precompile_addr), + U256::from(100), + "{description}: unexpected balance" + ); assert_eq!( alloy_core::hex::encode(result.data), alloy_core::hex::encode(output), - "Unexpected output for precompile: {precompile_addr:?}", + "{description} Unexpected output for precompile: {precompile_addr:?}", ); assert_eq!(result.flags, ReturnFlags::empty()); }); @@ -4658,6 +4894,38 @@ fn precompiles_work() { Panic::from(PanicKind::ResourceError).abi_encode(), RuntimeReturnCode::CalleeReverted, ), + ( + INoInfo::INoInfoCalls::passData(INoInfo::passDataCall { + inputLen: limits::CALLDATA_BYTES, + }) + .abi_encode(), + Vec::new(), + RuntimeReturnCode::Success, + ), + ( + INoInfo::INoInfoCalls::passData(INoInfo::passDataCall { + inputLen: limits::CALLDATA_BYTES + 1, + }) + .abi_encode(), + Vec::new(), + RuntimeReturnCode::CalleeTrapped, + ), + ( + INoInfo::INoInfoCalls::returnData(INoInfo::returnDataCall { + returnLen: limits::CALLDATA_BYTES - 4, + }) + .abi_encode(), + vec![42u8; limits::CALLDATA_BYTES as usize - 4], + RuntimeReturnCode::Success, + ), + ( + INoInfo::INoInfoCalls::returnData(INoInfo::returnDataCall { + returnLen: limits::CALLDATA_BYTES + 1, + }) + .abi_encode(), + vec![], + RuntimeReturnCode::CalleeTrapped, + ), ]; for (input, output, error_code) in cases { @@ -4666,7 +4934,7 @@ fn precompiles_work() { let id = ::AddressMapper::to_account_id(&precompile_addr); let _ = ::Currency::set_balance(&ALICE, 100_000_000_000); let Contract { addr, .. } = builder::bare_instantiate(Code::Upload(code)) - .value(1000) + .native_value(1000) .build_and_unwrap_contract(); let result = builder::bare_call(addr) @@ -4678,7 +4946,7 @@ fn precompiles_work() { // no account or contract info should be created for a NoInfo pre-compile assert!(test_utils::get_contract_checked(&precompile_addr).is_none()); assert!(!System::account_exists(&id)); - assert_eq!(test_utils::get_balance(&id), 0u64); + assert_eq!(Pallet::::evm_balance(&precompile_addr), U256::zero()); assert_eq!(result.flags, ReturnFlags::empty()); assert_eq!(u32::from_le_bytes(result.data[..4].try_into().unwrap()), error_code as u32); @@ -4711,7 +4979,7 @@ fn precompiles_with_info_creates_contract() { let id = ::AddressMapper::to_account_id(&precompile_addr); let _ = ::Currency::set_balance(&ALICE, 100_000_000_000); let Contract { addr, .. } = builder::bare_instantiate(Code::Upload(code)) - .value(1000) + .native_value(1000) .build_and_unwrap_contract(); let result = builder::bare_call(addr) @@ -4723,7 +4991,7 @@ fn precompiles_with_info_creates_contract() { // a pre-compile with contract info should create an account on first call assert!(test_utils::get_contract_checked(&precompile_addr).is_some()); assert!(System::account_exists(&id)); - assert_eq!(test_utils::get_balance(&id), 1u64); + assert_eq!(Pallet::::evm_balance(&precompile_addr), U256::from(0)); assert_eq!(result.flags, ReturnFlags::empty()); assert_eq!(u32::from_le_bytes(result.data[..4].try_into().unwrap()), error_code as u32); @@ -4795,7 +5063,7 @@ fn code_size_for_precompiles_works() { ExtBuilder::default().build().execute_with(|| { let _ = ::Currency::set_balance(&ALICE, 100_000_000_000); let Contract { addr, .. } = builder::bare_instantiate(Code::Upload(code)) - .value(1000) + .native_value(1000) .build_and_unwrap_contract(); // the primitive pre-compiles return 0 code size on eth @@ -4809,3 +5077,141 @@ fn code_size_for_precompiles_works() { .build_and_unwrap_result(); }); } + +#[test] +fn call_data_limit_is_enforced_subcalls() { + let (code, _code_hash) = compile_module("call_with_input_size").unwrap(); + + ExtBuilder::default().build().execute_with(|| { + let _ = ::Currency::set_balance(&ALICE, 100_000_000_000); + let Contract { addr, .. } = + builder::bare_instantiate(Code::Upload(code)).build_and_unwrap_contract(); + + let cases: Vec<(u32, Box)> = vec![ + ( + 0_u32, + Box::new(|result| { + assert_ok!(result); + }), + ), + ( + 1_u32, + Box::new(|result| { + assert_ok!(result); + }), + ), + ( + limits::CALLDATA_BYTES, + Box::new(|result| { + assert_ok!(result); + }), + ), + ( + limits::CALLDATA_BYTES + 1, + Box::new(|result| { + assert_err!(result, >::CallDataTooLarge); + }), + ), + ]; + + for (callee_input_size, assert_result) in cases { + let result = builder::bare_call(addr).data(callee_input_size.encode()).build().result; + assert_result(result); + } + }); +} + +#[test] +fn call_data_limit_is_enforced_root_call() { + let (code, _code_hash) = compile_module("dummy").unwrap(); + + ExtBuilder::default().build().execute_with(|| { + let _ = ::Currency::set_balance(&ALICE, 100_000_000_000); + let Contract { addr, .. } = + builder::bare_instantiate(Code::Upload(code)).build_and_unwrap_contract(); + + let cases: Vec<(H160, u32, Box)> = vec![ + ( + addr, + 0_u32, + Box::new(|result| { + assert_ok!(result); + }), + ), + ( + addr, + 1_u32, + Box::new(|result| { + assert_ok!(result); + }), + ), + ( + addr, + limits::CALLDATA_BYTES, + Box::new(|result| { + assert_ok!(result); + }), + ), + ( + addr, + limits::CALLDATA_BYTES + 1, + Box::new(|result| { + assert_err!(result, >::CallDataTooLarge); + }), + ), + ( + // limit is not enforced when tx calls EOA + BOB_ADDR, + limits::CALLDATA_BYTES + 1, + Box::new(|result| { + assert_ok!(result); + }), + ), + ]; + + for (addr, callee_input_size, assert_result) in cases { + let result = builder::bare_call(addr) + .data(vec![42; callee_input_size as usize]) + .build() + .result; + assert_result(result); + } + }); +} + +#[test] +fn return_data_limit_is_enforced() { + let (code, _code_hash) = compile_module("return_sized").unwrap(); + + ExtBuilder::default().build().execute_with(|| { + let _ = ::Currency::set_balance(&ALICE, 100_000_000_000); + let Contract { addr, .. } = + builder::bare_instantiate(Code::Upload(code)).build_and_unwrap_contract(); + + let cases: Vec<(u32, Box)> = vec![ + ( + 1_u32, + Box::new(|result| { + assert_ok!(result); + }), + ), + ( + limits::CALLDATA_BYTES, + Box::new(|result| { + assert_ok!(result); + }), + ), + ( + limits::CALLDATA_BYTES + 1, + Box::new(|result| { + assert_err!(result, >::ReturnDataTooLarge); + }), + ), + ]; + + for (return_size, assert_result) in cases { + let result = builder::bare_call(addr).data(return_size.encode()).build().result; + assert_result(result); + } + }); +} diff --git a/substrate/frame/revive/src/tests/precompiles.rs b/substrate/frame/revive/src/tests/precompiles.rs index 288c98ef76499..b10e83e1d1fa7 100644 --- a/substrate/frame/revive/src/tests/precompiles.rs +++ b/substrate/frame/revive/src/tests/precompiles.rs @@ -20,7 +20,7 @@ use crate::{ exec::{ErrorOrigin, ExecError}, precompiles::{AddressMatcher, Error, Ext, ExtWithInfo, Precompile, Token}, - Config, DispatchError, Origin, Weight, + Config, DispatchError, Origin, Weight, U256, }; use alloc::vec::Vec; use alloy_core::{ @@ -44,6 +44,8 @@ sol! { function errors() external; function consumeMaxGas() external; function callRuntime(bytes memory call) external; + function passData(uint32 inputLen) external; + function returnData(uint32 returnLen) external returns (bytes); } } @@ -105,6 +107,20 @@ impl Precompile for NoInfo { Err(Error::Error(ExecError { error: e.error, origin: ErrorOrigin::Caller })), } }, + INoInfoCalls::passData(INoInfo::passDataCall { inputLen }) => { + env.call( + Weight::MAX, + U256::MAX, + &env.address(), + 0.into(), + vec![42; *inputLen as usize], + true, + false, + )?; + Ok(Vec::new()) + }, + INoInfoCalls::returnData(INoInfo::returnDataCall { returnLen }) => + Ok(vec![42; *returnLen as usize]), } } } diff --git a/substrate/frame/revive/src/vm/mod.rs b/substrate/frame/revive/src/vm/mod.rs index d55250ff2ac90..ced372c320ba1 100644 --- a/substrate/frame/revive/src/vm/mod.rs +++ b/substrate/frame/revive/src/vm/mod.rs @@ -383,6 +383,14 @@ impl ContractBlob { })?; instance.set_gas(gas_limit_polkavm); + instance + .set_interpreter_cache_size_limit(Some(polkavm::SetCacheSizeLimitArgs { + max_block_size: limits::code::BASIC_BLOCK_SIZE, + max_cache_size_bytes: limits::code::INTERPRETER_CACHE_BYTES + .try_into() + .map_err(|_| Error::::CodeRejected)?, + })) + .map_err(|_| Error::::CodeRejected)?; instance.prepare_call_untyped(entry_program_counter, &[]); Ok(PreparedCall { module, instance, runtime }) diff --git a/substrate/frame/revive/src/vm/runtime.rs b/substrate/frame/revive/src/vm/runtime.rs index 5a18d909c421b..c03544c39738e 100644 --- a/substrate/frame/revive/src/vm/runtime.rs +++ b/substrate/frame/revive/src/vm/runtime.rs @@ -26,7 +26,7 @@ use crate::{ precompiles::{All as AllPrecompiles, Precompiles}, primitives::ExecReturnValue, weights::WeightInfo, - Config, Error, LOG_TARGET, SENTINEL, + Config, Error, Pallet, LOG_TARGET, SENTINEL, }; use alloc::{vec, vec::Vec}; use codec::Encode; @@ -35,7 +35,7 @@ use frame_support::{ensure, traits::Get, weights::Weight}; use pallet_revive_proc_macro::define_env; use pallet_revive_uapi::{CallFlags, ReturnErrorCode, ReturnFlags, StorageFlags}; use sp_core::{H160, H256, U256}; -use sp_io::hashing::{blake2_128, blake2_256, keccak_256}; +use sp_io::hashing::{blake2_128, keccak_256}; use sp_runtime::{DispatchError, RuntimeDebug}; /// Abstraction over the memory access within syscalls. @@ -66,6 +66,13 @@ pub trait Memory { /// - designated area is not within the bounds of the sandbox memory. fn zero(&mut self, ptr: u32, len: u32) -> Result<(), DispatchError>; + /// This will reset all compilation artifacts of the currently executing instance. + /// + /// This is used before we call into a new contract to free up some memory. Doing + /// so we make sure that we only ever have to hold one compilation cache at a time + /// independtently of of our call stack depth. + fn reset_interpreter_cache(&mut self); + /// Read designated chunk from the sandbox memory. /// /// Returns `Err` if one of the following conditions occurs: @@ -150,6 +157,8 @@ impl Memory for [u8] { fn zero(&mut self, ptr: u32, len: u32) -> Result<(), DispatchError> { <[u8] as Memory>::write(self, ptr, &vec![0; len as usize]) } + + fn reset_interpreter_cache(&mut self) {} } impl Memory for polkavm::RawInstance { @@ -166,6 +175,10 @@ impl Memory for polkavm::RawInstance { fn zero(&mut self, ptr: u32, len: u32) -> Result<(), DispatchError> { self.zero_memory(ptr, len).map_err(|_| Error::::OutOfBounds.into()) } + + fn reset_interpreter_cache(&mut self) { + self.reset_interpreter_cache(); + } } impl PolkaVmInstance for polkavm::RawInstance { @@ -341,18 +354,20 @@ pub enum RuntimeCosts { /// Weight of reading and decoding the input to a precompile. PrecompileDecode(u32), /// Weight of the transfer performed during a call. - CallTransferSurcharge, + /// parameter `dust_transfer` indicates whether the transfer has a `dust` value. + CallTransferSurcharge { dust_transfer: bool }, /// Weight per byte that is cloned by supplying the `CLONE_INPUT` flag. CallInputCloned(u32), - /// Weight of calling `seal_instantiate` for the given input length. - Instantiate { input_data_len: u32 }, + /// Weight of calling `seal_instantiate`. + Instantiate { input_data_len: u32, balance_transfer: bool, dust_transfer: bool }, /// Weight of calling `Ripemd160` precompile for the given input size. Ripemd160(u32), /// Weight of calling `Sha256` precompile for the given input size. HashSha256(u32), /// Weight of calling `seal_hash_keccak_256` for the given input size. HashKeccak256(u32), - /// Weight of calling `seal_hash_blake2_256` for the given input size. + /// Weight of calling the `System::hash_blake2_256` precompile function for the given input + /// size. HashBlake256(u32), /// Weight of calling `seal_hash_blake2_128` for the given input size. HashBlake128(u32), @@ -490,18 +505,24 @@ impl Token for RuntimeCosts { TakeTransientStorage(len) => { cost_storage!(write_transient, seal_take_transient_storage, len) }, - CallBase => T::WeightInfo::seal_call(0, 0), + CallBase => T::WeightInfo::seal_call(0, 0, 0), DelegateCallBase => T::WeightInfo::seal_delegate_call(), PrecompileBase => T::WeightInfo::seal_call_precompile(0, 0), PrecompileWithInfoBase => T::WeightInfo::seal_call_precompile(1, 0), PrecompileDecode(len) => cost_args!(seal_call_precompile, 0, len), - CallTransferSurcharge => cost_args!(seal_call, 1, 0), - CallInputCloned(len) => cost_args!(seal_call, 0, len), - Instantiate { input_data_len } => T::WeightInfo::seal_instantiate(input_data_len), + CallTransferSurcharge { dust_transfer } => + cost_args!(seal_call, 1, dust_transfer.into(), 0), + CallInputCloned(len) => cost_args!(seal_call, 0, 0, len), + Instantiate { input_data_len, balance_transfer, dust_transfer } => + T::WeightInfo::seal_instantiate( + input_data_len, + balance_transfer.into(), + dust_transfer.into(), + ), HashSha256(len) => T::WeightInfo::sha2_256(len), Ripemd160(len) => T::WeightInfo::ripemd_160(len), HashKeccak256(len) => T::WeightInfo::seal_hash_keccak_256(len), - HashBlake256(len) => T::WeightInfo::seal_hash_blake2_256(len), + HashBlake256(len) => T::WeightInfo::hash_blake2_256(len), HashBlake128(len) => T::WeightInfo::seal_hash_blake2_128(len), EcdsaRecovery => T::WeightInfo::ecdsa_recover(), Sr25519Verify(len) => T::WeightInfo::seal_sr25519_verify(len), @@ -1065,6 +1086,11 @@ impl<'a, E: Ext, M: ?Sized + Memory> Runtime<'a, E, M> { let deposit_limit = memory.read_u256(deposit_ptr)?; + // we do check this in exec.rs but we want to error out early + if input_data_len > limits::CALLDATA_BYTES { + Err(>::CallDataTooLarge)?; + } + let input_data = if flags.contains(CallFlags::CLONE_INPUT) { let input = self.input_data.as_ref().ok_or(Error::::InputForwarded)?; charge_gas!(self, RuntimeCosts::CallInputCloned(input.len() as u32))?; @@ -1080,6 +1106,8 @@ impl<'a, E: Ext, M: ?Sized + Memory> Runtime<'a, E, M> { memory.read(input_data_ptr, input_data_len)? }; + memory.reset_interpreter_cache(); + let call_outcome = match call_type { CallType::Call { value_ptr } => { let read_only = flags.contains(CallFlags::READ_ONLY); @@ -1090,7 +1118,10 @@ impl<'a, E: Ext, M: ?Sized + Memory> Runtime<'a, E, M> { if read_only || self.ext.is_read_only() { return Err(Error::::StateChangeDenied.into()); } - self.charge_gas(RuntimeCosts::CallTransferSurcharge)?; + + self.charge_gas(RuntimeCosts::CallTransferSurcharge { + dust_transfer: Pallet::::has_dust(value), + })?; } self.ext.call( weight, @@ -1156,10 +1187,29 @@ impl<'a, E: Ext, M: ?Sized + Memory> Runtime<'a, E, M> { output_len_ptr: u32, salt_ptr: u32, ) -> Result { - self.charge_gas(RuntimeCosts::Instantiate { input_data_len })?; + let value = match memory.read_u256(value_ptr) { + Ok(value) => { + self.charge_gas(RuntimeCosts::Instantiate { + input_data_len, + balance_transfer: Pallet::::has_balance(value), + dust_transfer: Pallet::::has_dust(value), + })?; + value + }, + Err(err) => { + self.charge_gas(RuntimeCosts::Instantiate { + input_data_len: 0, + balance_transfer: false, + dust_transfer: false, + })?; + return Err(err.into()); + }, + }; let deposit_limit: U256 = memory.read_u256(deposit_ptr)?; - let value = memory.read_u256(value_ptr)?; let code_hash = memory.read_h256(code_hash_ptr)?; + if input_data_len > limits::CALLDATA_BYTES { + Err(>::CallDataTooLarge)?; + } let input_data = memory.read(input_data_ptr, input_data_len)?; let salt = if salt_ptr == SENTINEL { None @@ -1168,6 +1218,8 @@ impl<'a, E: Ext, M: ?Sized + Memory> Runtime<'a, E, M> { Some(salt) }; + memory.reset_interpreter_cache(); + match self.ext.instantiate( weight, deposit_limit, @@ -1497,6 +1549,9 @@ pub mod env { data_len: u32, ) -> Result<(), TrapReason> { self.charge_gas(RuntimeCosts::CopyFromContract(data_len))?; + if data_len > limits::CALLDATA_BYTES { + Err(>::ReturnDataTooLarge)?; + } Err(TrapReason::Return(ReturnData { flags, data: memory.read(data_ptr, data_len)? })) } @@ -1957,21 +2012,6 @@ pub mod env { )?) } - /// Computes the BLAKE2 256-bit hash on the given input buffer. - /// See [`pallet_revive_uapi::HostFn::hash_blake2_256`]. - fn hash_blake2_256( - &mut self, - memory: &mut M, - input_ptr: u32, - input_len: u32, - output_ptr: u32, - ) -> Result<(), TrapReason> { - self.charge_gas(RuntimeCosts::HashBlake256(input_len))?; - Ok(self.compute_hash_on_intermediate_buffer( - memory, blake2_256, input_ptr, input_len, output_ptr, - )?) - } - /// Stores the minimum balance (a.k.a. existential deposit) into the supplied buffer. /// See [`pallet_revive_uapi::HostFn::minimum_balance`]. fn minimum_balance(&mut self, memory: &mut M, out_ptr: u32) -> Result<(), TrapReason> { diff --git a/substrate/frame/revive/src/weights.rs b/substrate/frame/revive/src/weights.rs index 1c0a94336d14a..9119103314557 100644 --- a/substrate/frame/revive/src/weights.rs +++ b/substrate/frame/revive/src/weights.rs @@ -35,9 +35,9 @@ //! Autogenerated weights for `pallet_revive` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 -//! DATE: 2025-04-16, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2025-08-11, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `cd6bf3e6c4c6`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! HOSTNAME: `c19fa2715a10`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` //! WASM-EXECUTION: `Compiled`, CHAIN: `None`, DB CACHE: `1024` // Executed Command: @@ -76,8 +76,10 @@ pub trait WeightInfo { fn call_with_code_per_byte(c: u32, ) -> Weight; fn basic_block_compilation(b: u32, ) -> Weight; fn instantiate_with_code(c: u32, i: u32, ) -> Weight; + fn eth_instantiate_with_code(c: u32, i: u32, d: u32, ) -> Weight; fn instantiate(i: u32, ) -> Weight; fn call() -> Weight; + fn eth_call(d: u32, ) -> Weight; fn upload_code(c: u32, ) -> Weight; fn remove_code() -> Weight; fn set_code() -> Weight; @@ -137,15 +139,15 @@ pub trait WeightInfo { fn seal_get_transient_storage(n: u32, ) -> Weight; fn seal_contains_transient_storage(n: u32, ) -> Weight; fn seal_take_transient_storage(n: u32, ) -> Weight; - fn seal_call(t: u32, i: u32, ) -> Weight; + fn seal_call(t: u32, d: u32, i: u32, ) -> Weight; fn seal_call_precompile(d: u32, i: u32, ) -> Weight; fn seal_delegate_call() -> Weight; - fn seal_instantiate(i: u32, ) -> Weight; + fn seal_instantiate(t: u32, d: u32, i: u32, ) -> Weight; fn sha2_256(n: u32, ) -> Weight; fn identity(n: u32, ) -> Weight; fn ripemd_160(n: u32, ) -> Weight; fn seal_hash_keccak_256(n: u32, ) -> Weight; - fn seal_hash_blake2_256(n: u32, ) -> Weight; + fn hash_blake2_256(n: u32, ) -> Weight; fn seal_hash_blake2_128(n: u32, ) -> Weight; fn seal_sr25519_verify(n: u32, ) -> Weight; fn ecdsa_recover() -> Weight; @@ -157,6 +159,7 @@ pub trait WeightInfo { fn seal_set_code_hash() -> Weight; fn instr(r: u32, ) -> Weight; fn instr_empty_loop(r: u32, ) -> Weight; + fn v1_migration_step() -> Weight; } /// Weights for `pallet_revive` using the Substrate node and recommended hardware. @@ -168,8 +171,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `147` // Estimated: `1632` - // Minimum execution time: 2_971_000 picoseconds. - Weight::from_parts(3_218_000, 1632) + // Minimum execution time: 3_008_000 picoseconds. + Weight::from_parts(3_256_000, 1632) .saturating_add(T::DbWeight::get().reads(1_u64)) } /// Storage: `Skipped::Metadata` (r:0 w:0) @@ -177,12 +180,12 @@ impl WeightInfo for SubstrateWeight { /// The range of component `k` is `[0, 1024]`. fn on_initialize_per_trie_key(k: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `425 + k * (69 ±0)` - // Estimated: `415 + k * (70 ±0)` - // Minimum execution time: 14_042_000 picoseconds. - Weight::from_parts(14_510_000, 415) - // Standard Error: 1_047 - .saturating_add(Weight::from_parts(1_167_098, 0).saturating_mul(k.into())) + // Measured: `458 + k * (69 ±0)` + // Estimated: `448 + k * (70 ±0)` + // Minimum execution time: 14_584_000 picoseconds. + Weight::from_parts(772_449, 448) + // Standard Error: 1_278 + .saturating_add(Weight::from_parts(1_204_643, 0).saturating_mul(k.into())) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(k.into()))) .saturating_add(T::DbWeight::get().writes(2_u64)) @@ -191,198 +194,258 @@ impl WeightInfo for SubstrateWeight { } /// Storage: `Revive::OriginalAccount` (r:2 w:0) /// Proof: `Revive::OriginalAccount` (`max_values`: None, `max_size`: Some(52), added: 2527, mode: `Measured`) - /// Storage: `Revive::ContractInfoOf` (r:1 w:1) - /// Proof: `Revive::ContractInfoOf` (`max_values`: None, `max_size`: Some(242), added: 2717, mode: `Measured`) + /// Storage: `Revive::AccountInfoOf` (r:1 w:1) + /// Proof: `Revive::AccountInfoOf` (`max_values`: None, `max_size`: Some(247), added: 2722, mode: `Measured`) /// Storage: `Revive::CodeInfoOf` (r:1 w:0) /// Proof: `Revive::CodeInfoOf` (`max_values`: None, `max_size`: Some(96), added: 2571, mode: `Measured`) /// Storage: `Revive::PristineCode` (r:1 w:0) - /// Proof: `Revive::PristineCode` (`max_values`: None, `max_size`: Some(262180), added: 264655, mode: `Measured`) + /// Proof: `Revive::PristineCode` (`max_values`: None, `max_size`: Some(1048612), added: 1051087, mode: `Measured`) /// Storage: `Timestamp::Now` (r:1 w:0) /// Proof: `Timestamp::Now` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `Measured`) /// Storage: `System::Account` (r:1 w:1) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) - /// The range of component `c` is `[0, 104857]`. + /// The range of component `c` is `[0, 102400]`. fn call_with_code_per_byte(c: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `1178 + c * (1 ±0)` - // Estimated: `7119 + c * (1 ±0)` - // Minimum execution time: 81_842_000 picoseconds. - Weight::from_parts(110_091_076, 7119) - // Standard Error: 12 - .saturating_add(Weight::from_parts(2_123, 0).saturating_mul(c.into())) + // Measured: `1171 + c * (1 ±0)` + // Estimated: `7106 + c * (1 ±0)` + // Minimum execution time: 86_230_000 picoseconds. + Weight::from_parts(124_424_225, 7106) + // Standard Error: 10 + .saturating_add(Weight::from_parts(1_256, 0).saturating_mul(c.into())) .saturating_add(T::DbWeight::get().reads(7_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) .saturating_add(Weight::from_parts(0, 1).saturating_mul(c.into())) } /// Storage: `Revive::OriginalAccount` (r:2 w:0) /// Proof: `Revive::OriginalAccount` (`max_values`: None, `max_size`: Some(52), added: 2527, mode: `Measured`) - /// Storage: `Revive::ContractInfoOf` (r:1 w:1) - /// Proof: `Revive::ContractInfoOf` (`max_values`: None, `max_size`: Some(242), added: 2717, mode: `Measured`) + /// Storage: `Revive::AccountInfoOf` (r:1 w:1) + /// Proof: `Revive::AccountInfoOf` (`max_values`: None, `max_size`: Some(247), added: 2722, mode: `Measured`) /// Storage: `Revive::CodeInfoOf` (r:1 w:0) /// Proof: `Revive::CodeInfoOf` (`max_values`: None, `max_size`: Some(96), added: 2571, mode: `Measured`) /// Storage: `Revive::PristineCode` (r:1 w:0) - /// Proof: `Revive::PristineCode` (`max_values`: None, `max_size`: Some(262180), added: 264655, mode: `Measured`) + /// Proof: `Revive::PristineCode` (`max_values`: None, `max_size`: Some(1048612), added: 1051087, mode: `Measured`) /// Storage: `Timestamp::Now` (r:1 w:0) /// Proof: `Timestamp::Now` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `Measured`) /// Storage: `System::Account` (r:1 w:1) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) /// The range of component `b` is `[0, 1]`. - fn basic_block_compilation(b: u32, ) -> Weight { - // Proof Size summary in bytes: - // Measured: `4513` - // Estimated: `10453` - // Minimum execution time: 121_768_000 picoseconds. - Weight::from_parts(126_040_712, 10453) - // Standard Error: 315_571 - .saturating_add(Weight::from_parts(961_687, 0).saturating_mul(b.into())) + fn basic_block_compilation(_b: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `4515` + // Estimated: `10455` + // Minimum execution time: 124_359_000 picoseconds. + Weight::from_parts(129_025_585, 10455) .saturating_add(T::DbWeight::get().reads(7_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } /// Storage: `Revive::CodeInfoOf` (r:1 w:1) /// Proof: `Revive::CodeInfoOf` (`max_values`: None, `max_size`: Some(96), added: 2571, mode: `Measured`) /// Storage: `Balances::Holds` (r:2 w:2) - /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(409), added: 2884, mode: `Measured`) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(427), added: 2902, mode: `Measured`) /// Storage: `Revive::OriginalAccount` (r:1 w:0) /// Proof: `Revive::OriginalAccount` (`max_values`: None, `max_size`: Some(52), added: 2527, mode: `Measured`) - /// Storage: `Revive::ContractInfoOf` (r:1 w:1) - /// Proof: `Revive::ContractInfoOf` (`max_values`: None, `max_size`: Some(242), added: 2717, mode: `Measured`) + /// Storage: `Revive::AccountInfoOf` (r:1 w:1) + /// Proof: `Revive::AccountInfoOf` (`max_values`: None, `max_size`: Some(247), added: 2722, mode: `Measured`) /// Storage: `Timestamp::Now` (r:1 w:0) /// Proof: `Timestamp::Now` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `Measured`) /// Storage: `System::Account` (r:1 w:1) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) /// Storage: `Revive::PristineCode` (r:0 w:1) - /// Proof: `Revive::PristineCode` (`max_values`: None, `max_size`: Some(262180), added: 264655, mode: `Measured`) - /// The range of component `c` is `[0, 104857]`. - /// The range of component `i` is `[0, 262144]`. + /// Proof: `Revive::PristineCode` (`max_values`: None, `max_size`: Some(1048612), added: 1051087, mode: `Measured`) + /// The range of component `c` is `[0, 102400]`. + /// The range of component `i` is `[0, 131072]`. fn instantiate_with_code(c: u32, i: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `1108` + // Estimated: `7041` + // Minimum execution time: 755_622_000 picoseconds. + Weight::from_parts(57_161_132, 7041) + // Standard Error: 36 + .saturating_add(Weight::from_parts(19_425, 0).saturating_mul(c.into())) + // Standard Error: 28 + .saturating_add(Weight::from_parts(5_000, 0).saturating_mul(i.into())) + .saturating_add(T::DbWeight::get().reads(7_u64)) + .saturating_add(T::DbWeight::get().writes(6_u64)) + } + /// Storage: `Revive::CodeInfoOf` (r:1 w:1) + /// Proof: `Revive::CodeInfoOf` (`max_values`: None, `max_size`: Some(96), added: 2571, mode: `Measured`) + /// Storage: `Balances::Holds` (r:2 w:2) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(427), added: 2902, mode: `Measured`) + /// Storage: `Revive::OriginalAccount` (r:1 w:0) + /// Proof: `Revive::OriginalAccount` (`max_values`: None, `max_size`: Some(52), added: 2527, mode: `Measured`) + /// Storage: `Revive::AccountInfoOf` (r:2 w:2) + /// Proof: `Revive::AccountInfoOf` (`max_values`: None, `max_size`: Some(247), added: 2722, mode: `Measured`) + /// Storage: `Timestamp::Now` (r:1 w:0) + /// Proof: `Timestamp::Now` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `Measured`) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) + /// Storage: `Revive::PristineCode` (r:0 w:1) + /// Proof: `Revive::PristineCode` (`max_values`: None, `max_size`: Some(1048612), added: 1051087, mode: `Measured`) + /// The range of component `c` is `[0, 102400]`. + /// The range of component `i` is `[0, 131072]`. + /// The range of component `d` is `[0, 1]`. + fn eth_instantiate_with_code(c: u32, i: u32, d: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `1122` - // Estimated: `7010` - // Minimum execution time: 1_593_697_000 picoseconds. - Weight::from_parts(150_335_332, 7010) - // Standard Error: 34 - .saturating_add(Weight::from_parts(19_710, 0).saturating_mul(c.into())) - // Standard Error: 13 - .saturating_add(Weight::from_parts(5_466, 0).saturating_mul(i.into())) + // Estimated: `7062 + d * (2475 ±0)` + // Minimum execution time: 281_326_000 picoseconds. + Weight::from_parts(192_766_004, 7062) + // Standard Error: 15 + .saturating_add(Weight::from_parts(14_166, 0).saturating_mul(c.into())) + // Standard Error: 11 + .saturating_add(Weight::from_parts(403, 0).saturating_mul(i.into())) + // Standard Error: 983_169 + .saturating_add(Weight::from_parts(30_340_467, 0).saturating_mul(d.into())) .saturating_add(T::DbWeight::get().reads(7_u64)) + .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(d.into()))) .saturating_add(T::DbWeight::get().writes(6_u64)) + .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(d.into()))) + .saturating_add(Weight::from_parts(0, 2475).saturating_mul(d.into())) } /// Storage: `Revive::CodeInfoOf` (r:1 w:1) /// Proof: `Revive::CodeInfoOf` (`max_values`: None, `max_size`: Some(96), added: 2571, mode: `Measured`) /// Storage: `Revive::PristineCode` (r:1 w:0) - /// Proof: `Revive::PristineCode` (`max_values`: None, `max_size`: Some(262180), added: 264655, mode: `Measured`) + /// Proof: `Revive::PristineCode` (`max_values`: None, `max_size`: Some(1048612), added: 1051087, mode: `Measured`) /// Storage: `Revive::OriginalAccount` (r:1 w:0) /// Proof: `Revive::OriginalAccount` (`max_values`: None, `max_size`: Some(52), added: 2527, mode: `Measured`) - /// Storage: `Revive::ContractInfoOf` (r:1 w:1) - /// Proof: `Revive::ContractInfoOf` (`max_values`: None, `max_size`: Some(242), added: 2717, mode: `Measured`) + /// Storage: `Revive::AccountInfoOf` (r:1 w:1) + /// Proof: `Revive::AccountInfoOf` (`max_values`: None, `max_size`: Some(247), added: 2722, mode: `Measured`) /// Storage: `Timestamp::Now` (r:1 w:0) /// Proof: `Timestamp::Now` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `Measured`) /// Storage: `System::Account` (r:1 w:1) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) /// Storage: `Balances::Holds` (r:1 w:1) - /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(409), added: 2884, mode: `Measured`) - /// The range of component `i` is `[0, 262144]`. + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(427), added: 2902, mode: `Measured`) + /// The range of component `i` is `[0, 131072]`. fn instantiate(i: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `1886` - // Estimated: `5346` - // Minimum execution time: 155_867_000 picoseconds. - Weight::from_parts(88_055_300, 5346) - // Standard Error: 25 - .saturating_add(Weight::from_parts(5_561, 0).saturating_mul(i.into())) + // Measured: `1912` + // Estimated: `5362` + // Minimum execution time: 172_513_000 picoseconds. + Weight::from_parts(178_290_134, 5362) + // Standard Error: 11 + .saturating_add(Weight::from_parts(4_158, 0).saturating_mul(i.into())) .saturating_add(T::DbWeight::get().reads(7_u64)) .saturating_add(T::DbWeight::get().writes(4_u64)) } /// Storage: `Revive::OriginalAccount` (r:2 w:0) /// Proof: `Revive::OriginalAccount` (`max_values`: None, `max_size`: Some(52), added: 2527, mode: `Measured`) - /// Storage: `Revive::ContractInfoOf` (r:1 w:1) - /// Proof: `Revive::ContractInfoOf` (`max_values`: None, `max_size`: Some(242), added: 2717, mode: `Measured`) + /// Storage: `Revive::AccountInfoOf` (r:1 w:1) + /// Proof: `Revive::AccountInfoOf` (`max_values`: None, `max_size`: Some(247), added: 2722, mode: `Measured`) /// Storage: `Revive::CodeInfoOf` (r:1 w:0) /// Proof: `Revive::CodeInfoOf` (`max_values`: None, `max_size`: Some(96), added: 2571, mode: `Measured`) /// Storage: `Revive::PristineCode` (r:1 w:0) - /// Proof: `Revive::PristineCode` (`max_values`: None, `max_size`: Some(262180), added: 264655, mode: `Measured`) + /// Proof: `Revive::PristineCode` (`max_values`: None, `max_size`: Some(1048612), added: 1051087, mode: `Measured`) /// Storage: `Timestamp::Now` (r:1 w:0) /// Proof: `Timestamp::Now` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `Measured`) /// Storage: `System::Account` (r:1 w:1) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) fn call() -> Weight { // Proof Size summary in bytes: - // Measured: `1812` - // Estimated: `7752` - // Minimum execution time: 85_908_000 picoseconds. - Weight::from_parts(87_953_000, 7752) + // Measured: `1792` + // Estimated: `7732` + // Minimum execution time: 87_638_000 picoseconds. + Weight::from_parts(90_000_000, 7732) + .saturating_add(T::DbWeight::get().reads(7_u64)) + .saturating_add(T::DbWeight::get().writes(2_u64)) + } + /// Storage: `Revive::OriginalAccount` (r:2 w:0) + /// Proof: `Revive::OriginalAccount` (`max_values`: None, `max_size`: Some(52), added: 2527, mode: `Measured`) + /// Storage: `Revive::AccountInfoOf` (r:2 w:2) + /// Proof: `Revive::AccountInfoOf` (`max_values`: None, `max_size`: Some(247), added: 2722, mode: `Measured`) + /// Storage: `Revive::CodeInfoOf` (r:1 w:0) + /// Proof: `Revive::CodeInfoOf` (`max_values`: None, `max_size`: Some(96), added: 2571, mode: `Measured`) + /// Storage: `Revive::PristineCode` (r:1 w:0) + /// Proof: `Revive::PristineCode` (`max_values`: None, `max_size`: Some(1048612), added: 1051087, mode: `Measured`) + /// Storage: `Timestamp::Now` (r:1 w:0) + /// Proof: `Timestamp::Now` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `Measured`) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) + /// The range of component `d` is `[0, 1]`. + fn eth_call(d: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `1792` + // Estimated: `7732 + d * (2475 ±0)` + // Minimum execution time: 85_839_000 picoseconds. + Weight::from_parts(90_556_373, 7732) + // Standard Error: 358_297 + .saturating_add(Weight::from_parts(27_649_126, 0).saturating_mul(d.into())) .saturating_add(T::DbWeight::get().reads(7_u64)) + .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(d.into()))) .saturating_add(T::DbWeight::get().writes(2_u64)) + .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(d.into()))) + .saturating_add(Weight::from_parts(0, 2475).saturating_mul(d.into())) } /// Storage: `Revive::CodeInfoOf` (r:1 w:1) /// Proof: `Revive::CodeInfoOf` (`max_values`: None, `max_size`: Some(96), added: 2571, mode: `Measured`) /// Storage: `Balances::Holds` (r:1 w:1) - /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(409), added: 2884, mode: `Measured`) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(427), added: 2902, mode: `Measured`) /// Storage: `Revive::PristineCode` (r:0 w:1) - /// Proof: `Revive::PristineCode` (`max_values`: None, `max_size`: Some(262180), added: 264655, mode: `Measured`) - /// The range of component `c` is `[0, 104857]`. + /// Proof: `Revive::PristineCode` (`max_values`: None, `max_size`: Some(1048612), added: 1051087, mode: `Measured`) + /// The range of component `c` is `[0, 102400]`. fn upload_code(c: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `505` // Estimated: `3970` - // Minimum execution time: 51_305_000 picoseconds. - Weight::from_parts(27_197_599, 3970) - // Standard Error: 20 - .saturating_add(Weight::from_parts(14_721, 0).saturating_mul(c.into())) + // Minimum execution time: 56_805_000 picoseconds. + Weight::from_parts(50_855_179, 3970) + // Standard Error: 35 + .saturating_add(Weight::from_parts(13_927, 0).saturating_mul(c.into())) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) } /// Storage: `Revive::CodeInfoOf` (r:1 w:1) /// Proof: `Revive::CodeInfoOf` (`max_values`: None, `max_size`: Some(96), added: 2571, mode: `Measured`) /// Storage: `Balances::Holds` (r:1 w:1) - /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(409), added: 2884, mode: `Measured`) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(427), added: 2902, mode: `Measured`) /// Storage: `Revive::PristineCode` (r:0 w:1) - /// Proof: `Revive::PristineCode` (`max_values`: None, `max_size`: Some(262180), added: 264655, mode: `Measured`) + /// Proof: `Revive::PristineCode` (`max_values`: None, `max_size`: Some(1048612), added: 1051087, mode: `Measured`) fn remove_code() -> Weight { // Proof Size summary in bytes: // Measured: `658` // Estimated: `4123` - // Minimum execution time: 41_900_000 picoseconds. - Weight::from_parts(42_985_000, 4123) + // Minimum execution time: 47_344_000 picoseconds. + Weight::from_parts(48_892_000, 4123) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) } - /// Storage: `Revive::ContractInfoOf` (r:1 w:1) - /// Proof: `Revive::ContractInfoOf` (`max_values`: None, `max_size`: Some(242), added: 2717, mode: `Measured`) + /// Storage: `Revive::AccountInfoOf` (r:1 w:1) + /// Proof: `Revive::AccountInfoOf` (`max_values`: None, `max_size`: Some(247), added: 2722, mode: `Measured`) /// Storage: `Revive::CodeInfoOf` (r:2 w:2) /// Proof: `Revive::CodeInfoOf` (`max_values`: None, `max_size`: Some(96), added: 2571, mode: `Measured`) fn set_code() -> Weight { // Proof Size summary in bytes: - // Measured: `528` - // Estimated: `6468` - // Minimum execution time: 20_254_000 picoseconds. - Weight::from_parts(21_122_000, 6468) + // Measured: `530` + // Estimated: `6470` + // Minimum execution time: 20_627_000 picoseconds. + Weight::from_parts(21_451_000, 6470) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) } /// Storage: `Revive::OriginalAccount` (r:1 w:1) /// Proof: `Revive::OriginalAccount` (`max_values`: None, `max_size`: Some(52), added: 2527, mode: `Measured`) /// Storage: `Balances::Holds` (r:1 w:1) - /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(409), added: 2884, mode: `Measured`) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(427), added: 2902, mode: `Measured`) fn map_account() -> Weight { // Proof Size summary in bytes: // Measured: `813` // Estimated: `4278` - // Minimum execution time: 50_406_000 picoseconds. - Weight::from_parts(51_939_000, 4278) + // Minimum execution time: 57_209_000 picoseconds. + Weight::from_parts(58_942_000, 4278) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } /// Storage: `Balances::Holds` (r:1 w:1) - /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(409), added: 2884, mode: `Measured`) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(427), added: 2902, mode: `Measured`) /// Storage: `Revive::OriginalAccount` (r:0 w:1) /// Proof: `Revive::OriginalAccount` (`max_values`: None, `max_size`: Some(52), added: 2527, mode: `Measured`) fn unmap_account() -> Weight { // Proof Size summary in bytes: // Measured: `395` // Estimated: `3860` - // Minimum execution time: 37_679_000 picoseconds. - Weight::from_parts(39_183_000, 3860) + // Minimum execution time: 42_757_000 picoseconds. + Weight::from_parts(44_178_000, 3860) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } @@ -394,8 +457,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `145` // Estimated: `3610` - // Minimum execution time: 12_684_000 picoseconds. - Weight::from_parts(13_240_000, 3610) + // Minimum execution time: 13_062_000 picoseconds. + Weight::from_parts(13_660_000, 3610) .saturating_add(T::DbWeight::get().reads(2_u64)) } /// The range of component `r` is `[0, 1600]`. @@ -403,129 +466,131 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 6_583_000 picoseconds. - Weight::from_parts(8_416_964, 0) - // Standard Error: 170 - .saturating_add(Weight::from_parts(164_523, 0).saturating_mul(r.into())) + // Minimum execution time: 7_588_000 picoseconds. + Weight::from_parts(8_755_261, 0) + // Standard Error: 236 + .saturating_add(Weight::from_parts(182_421, 0).saturating_mul(r.into())) } fn seal_caller() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 199_000 picoseconds. - Weight::from_parts(233_000, 0) + // Minimum execution time: 335_000 picoseconds. + Weight::from_parts(390_000, 0) } fn seal_origin() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 184_000 picoseconds. - Weight::from_parts(206_000, 0) + // Minimum execution time: 350_000 picoseconds. + Weight::from_parts(386_000, 0) } /// Storage: `Revive::OriginalAccount` (r:1 w:0) /// Proof: `Revive::OriginalAccount` (`max_values`: None, `max_size`: Some(52), added: 2527, mode: `Measured`) fn seal_to_account_id() -> Weight { // Proof Size summary in bytes: - // Measured: `538` - // Estimated: `4003` - // Minimum execution time: 9_364_000 picoseconds. - Weight::from_parts(9_672_000, 4003) + // Measured: `571` + // Estimated: `4036` + // Minimum execution time: 9_818_000 picoseconds. + Weight::from_parts(10_279_000, 4036) .saturating_add(T::DbWeight::get().reads(1_u64)) } - /// Storage: `Revive::ContractInfoOf` (r:1 w:0) - /// Proof: `Revive::ContractInfoOf` (`max_values`: None, `max_size`: Some(242), added: 2717, mode: `Measured`) + /// Storage: `Revive::AccountInfoOf` (r:1 w:0) + /// Proof: `Revive::AccountInfoOf` (`max_values`: None, `max_size`: Some(247), added: 2722, mode: `Measured`) fn seal_code_hash() -> Weight { // Proof Size summary in bytes: - // Measured: `402` - // Estimated: `3867` - // Minimum execution time: 9_183_000 picoseconds. - Weight::from_parts(9_609_000, 3867) + // Measured: `403` + // Estimated: `3868` + // Minimum execution time: 9_222_000 picoseconds. + Weight::from_parts(9_806_000, 3868) .saturating_add(T::DbWeight::get().reads(1_u64)) } fn seal_own_code_hash() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 131_000 picoseconds. - Weight::from_parts(176_000, 0) + // Minimum execution time: 282_000 picoseconds. + Weight::from_parts(336_000, 0) } - /// Storage: `Revive::ContractInfoOf` (r:1 w:0) - /// Proof: `Revive::ContractInfoOf` (`max_values`: None, `max_size`: Some(242), added: 2717, mode: `Measured`) + /// Storage: `Revive::AccountInfoOf` (r:1 w:0) + /// Proof: `Revive::AccountInfoOf` (`max_values`: None, `max_size`: Some(247), added: 2722, mode: `Measured`) /// Storage: `Revive::CodeInfoOf` (r:1 w:0) /// Proof: `Revive::CodeInfoOf` (`max_values`: None, `max_size`: Some(96), added: 2571, mode: `Measured`) fn seal_code_size() -> Weight { // Proof Size summary in bytes: - // Measured: `472` - // Estimated: `3937` - // Minimum execution time: 12_217_000 picoseconds. - Weight::from_parts(13_005_000, 3937) + // Measured: `474` + // Estimated: `3939` + // Minimum execution time: 12_825_000 picoseconds. + Weight::from_parts(13_490_000, 3939) .saturating_add(T::DbWeight::get().reads(2_u64)) } fn seal_caller_is_origin() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 208_000 picoseconds. - Weight::from_parts(228_000, 0) + // Minimum execution time: 321_000 picoseconds. + Weight::from_parts(372_000, 0) } fn seal_caller_is_root() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 170_000 picoseconds. - Weight::from_parts(203_000, 0) + // Minimum execution time: 269_000 picoseconds. + Weight::from_parts(327_000, 0) } fn seal_address() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 182_000 picoseconds. - Weight::from_parts(204_000, 0) + // Minimum execution time: 304_000 picoseconds. + Weight::from_parts(343_000, 0) } fn seal_weight_left() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 576_000 picoseconds. - Weight::from_parts(637_000, 0) + // Minimum execution time: 700_000 picoseconds. + Weight::from_parts(802_000, 0) } fn seal_ref_time_left() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 131_000 picoseconds. - Weight::from_parts(168_000, 0) + // Minimum execution time: 263_000 picoseconds. + Weight::from_parts(325_000, 0) } fn seal_balance() -> Weight { // Proof Size summary in bytes: - // Measured: `103` + // Measured: `506` // Estimated: `0` - // Minimum execution time: 4_466_000 picoseconds. - Weight::from_parts(4_813_000, 0) + // Minimum execution time: 13_351_000 picoseconds. + Weight::from_parts(13_878_000, 0) } /// Storage: `Revive::OriginalAccount` (r:1 w:0) /// Proof: `Revive::OriginalAccount` (`max_values`: None, `max_size`: Some(52), added: 2527, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) + /// Storage: `Revive::AccountInfoOf` (r:1 w:0) + /// Proof: `Revive::AccountInfoOf` (`max_values`: None, `max_size`: Some(247), added: 2722, mode: `Measured`) fn seal_balance_of() -> Weight { // Proof Size summary in bytes: - // Measured: `517` - // Estimated: `3982` - // Minimum execution time: 8_786_000 picoseconds. - Weight::from_parts(9_450_000, 3982) - .saturating_add(T::DbWeight::get().reads(2_u64)) + // Measured: `791` + // Estimated: `4256` + // Minimum execution time: 18_603_000 picoseconds. + Weight::from_parts(19_511_000, 4256) + .saturating_add(T::DbWeight::get().reads(3_u64)) } /// Storage: `Revive::ImmutableDataOf` (r:1 w:0) /// Proof: `Revive::ImmutableDataOf` (`max_values`: None, `max_size`: Some(4118), added: 6593, mode: `Measured`) /// The range of component `n` is `[1, 4096]`. fn seal_get_immutable_data(n: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `238 + n * (1 ±0)` - // Estimated: `3703 + n * (1 ±0)` - // Minimum execution time: 5_796_000 picoseconds. - Weight::from_parts(6_399_722, 3703) - // Standard Error: 4 - .saturating_add(Weight::from_parts(581, 0).saturating_mul(n.into())) + // Measured: `271 + n * (1 ±0)` + // Estimated: `3736 + n * (1 ±0)` + // Minimum execution time: 6_013_000 picoseconds. + Weight::from_parts(6_757_699, 3736) + // Standard Error: 5 + .saturating_add(Weight::from_parts(483, 0).saturating_mul(n.into())) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(Weight::from_parts(0, 1).saturating_mul(n.into())) } @@ -536,67 +601,67 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 1_950_000 picoseconds. - Weight::from_parts(2_072_690, 0) - // Standard Error: 1 - .saturating_add(Weight::from_parts(633, 0).saturating_mul(n.into())) + // Minimum execution time: 2_052_000 picoseconds. + Weight::from_parts(2_330_454, 0) + // Standard Error: 2 + .saturating_add(Weight::from_parts(525, 0).saturating_mul(n.into())) .saturating_add(T::DbWeight::get().writes(1_u64)) } fn seal_value_transferred() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 151_000 picoseconds. - Weight::from_parts(170_000, 0) + // Minimum execution time: 259_000 picoseconds. + Weight::from_parts(331_000, 0) } fn seal_minimum_balance() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 127_000 picoseconds. - Weight::from_parts(151_000, 0) + // Minimum execution time: 278_000 picoseconds. + Weight::from_parts(339_000, 0) } fn seal_return_data_size() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 112_000 picoseconds. - Weight::from_parts(149_000, 0) + // Minimum execution time: 272_000 picoseconds. + Weight::from_parts(326_000, 0) } fn seal_call_data_size() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 124_000 picoseconds. - Weight::from_parts(154_000, 0) + // Minimum execution time: 268_000 picoseconds. + Weight::from_parts(313_000, 0) } fn seal_gas_limit() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 331_000 picoseconds. - Weight::from_parts(370_000, 0) + // Minimum execution time: 436_000 picoseconds. + Weight::from_parts(509_000, 0) } fn seal_gas_price() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 137_000 picoseconds. - Weight::from_parts(163_000, 0) + // Minimum execution time: 262_000 picoseconds. + Weight::from_parts(317_000, 0) } fn seal_base_fee() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 130_000 picoseconds. - Weight::from_parts(154_000, 0) + // Minimum execution time: 289_000 picoseconds. + Weight::from_parts(347_000, 0) } fn seal_block_number() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 150_000 picoseconds. - Weight::from_parts(167_000, 0) + // Minimum execution time: 305_000 picoseconds. + Weight::from_parts(358_000, 0) } /// Storage: `Session::Validators` (r:1 w:0) /// Proof: `Session::Validators` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) @@ -604,8 +669,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `141` // Estimated: `1626` - // Minimum execution time: 19_205_000 picoseconds. - Weight::from_parts(19_687_000, 1626) + // Minimum execution time: 22_975_000 picoseconds. + Weight::from_parts(23_506_000, 1626) .saturating_add(T::DbWeight::get().reads(1_u64)) } /// Storage: `System::BlockHash` (r:1 w:0) @@ -614,60 +679,60 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `30` // Estimated: `3495` - // Minimum execution time: 3_333_000 picoseconds. - Weight::from_parts(3_522_000, 3495) + // Minimum execution time: 3_631_000 picoseconds. + Weight::from_parts(3_829_000, 3495) .saturating_add(T::DbWeight::get().reads(1_u64)) } fn seal_now() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 126_000 picoseconds. - Weight::from_parts(156_000, 0) + // Minimum execution time: 271_000 picoseconds. + Weight::from_parts(337_000, 0) } fn seal_weight_to_fee() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 1_364_000 picoseconds. - Weight::from_parts(1_477_000, 0) + // Minimum execution time: 1_603_000 picoseconds. + Weight::from_parts(1_712_000, 0) } - /// The range of component `n` is `[0, 262140]`. + /// The range of component `n` is `[0, 1048572]`. fn seal_copy_to_contract(n: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 309_000 picoseconds. - Weight::from_parts(603_516, 0) + // Minimum execution time: 433_000 picoseconds. + Weight::from_parts(460_000, 0) // Standard Error: 0 - .saturating_add(Weight::from_parts(294, 0).saturating_mul(n.into())) + .saturating_add(Weight::from_parts(203, 0).saturating_mul(n.into())) } fn seal_call_data_load() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 120_000 picoseconds. - Weight::from_parts(142_000, 0) + // Minimum execution time: 293_000 picoseconds. + Weight::from_parts(325_000, 0) } - /// The range of component `n` is `[0, 262144]`. + /// The range of component `n` is `[0, 1048576]`. fn seal_call_data_copy(n: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 121_000 picoseconds. - Weight::from_parts(125_420, 0) + // Minimum execution time: 269_000 picoseconds. + Weight::from_parts(806_378, 0) // Standard Error: 0 - .saturating_add(Weight::from_parts(149, 0).saturating_mul(n.into())) + .saturating_add(Weight::from_parts(112, 0).saturating_mul(n.into())) } - /// The range of component `n` is `[0, 262140]`. + /// The range of component `n` is `[0, 131072]`. fn seal_return(n: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 150_000 picoseconds. - Weight::from_parts(445_753, 0) + // Minimum execution time: 290_000 picoseconds. + Weight::from_parts(488_982, 0) // Standard Error: 0 - .saturating_add(Weight::from_parts(296, 0).saturating_mul(n.into())) + .saturating_add(Weight::from_parts(201, 0).saturating_mul(n.into())) } /// Storage: `Revive::OriginalAccount` (r:1 w:0) /// Proof: `Revive::OriginalAccount` (`max_values`: None, `max_size`: Some(52), added: 2527, mode: `Measured`) @@ -681,10 +746,10 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Revive::ImmutableDataOf` (`max_values`: None, `max_size`: Some(4118), added: 6593, mode: `Measured`) fn seal_terminate() -> Weight { // Proof Size summary in bytes: - // Measured: `585` - // Estimated: `4050` - // Minimum execution time: 16_990_000 picoseconds. - Weight::from_parts(17_538_000, 4050) + // Measured: `582` + // Estimated: `4047` + // Minimum execution time: 17_674_000 picoseconds. + Weight::from_parts(18_031_000, 4047) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(4_u64)) } @@ -694,12 +759,12 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 4_218_000 picoseconds. - Weight::from_parts(4_143_231, 0) - // Standard Error: 3_302 - .saturating_add(Weight::from_parts(235_681, 0).saturating_mul(t.into())) - // Standard Error: 36 - .saturating_add(Weight::from_parts(1_298, 0).saturating_mul(n.into())) + // Minimum execution time: 4_375_000 picoseconds. + Weight::from_parts(4_568_155, 0) + // Standard Error: 3_591 + .saturating_add(Weight::from_parts(223_460, 0).saturating_mul(t.into())) + // Standard Error: 39 + .saturating_add(Weight::from_parts(854, 0).saturating_mul(n.into())) } /// Storage: `Skipped::Metadata` (r:0 w:0) /// Proof: `Skipped::Metadata` (`max_values`: None, `max_size`: None, mode: `Measured`) @@ -707,8 +772,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `648` // Estimated: `648` - // Minimum execution time: 6_942_000 picoseconds. - Weight::from_parts(7_454_000, 648) + // Minimum execution time: 7_272_000 picoseconds. + Weight::from_parts(7_635_000, 648) .saturating_add(T::DbWeight::get().reads(1_u64)) } /// Storage: `Skipped::Metadata` (r:0 w:0) @@ -717,8 +782,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `10658` // Estimated: `10658` - // Minimum execution time: 41_245_000 picoseconds. - Weight::from_parts(42_033_000, 10658) + // Minimum execution time: 41_207_000 picoseconds. + Weight::from_parts(41_863_000, 10658) .saturating_add(T::DbWeight::get().reads(1_u64)) } /// Storage: `Skipped::Metadata` (r:0 w:0) @@ -727,8 +792,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `648` // Estimated: `648` - // Minimum execution time: 7_877_000 picoseconds. - Weight::from_parts(8_376_000, 648) + // Minimum execution time: 8_492_000 picoseconds. + Weight::from_parts(9_013_000, 648) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -738,8 +803,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `10658` // Estimated: `10658` - // Minimum execution time: 42_844_000 picoseconds. - Weight::from_parts(43_778_000, 10658) + // Minimum execution time: 42_398_000 picoseconds. + Weight::from_parts(44_113_000, 10658) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -751,12 +816,12 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `248 + o * (1 ±0)` // Estimated: `247 + o * (1 ±0)` - // Minimum execution time: 8_517_000 picoseconds. - Weight::from_parts(9_327_675, 247) - // Standard Error: 52 - .saturating_add(Weight::from_parts(407, 0).saturating_mul(n.into())) - // Standard Error: 52 - .saturating_add(Weight::from_parts(434, 0).saturating_mul(o.into())) + // Minimum execution time: 8_728_000 picoseconds. + Weight::from_parts(9_632_969, 247) + // Standard Error: 56 + .saturating_add(Weight::from_parts(556, 0).saturating_mul(n.into())) + // Standard Error: 56 + .saturating_add(Weight::from_parts(958, 0).saturating_mul(o.into())) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) .saturating_add(Weight::from_parts(0, 1).saturating_mul(o.into())) @@ -768,10 +833,10 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `248 + n * (1 ±0)` // Estimated: `247 + n * (1 ±0)` - // Minimum execution time: 8_144_000 picoseconds. - Weight::from_parts(9_105_918, 247) - // Standard Error: 72 - .saturating_add(Weight::from_parts(684, 0).saturating_mul(n.into())) + // Minimum execution time: 9_032_000 picoseconds. + Weight::from_parts(9_816_471, 247) + // Standard Error: 82 + .saturating_add(Weight::from_parts(582, 0).saturating_mul(n.into())) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) .saturating_add(Weight::from_parts(0, 1).saturating_mul(n.into())) @@ -783,10 +848,10 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `248 + n * (1 ±0)` // Estimated: `247 + n * (1 ±0)` - // Minimum execution time: 7_914_000 picoseconds. - Weight::from_parts(8_683_792, 247) - // Standard Error: 65 - .saturating_add(Weight::from_parts(1_267, 0).saturating_mul(n.into())) + // Minimum execution time: 8_313_000 picoseconds. + Weight::from_parts(9_381_907, 247) + // Standard Error: 91 + .saturating_add(Weight::from_parts(1_184, 0).saturating_mul(n.into())) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(Weight::from_parts(0, 1).saturating_mul(n.into())) } @@ -797,10 +862,10 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `248 + n * (1 ±0)` // Estimated: `247 + n * (1 ±0)` - // Minimum execution time: 7_287_000 picoseconds. - Weight::from_parts(8_027_630, 247) - // Standard Error: 56 - .saturating_add(Weight::from_parts(698, 0).saturating_mul(n.into())) + // Minimum execution time: 7_645_000 picoseconds. + Weight::from_parts(8_714_974, 247) + // Standard Error: 87 + .saturating_add(Weight::from_parts(717, 0).saturating_mul(n.into())) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(Weight::from_parts(0, 1).saturating_mul(n.into())) } @@ -811,10 +876,10 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `248 + n * (1 ±0)` // Estimated: `247 + n * (1 ±0)` - // Minimum execution time: 8_870_000 picoseconds. - Weight::from_parts(9_939_099, 247) - // Standard Error: 225 - .saturating_add(Weight::from_parts(832, 0).saturating_mul(n.into())) + // Minimum execution time: 9_388_000 picoseconds. + Weight::from_parts(10_430_193, 247) + // Standard Error: 77 + .saturating_add(Weight::from_parts(1_346, 0).saturating_mul(n.into())) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) .saturating_add(Weight::from_parts(0, 1).saturating_mul(n.into())) @@ -823,36 +888,36 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 1_306_000 picoseconds. - Weight::from_parts(1_404_000, 0) + // Minimum execution time: 1_597_000 picoseconds. + Weight::from_parts(1_691_000, 0) } fn set_transient_storage_full() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 1_689_000 picoseconds. - Weight::from_parts(1_811_000, 0) + // Minimum execution time: 2_005_000 picoseconds. + Weight::from_parts(2_129_000, 0) } fn get_transient_storage_empty() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 1_302_000 picoseconds. - Weight::from_parts(1_387_000, 0) + // Minimum execution time: 1_602_000 picoseconds. + Weight::from_parts(1_721_000, 0) } fn get_transient_storage_full() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 1_450_000 picoseconds. - Weight::from_parts(1_531_000, 0) + // Minimum execution time: 1_796_000 picoseconds. + Weight::from_parts(1_951_000, 0) } fn rollback_transient_storage() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 1_003_000 picoseconds. - Weight::from_parts(1_083_000, 0) + // Minimum execution time: 1_279_000 picoseconds. + Weight::from_parts(1_353_000, 0) } /// The range of component `n` is `[0, 416]`. /// The range of component `o` is `[0, 416]`. @@ -860,258 +925,266 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 2_147_000 picoseconds. - Weight::from_parts(2_400_128, 0) - // Standard Error: 15 - .saturating_add(Weight::from_parts(305, 0).saturating_mul(n.into())) - // Standard Error: 15 - .saturating_add(Weight::from_parts(275, 0).saturating_mul(o.into())) + // Minimum execution time: 2_407_000 picoseconds. + Weight::from_parts(2_715_278, 0) + // Standard Error: 18 + .saturating_add(Weight::from_parts(147, 0).saturating_mul(n.into())) + // Standard Error: 18 + .saturating_add(Weight::from_parts(292, 0).saturating_mul(o.into())) } /// The range of component `n` is `[0, 416]`. fn seal_clear_transient_storage(n: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 1_941_000 picoseconds. - Weight::from_parts(2_245_468, 0) - // Standard Error: 18 - .saturating_add(Weight::from_parts(407, 0).saturating_mul(n.into())) + // Minimum execution time: 2_140_000 picoseconds. + Weight::from_parts(2_612_392, 0) + // Standard Error: 25 + .saturating_add(Weight::from_parts(305, 0).saturating_mul(n.into())) } /// The range of component `n` is `[0, 416]`. fn seal_get_transient_storage(n: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 1_738_000 picoseconds. - Weight::from_parts(1_944_507, 0) - // Standard Error: 16 - .saturating_add(Weight::from_parts(275, 0).saturating_mul(n.into())) + // Minimum execution time: 2_034_000 picoseconds. + Weight::from_parts(2_357_344, 0) + // Standard Error: 21 + .saturating_add(Weight::from_parts(276, 0).saturating_mul(n.into())) } /// The range of component `n` is `[0, 416]`. fn seal_contains_transient_storage(n: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 1_521_000 picoseconds. - Weight::from_parts(1_725_877, 0) - // Standard Error: 13 - .saturating_add(Weight::from_parts(184, 0).saturating_mul(n.into())) + // Minimum execution time: 1_888_000 picoseconds. + Weight::from_parts(2_137_193, 0) + // Standard Error: 16 + .saturating_add(Weight::from_parts(172, 0).saturating_mul(n.into())) } /// The range of component `n` is `[0, 416]`. fn seal_take_transient_storage(_n: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 2_366_000 picoseconds. - Weight::from_parts(2_590_846, 0) + // Minimum execution time: 2_733_000 picoseconds. + Weight::from_parts(3_004_772, 0) } /// Storage: `Revive::OriginalAccount` (r:1 w:0) /// Proof: `Revive::OriginalAccount` (`max_values`: None, `max_size`: Some(52), added: 2527, mode: `Measured`) - /// Storage: `Revive::ContractInfoOf` (r:1 w:0) - /// Proof: `Revive::ContractInfoOf` (`max_values`: None, `max_size`: Some(242), added: 2717, mode: `Measured`) + /// Storage: `Revive::AccountInfoOf` (r:1 w:1) + /// Proof: `Revive::AccountInfoOf` (`max_values`: None, `max_size`: Some(247), added: 2722, mode: `Measured`) /// Storage: `Revive::CodeInfoOf` (r:1 w:0) /// Proof: `Revive::CodeInfoOf` (`max_values`: None, `max_size`: Some(96), added: 2571, mode: `Measured`) /// Storage: `Revive::PristineCode` (r:1 w:0) - /// Proof: `Revive::PristineCode` (`max_values`: None, `max_size`: Some(262180), added: 264655, mode: `Measured`) - /// Storage: `System::Account` (r:1 w:0) + /// Proof: `Revive::PristineCode` (`max_values`: None, `max_size`: Some(1048612), added: 1051087, mode: `Measured`) + /// Storage: `System::Account` (r:1 w:1) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) /// The range of component `t` is `[0, 1]`. - /// The range of component `i` is `[0, 262144]`. - fn seal_call(t: u32, i: u32, ) -> Weight { - // Proof Size summary in bytes: - // Measured: `1545 + t * (206 ±0)` - // Estimated: `5010 + t * (2608 ±0)` - // Minimum execution time: 34_508_000 picoseconds. - Weight::from_parts(35_724_702, 5010) - // Standard Error: 42_504 - .saturating_add(Weight::from_parts(5_295_834, 0).saturating_mul(t.into())) + /// The range of component `d` is `[0, 1]`. + /// The range of component `i` is `[0, 1048576]`. + fn seal_call(t: u32, d: u32, i: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `2005` + // Estimated: `5470` + // Minimum execution time: 91_390_000 picoseconds. + Weight::from_parts(71_229_693, 5470) + // Standard Error: 146_616 + .saturating_add(Weight::from_parts(19_125_819, 0).saturating_mul(t.into())) + // Standard Error: 146_616 + .saturating_add(Weight::from_parts(26_490_547, 0).saturating_mul(d.into())) // Standard Error: 0 - .saturating_add(Weight::from_parts(2, 0).saturating_mul(i.into())) - .saturating_add(T::DbWeight::get().reads(4_u64)) - .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(t.into()))) + .saturating_add(Weight::from_parts(4, 0).saturating_mul(i.into())) + .saturating_add(T::DbWeight::get().reads(5_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) - .saturating_add(Weight::from_parts(0, 2608).saturating_mul(t.into())) + .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(t.into()))) } - /// Storage: `Revive::ContractInfoOf` (r:1 w:1) - /// Proof: `Revive::ContractInfoOf` (`max_values`: None, `max_size`: Some(242), added: 2717, mode: `Measured`) + /// Storage: `Revive::AccountInfoOf` (r:1 w:1) + /// Proof: `Revive::AccountInfoOf` (`max_values`: None, `max_size`: Some(247), added: 2722, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) /// The range of component `d` is `[0, 1]`. - /// The range of component `i` is `[0, 262144]`. + /// The range of component `i` is `[0, 130972]`. fn seal_call_precompile(d: u32, i: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `0 + d * (453 ±0)` - // Estimated: `1959 + d * (1959 ±0)` - // Minimum execution time: 19_412_000 picoseconds. - Weight::from_parts(3_906_222, 1959) - // Standard Error: 378_943 - .saturating_add(Weight::from_parts(16_405_804, 0).saturating_mul(d.into())) - // Standard Error: 2 - .saturating_add(Weight::from_parts(1_205, 0).saturating_mul(i.into())) + // Measured: `366 + d * (212 ±0)` + // Estimated: `2021 + d * (2021 ±0)` + // Minimum execution time: 24_210_000 picoseconds. + Weight::from_parts(11_783_977, 2021) + // Standard Error: 49_916 + .saturating_add(Weight::from_parts(14_132_066, 0).saturating_mul(d.into())) + // Standard Error: 0 + .saturating_add(Weight::from_parts(325, 0).saturating_mul(i.into())) .saturating_add(T::DbWeight::get().reads((2_u64).saturating_mul(d.into()))) .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(d.into()))) - .saturating_add(Weight::from_parts(0, 1959).saturating_mul(d.into())) + .saturating_add(Weight::from_parts(0, 2021).saturating_mul(d.into())) } - /// Storage: `Revive::ContractInfoOf` (r:1 w:0) - /// Proof: `Revive::ContractInfoOf` (`max_values`: None, `max_size`: Some(242), added: 2717, mode: `Measured`) + /// Storage: `Revive::AccountInfoOf` (r:1 w:0) + /// Proof: `Revive::AccountInfoOf` (`max_values`: None, `max_size`: Some(247), added: 2722, mode: `Measured`) /// Storage: `Revive::CodeInfoOf` (r:1 w:0) /// Proof: `Revive::CodeInfoOf` (`max_values`: None, `max_size`: Some(96), added: 2571, mode: `Measured`) /// Storage: `Revive::PristineCode` (r:1 w:0) - /// Proof: `Revive::PristineCode` (`max_values`: None, `max_size`: Some(262180), added: 264655, mode: `Measured`) + /// Proof: `Revive::PristineCode` (`max_values`: None, `max_size`: Some(1048612), added: 1051087, mode: `Measured`) fn seal_delegate_call() -> Weight { // Proof Size summary in bytes: - // Measured: `1236` - // Estimated: `4701` - // Minimum execution time: 28_834_000 picoseconds. - Weight::from_parts(30_072_000, 4701) + // Measured: `1362` + // Estimated: `4827` + // Minimum execution time: 31_948_000 picoseconds. + Weight::from_parts(33_936_000, 4827) .saturating_add(T::DbWeight::get().reads(3_u64)) } /// Storage: `Revive::CodeInfoOf` (r:1 w:1) /// Proof: `Revive::CodeInfoOf` (`max_values`: None, `max_size`: Some(96), added: 2571, mode: `Measured`) /// Storage: `Revive::PristineCode` (r:1 w:0) - /// Proof: `Revive::PristineCode` (`max_values`: None, `max_size`: Some(262180), added: 264655, mode: `Measured`) - /// Storage: `Revive::ContractInfoOf` (r:1 w:1) - /// Proof: `Revive::ContractInfoOf` (`max_values`: None, `max_size`: Some(242), added: 2717, mode: `Measured`) + /// Proof: `Revive::PristineCode` (`max_values`: None, `max_size`: Some(1048612), added: 1051087, mode: `Measured`) + /// Storage: `Revive::AccountInfoOf` (r:1 w:1) + /// Proof: `Revive::AccountInfoOf` (`max_values`: None, `max_size`: Some(247), added: 2722, mode: `Measured`) /// Storage: `System::Account` (r:1 w:1) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) - /// The range of component `i` is `[0, 262144]`. - fn seal_instantiate(i: u32, ) -> Weight { - // Proof Size summary in bytes: - // Measured: `1260` - // Estimated: `4728` - // Minimum execution time: 112_787_000 picoseconds. - Weight::from_parts(105_258_744, 4728) - // Standard Error: 10 - .saturating_add(Weight::from_parts(4_163, 0).saturating_mul(i.into())) + /// The range of component `t` is `[0, 1]`. + /// The range of component `d` is `[0, 1]`. + /// The range of component `i` is `[0, 131072]`. + fn seal_instantiate(t: u32, d: u32, i: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `1417` + // Estimated: `4876` + // Minimum execution time: 150_079_000 picoseconds. + Weight::from_parts(104_920_700, 4876) + // Standard Error: 456_076 + .saturating_add(Weight::from_parts(20_263_777, 0).saturating_mul(t.into())) + // Standard Error: 456_076 + .saturating_add(Weight::from_parts(30_617_352, 0).saturating_mul(d.into())) + // Standard Error: 5 + .saturating_add(Weight::from_parts(3_949, 0).saturating_mul(i.into())) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) } - /// The range of component `n` is `[0, 262144]`. + /// The range of component `n` is `[0, 1048576]`. fn sha2_256(n: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 792_000 picoseconds. - Weight::from_parts(4_505_628, 0) - // Standard Error: 3 - .saturating_add(Weight::from_parts(1_285, 0).saturating_mul(n.into())) + // Minimum execution time: 1_165_000 picoseconds. + Weight::from_parts(9_566_786, 0) + // Standard Error: 0 + .saturating_add(Weight::from_parts(1_251, 0).saturating_mul(n.into())) } - /// The range of component `n` is `[0, 262144]`. + /// The range of component `n` is `[0, 1048576]`. fn identity(n: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 300_000 picoseconds. - Weight::from_parts(468_743, 0) + // Minimum execution time: 727_000 picoseconds. + Weight::from_parts(868_990, 0) // Standard Error: 0 - .saturating_add(Weight::from_parts(148, 0).saturating_mul(n.into())) + .saturating_add(Weight::from_parts(112, 0).saturating_mul(n.into())) } - /// The range of component `n` is `[0, 262144]`. + /// The range of component `n` is `[0, 1048576]`. fn ripemd_160(n: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 744_000 picoseconds. - Weight::from_parts(771_000, 0) - // Standard Error: 1 - .saturating_add(Weight::from_parts(3_928, 0).saturating_mul(n.into())) + // Minimum execution time: 1_228_000 picoseconds. + Weight::from_parts(8_112_183, 0) + // Standard Error: 0 + .saturating_add(Weight::from_parts(3_718, 0).saturating_mul(n.into())) } - /// The range of component `n` is `[0, 262144]`. + /// The range of component `n` is `[0, 1048576]`. fn seal_hash_keccak_256(n: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 1_002_000 picoseconds. - Weight::from_parts(3_889_121, 0) - // Standard Error: 3 - .saturating_add(Weight::from_parts(3_666, 0).saturating_mul(n.into())) + // Minimum execution time: 1_142_000 picoseconds. + Weight::from_parts(12_135_609, 0) + // Standard Error: 1 + .saturating_add(Weight::from_parts(3_539, 0).saturating_mul(n.into())) } - /// The range of component `n` is `[0, 262144]`. - fn seal_hash_blake2_256(n: u32, ) -> Weight { + /// The range of component `n` is `[0, 1048576]`. + fn hash_blake2_256(n: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 562_000 picoseconds. - Weight::from_parts(3_823_066, 0) - // Standard Error: 3 - .saturating_add(Weight::from_parts(1_569, 0).saturating_mul(n.into())) + // Minimum execution time: 1_520_000 picoseconds. + Weight::from_parts(10_863_970, 0) + // Standard Error: 0 + .saturating_add(Weight::from_parts(1_405, 0).saturating_mul(n.into())) } - /// The range of component `n` is `[0, 262144]`. + /// The range of component `n` is `[0, 1048576]`. fn seal_hash_blake2_128(n: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 543_000 picoseconds. - Weight::from_parts(3_582_133, 0) - // Standard Error: 2 - .saturating_add(Weight::from_parts(1_576, 0).saturating_mul(n.into())) + // Minimum execution time: 713_000 picoseconds. + Weight::from_parts(5_972_288, 0) + // Standard Error: 0 + .saturating_add(Weight::from_parts(1_498, 0).saturating_mul(n.into())) } - /// The range of component `n` is `[0, 261889]`. + /// The range of component `n` is `[0, 1048321]`. fn seal_sr25519_verify(n: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 42_702_000 picoseconds. - Weight::from_parts(30_839_817, 0) - // Standard Error: 10 - .saturating_add(Weight::from_parts(5_086, 0).saturating_mul(n.into())) + // Minimum execution time: 42_872_000 picoseconds. + Weight::from_parts(83_548_865, 0) + // Standard Error: 3 + .saturating_add(Weight::from_parts(4_865, 0).saturating_mul(n.into())) } fn ecdsa_recover() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 44_770_000 picoseconds. - Weight::from_parts(45_791_000, 0) + // Minimum execution time: 45_827_000 picoseconds. + Weight::from_parts(46_613_000, 0) } fn bn128_add() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 15_705_000 picoseconds. - Weight::from_parts(16_885_000, 0) + // Minimum execution time: 14_422_000 picoseconds. + Weight::from_parts(15_942_000, 0) } fn bn128_mul() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 1_018_103_000 picoseconds. - Weight::from_parts(1_023_315_000, 0) + // Minimum execution time: 974_593_000 picoseconds. + Weight::from_parts(980_966_000, 0) } /// The range of component `n` is `[0, 20]`. fn bn128_pairing(n: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 378_000 picoseconds. - Weight::from_parts(5_119_381_361, 0) - // Standard Error: 10_821_771 - .saturating_add(Weight::from_parts(6_202_434_383, 0).saturating_mul(n.into())) + // Minimum execution time: 851_000 picoseconds. + Weight::from_parts(4_760_087_459, 0) + // Standard Error: 10_485_749 + .saturating_add(Weight::from_parts(5_940_723_809, 0).saturating_mul(n.into())) } /// The range of component `n` is `[0, 1200]`. fn blake2f(n: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 435_000 picoseconds. - Weight::from_parts(658_540, 0) - // Standard Error: 6 - .saturating_add(Weight::from_parts(22_679, 0).saturating_mul(n.into())) + // Minimum execution time: 953_000 picoseconds. + Weight::from_parts(1_258_163, 0) + // Standard Error: 50 + .saturating_add(Weight::from_parts(28_977, 0).saturating_mul(n.into())) } fn seal_ecdsa_to_eth_address() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 12_639_000 picoseconds. - Weight::from_parts(12_782_000, 0) + // Minimum execution time: 13_049_000 picoseconds. + Weight::from_parts(13_232_000, 0) } /// Storage: `Revive::CodeInfoOf` (r:1 w:1) /// Proof: `Revive::CodeInfoOf` (`max_values`: None, `max_size`: Some(96), added: 2571, mode: `Measured`) fn seal_set_code_hash() -> Weight { // Proof Size summary in bytes: - // Measured: `300` - // Estimated: `3765` - // Minimum execution time: 12_210_000 picoseconds. - Weight::from_parts(12_747_000, 3765) + // Measured: `296` + // Estimated: `3761` + // Minimum execution time: 10_342_000 picoseconds. + Weight::from_parts(10_818_000, 3761) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -1120,20 +1193,33 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 11_244_000 picoseconds. - Weight::from_parts(48_207_913, 0) - // Standard Error: 495 - .saturating_add(Weight::from_parts(125_133, 0).saturating_mul(r.into())) + // Minimum execution time: 11_081_000 picoseconds. + Weight::from_parts(39_209_404, 0) + // Standard Error: 395 + .saturating_add(Weight::from_parts(106_585, 0).saturating_mul(r.into())) } /// The range of component `r` is `[0, 100000]`. fn instr_empty_loop(r: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 2_776_000 picoseconds. - Weight::from_parts(6_412_428, 0) - // Standard Error: 17 - .saturating_add(Weight::from_parts(72_988, 0).saturating_mul(r.into())) + // Minimum execution time: 3_146_000 picoseconds. + Weight::from_parts(4_731_872, 0) + // Standard Error: 13 + .saturating_add(Weight::from_parts(73_452, 0).saturating_mul(r.into())) + } + /// Storage: UNKNOWN KEY `0x735f040a5d490f1107ad9c56f5ca00d2060e99e5378e562537cf3bc983e17b91` (r:2 w:1) + /// Proof: UNKNOWN KEY `0x735f040a5d490f1107ad9c56f5ca00d2060e99e5378e562537cf3bc983e17b91` (r:2 w:1) + /// Storage: `Revive::AccountInfoOf` (r:0 w:1) + /// Proof: `Revive::AccountInfoOf` (`max_values`: None, `max_size`: Some(247), added: 2722, mode: `MaxEncodedLen`) + fn v1_migration_step() -> Weight { + // Proof Size summary in bytes: + // Measured: `316` + // Estimated: `6256` + // Minimum execution time: 12_136_000 picoseconds. + Weight::from_parts(12_668_000, 6256) + .saturating_add(T::DbWeight::get().reads(2_u64)) + .saturating_add(T::DbWeight::get().writes(2_u64)) } } @@ -1145,8 +1231,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `147` // Estimated: `1632` - // Minimum execution time: 2_971_000 picoseconds. - Weight::from_parts(3_218_000, 1632) + // Minimum execution time: 3_008_000 picoseconds. + Weight::from_parts(3_256_000, 1632) .saturating_add(RocksDbWeight::get().reads(1_u64)) } /// Storage: `Skipped::Metadata` (r:0 w:0) @@ -1154,12 +1240,12 @@ impl WeightInfo for () { /// The range of component `k` is `[0, 1024]`. fn on_initialize_per_trie_key(k: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `425 + k * (69 ±0)` - // Estimated: `415 + k * (70 ±0)` - // Minimum execution time: 14_042_000 picoseconds. - Weight::from_parts(14_510_000, 415) - // Standard Error: 1_047 - .saturating_add(Weight::from_parts(1_167_098, 0).saturating_mul(k.into())) + // Measured: `458 + k * (69 ±0)` + // Estimated: `448 + k * (70 ±0)` + // Minimum execution time: 14_584_000 picoseconds. + Weight::from_parts(772_449, 448) + // Standard Error: 1_278 + .saturating_add(Weight::from_parts(1_204_643, 0).saturating_mul(k.into())) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(k.into()))) .saturating_add(RocksDbWeight::get().writes(2_u64)) @@ -1168,198 +1254,258 @@ impl WeightInfo for () { } /// Storage: `Revive::OriginalAccount` (r:2 w:0) /// Proof: `Revive::OriginalAccount` (`max_values`: None, `max_size`: Some(52), added: 2527, mode: `Measured`) - /// Storage: `Revive::ContractInfoOf` (r:1 w:1) - /// Proof: `Revive::ContractInfoOf` (`max_values`: None, `max_size`: Some(242), added: 2717, mode: `Measured`) + /// Storage: `Revive::AccountInfoOf` (r:1 w:1) + /// Proof: `Revive::AccountInfoOf` (`max_values`: None, `max_size`: Some(247), added: 2722, mode: `Measured`) /// Storage: `Revive::CodeInfoOf` (r:1 w:0) /// Proof: `Revive::CodeInfoOf` (`max_values`: None, `max_size`: Some(96), added: 2571, mode: `Measured`) /// Storage: `Revive::PristineCode` (r:1 w:0) - /// Proof: `Revive::PristineCode` (`max_values`: None, `max_size`: Some(262180), added: 264655, mode: `Measured`) + /// Proof: `Revive::PristineCode` (`max_values`: None, `max_size`: Some(1048612), added: 1051087, mode: `Measured`) /// Storage: `Timestamp::Now` (r:1 w:0) /// Proof: `Timestamp::Now` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `Measured`) /// Storage: `System::Account` (r:1 w:1) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) - /// The range of component `c` is `[0, 104857]`. + /// The range of component `c` is `[0, 102400]`. fn call_with_code_per_byte(c: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `1178 + c * (1 ±0)` - // Estimated: `7119 + c * (1 ±0)` - // Minimum execution time: 81_842_000 picoseconds. - Weight::from_parts(110_091_076, 7119) - // Standard Error: 12 - .saturating_add(Weight::from_parts(2_123, 0).saturating_mul(c.into())) + // Measured: `1171 + c * (1 ±0)` + // Estimated: `7106 + c * (1 ±0)` + // Minimum execution time: 86_230_000 picoseconds. + Weight::from_parts(124_424_225, 7106) + // Standard Error: 10 + .saturating_add(Weight::from_parts(1_256, 0).saturating_mul(c.into())) .saturating_add(RocksDbWeight::get().reads(7_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) .saturating_add(Weight::from_parts(0, 1).saturating_mul(c.into())) } /// Storage: `Revive::OriginalAccount` (r:2 w:0) /// Proof: `Revive::OriginalAccount` (`max_values`: None, `max_size`: Some(52), added: 2527, mode: `Measured`) - /// Storage: `Revive::ContractInfoOf` (r:1 w:1) - /// Proof: `Revive::ContractInfoOf` (`max_values`: None, `max_size`: Some(242), added: 2717, mode: `Measured`) + /// Storage: `Revive::AccountInfoOf` (r:1 w:1) + /// Proof: `Revive::AccountInfoOf` (`max_values`: None, `max_size`: Some(247), added: 2722, mode: `Measured`) /// Storage: `Revive::CodeInfoOf` (r:1 w:0) /// Proof: `Revive::CodeInfoOf` (`max_values`: None, `max_size`: Some(96), added: 2571, mode: `Measured`) /// Storage: `Revive::PristineCode` (r:1 w:0) - /// Proof: `Revive::PristineCode` (`max_values`: None, `max_size`: Some(262180), added: 264655, mode: `Measured`) + /// Proof: `Revive::PristineCode` (`max_values`: None, `max_size`: Some(1048612), added: 1051087, mode: `Measured`) /// Storage: `Timestamp::Now` (r:1 w:0) /// Proof: `Timestamp::Now` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `Measured`) /// Storage: `System::Account` (r:1 w:1) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) /// The range of component `b` is `[0, 1]`. - fn basic_block_compilation(b: u32, ) -> Weight { - // Proof Size summary in bytes: - // Measured: `4513` - // Estimated: `10453` - // Minimum execution time: 121_768_000 picoseconds. - Weight::from_parts(126_040_712, 10453) - // Standard Error: 315_571 - .saturating_add(Weight::from_parts(961_687, 0).saturating_mul(b.into())) + fn basic_block_compilation(_b: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `4515` + // Estimated: `10455` + // Minimum execution time: 124_359_000 picoseconds. + Weight::from_parts(129_025_585, 10455) .saturating_add(RocksDbWeight::get().reads(7_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } /// Storage: `Revive::CodeInfoOf` (r:1 w:1) /// Proof: `Revive::CodeInfoOf` (`max_values`: None, `max_size`: Some(96), added: 2571, mode: `Measured`) /// Storage: `Balances::Holds` (r:2 w:2) - /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(409), added: 2884, mode: `Measured`) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(427), added: 2902, mode: `Measured`) /// Storage: `Revive::OriginalAccount` (r:1 w:0) /// Proof: `Revive::OriginalAccount` (`max_values`: None, `max_size`: Some(52), added: 2527, mode: `Measured`) - /// Storage: `Revive::ContractInfoOf` (r:1 w:1) - /// Proof: `Revive::ContractInfoOf` (`max_values`: None, `max_size`: Some(242), added: 2717, mode: `Measured`) + /// Storage: `Revive::AccountInfoOf` (r:1 w:1) + /// Proof: `Revive::AccountInfoOf` (`max_values`: None, `max_size`: Some(247), added: 2722, mode: `Measured`) /// Storage: `Timestamp::Now` (r:1 w:0) /// Proof: `Timestamp::Now` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `Measured`) /// Storage: `System::Account` (r:1 w:1) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) /// Storage: `Revive::PristineCode` (r:0 w:1) - /// Proof: `Revive::PristineCode` (`max_values`: None, `max_size`: Some(262180), added: 264655, mode: `Measured`) - /// The range of component `c` is `[0, 104857]`. - /// The range of component `i` is `[0, 262144]`. + /// Proof: `Revive::PristineCode` (`max_values`: None, `max_size`: Some(1048612), added: 1051087, mode: `Measured`) + /// The range of component `c` is `[0, 102400]`. + /// The range of component `i` is `[0, 131072]`. fn instantiate_with_code(c: u32, i: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `1108` + // Estimated: `7041` + // Minimum execution time: 755_622_000 picoseconds. + Weight::from_parts(57_161_132, 7041) + // Standard Error: 36 + .saturating_add(Weight::from_parts(19_425, 0).saturating_mul(c.into())) + // Standard Error: 28 + .saturating_add(Weight::from_parts(5_000, 0).saturating_mul(i.into())) + .saturating_add(RocksDbWeight::get().reads(7_u64)) + .saturating_add(RocksDbWeight::get().writes(6_u64)) + } + /// Storage: `Revive::CodeInfoOf` (r:1 w:1) + /// Proof: `Revive::CodeInfoOf` (`max_values`: None, `max_size`: Some(96), added: 2571, mode: `Measured`) + /// Storage: `Balances::Holds` (r:2 w:2) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(427), added: 2902, mode: `Measured`) + /// Storage: `Revive::OriginalAccount` (r:1 w:0) + /// Proof: `Revive::OriginalAccount` (`max_values`: None, `max_size`: Some(52), added: 2527, mode: `Measured`) + /// Storage: `Revive::AccountInfoOf` (r:2 w:2) + /// Proof: `Revive::AccountInfoOf` (`max_values`: None, `max_size`: Some(247), added: 2722, mode: `Measured`) + /// Storage: `Timestamp::Now` (r:1 w:0) + /// Proof: `Timestamp::Now` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `Measured`) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) + /// Storage: `Revive::PristineCode` (r:0 w:1) + /// Proof: `Revive::PristineCode` (`max_values`: None, `max_size`: Some(1048612), added: 1051087, mode: `Measured`) + /// The range of component `c` is `[0, 102400]`. + /// The range of component `i` is `[0, 131072]`. + /// The range of component `d` is `[0, 1]`. + fn eth_instantiate_with_code(c: u32, i: u32, d: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `1122` - // Estimated: `7010` - // Minimum execution time: 1_593_697_000 picoseconds. - Weight::from_parts(150_335_332, 7010) - // Standard Error: 34 - .saturating_add(Weight::from_parts(19_710, 0).saturating_mul(c.into())) - // Standard Error: 13 - .saturating_add(Weight::from_parts(5_466, 0).saturating_mul(i.into())) + // Estimated: `7062 + d * (2475 ±0)` + // Minimum execution time: 281_326_000 picoseconds. + Weight::from_parts(192_766_004, 7062) + // Standard Error: 15 + .saturating_add(Weight::from_parts(14_166, 0).saturating_mul(c.into())) + // Standard Error: 11 + .saturating_add(Weight::from_parts(403, 0).saturating_mul(i.into())) + // Standard Error: 983_169 + .saturating_add(Weight::from_parts(30_340_467, 0).saturating_mul(d.into())) .saturating_add(RocksDbWeight::get().reads(7_u64)) + .saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(d.into()))) .saturating_add(RocksDbWeight::get().writes(6_u64)) + .saturating_add(RocksDbWeight::get().writes((1_u64).saturating_mul(d.into()))) + .saturating_add(Weight::from_parts(0, 2475).saturating_mul(d.into())) } /// Storage: `Revive::CodeInfoOf` (r:1 w:1) /// Proof: `Revive::CodeInfoOf` (`max_values`: None, `max_size`: Some(96), added: 2571, mode: `Measured`) /// Storage: `Revive::PristineCode` (r:1 w:0) - /// Proof: `Revive::PristineCode` (`max_values`: None, `max_size`: Some(262180), added: 264655, mode: `Measured`) + /// Proof: `Revive::PristineCode` (`max_values`: None, `max_size`: Some(1048612), added: 1051087, mode: `Measured`) /// Storage: `Revive::OriginalAccount` (r:1 w:0) /// Proof: `Revive::OriginalAccount` (`max_values`: None, `max_size`: Some(52), added: 2527, mode: `Measured`) - /// Storage: `Revive::ContractInfoOf` (r:1 w:1) - /// Proof: `Revive::ContractInfoOf` (`max_values`: None, `max_size`: Some(242), added: 2717, mode: `Measured`) + /// Storage: `Revive::AccountInfoOf` (r:1 w:1) + /// Proof: `Revive::AccountInfoOf` (`max_values`: None, `max_size`: Some(247), added: 2722, mode: `Measured`) /// Storage: `Timestamp::Now` (r:1 w:0) /// Proof: `Timestamp::Now` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `Measured`) /// Storage: `System::Account` (r:1 w:1) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) /// Storage: `Balances::Holds` (r:1 w:1) - /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(409), added: 2884, mode: `Measured`) - /// The range of component `i` is `[0, 262144]`. + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(427), added: 2902, mode: `Measured`) + /// The range of component `i` is `[0, 131072]`. fn instantiate(i: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `1886` - // Estimated: `5346` - // Minimum execution time: 155_867_000 picoseconds. - Weight::from_parts(88_055_300, 5346) - // Standard Error: 25 - .saturating_add(Weight::from_parts(5_561, 0).saturating_mul(i.into())) + // Measured: `1912` + // Estimated: `5362` + // Minimum execution time: 172_513_000 picoseconds. + Weight::from_parts(178_290_134, 5362) + // Standard Error: 11 + .saturating_add(Weight::from_parts(4_158, 0).saturating_mul(i.into())) .saturating_add(RocksDbWeight::get().reads(7_u64)) .saturating_add(RocksDbWeight::get().writes(4_u64)) } /// Storage: `Revive::OriginalAccount` (r:2 w:0) /// Proof: `Revive::OriginalAccount` (`max_values`: None, `max_size`: Some(52), added: 2527, mode: `Measured`) - /// Storage: `Revive::ContractInfoOf` (r:1 w:1) - /// Proof: `Revive::ContractInfoOf` (`max_values`: None, `max_size`: Some(242), added: 2717, mode: `Measured`) + /// Storage: `Revive::AccountInfoOf` (r:1 w:1) + /// Proof: `Revive::AccountInfoOf` (`max_values`: None, `max_size`: Some(247), added: 2722, mode: `Measured`) /// Storage: `Revive::CodeInfoOf` (r:1 w:0) /// Proof: `Revive::CodeInfoOf` (`max_values`: None, `max_size`: Some(96), added: 2571, mode: `Measured`) /// Storage: `Revive::PristineCode` (r:1 w:0) - /// Proof: `Revive::PristineCode` (`max_values`: None, `max_size`: Some(262180), added: 264655, mode: `Measured`) + /// Proof: `Revive::PristineCode` (`max_values`: None, `max_size`: Some(1048612), added: 1051087, mode: `Measured`) /// Storage: `Timestamp::Now` (r:1 w:0) /// Proof: `Timestamp::Now` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `Measured`) /// Storage: `System::Account` (r:1 w:1) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) fn call() -> Weight { // Proof Size summary in bytes: - // Measured: `1812` - // Estimated: `7752` - // Minimum execution time: 85_908_000 picoseconds. - Weight::from_parts(87_953_000, 7752) + // Measured: `1792` + // Estimated: `7732` + // Minimum execution time: 87_638_000 picoseconds. + Weight::from_parts(90_000_000, 7732) + .saturating_add(RocksDbWeight::get().reads(7_u64)) + .saturating_add(RocksDbWeight::get().writes(2_u64)) + } + /// Storage: `Revive::OriginalAccount` (r:2 w:0) + /// Proof: `Revive::OriginalAccount` (`max_values`: None, `max_size`: Some(52), added: 2527, mode: `Measured`) + /// Storage: `Revive::AccountInfoOf` (r:2 w:2) + /// Proof: `Revive::AccountInfoOf` (`max_values`: None, `max_size`: Some(247), added: 2722, mode: `Measured`) + /// Storage: `Revive::CodeInfoOf` (r:1 w:0) + /// Proof: `Revive::CodeInfoOf` (`max_values`: None, `max_size`: Some(96), added: 2571, mode: `Measured`) + /// Storage: `Revive::PristineCode` (r:1 w:0) + /// Proof: `Revive::PristineCode` (`max_values`: None, `max_size`: Some(1048612), added: 1051087, mode: `Measured`) + /// Storage: `Timestamp::Now` (r:1 w:0) + /// Proof: `Timestamp::Now` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `Measured`) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) + /// The range of component `d` is `[0, 1]`. + fn eth_call(d: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `1792` + // Estimated: `7732 + d * (2475 ±0)` + // Minimum execution time: 85_839_000 picoseconds. + Weight::from_parts(90_556_373, 7732) + // Standard Error: 358_297 + .saturating_add(Weight::from_parts(27_649_126, 0).saturating_mul(d.into())) .saturating_add(RocksDbWeight::get().reads(7_u64)) + .saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(d.into()))) .saturating_add(RocksDbWeight::get().writes(2_u64)) + .saturating_add(RocksDbWeight::get().writes((1_u64).saturating_mul(d.into()))) + .saturating_add(Weight::from_parts(0, 2475).saturating_mul(d.into())) } /// Storage: `Revive::CodeInfoOf` (r:1 w:1) /// Proof: `Revive::CodeInfoOf` (`max_values`: None, `max_size`: Some(96), added: 2571, mode: `Measured`) /// Storage: `Balances::Holds` (r:1 w:1) - /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(409), added: 2884, mode: `Measured`) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(427), added: 2902, mode: `Measured`) /// Storage: `Revive::PristineCode` (r:0 w:1) - /// Proof: `Revive::PristineCode` (`max_values`: None, `max_size`: Some(262180), added: 264655, mode: `Measured`) - /// The range of component `c` is `[0, 104857]`. + /// Proof: `Revive::PristineCode` (`max_values`: None, `max_size`: Some(1048612), added: 1051087, mode: `Measured`) + /// The range of component `c` is `[0, 102400]`. fn upload_code(c: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `505` // Estimated: `3970` - // Minimum execution time: 51_305_000 picoseconds. - Weight::from_parts(27_197_599, 3970) - // Standard Error: 20 - .saturating_add(Weight::from_parts(14_721, 0).saturating_mul(c.into())) + // Minimum execution time: 56_805_000 picoseconds. + Weight::from_parts(50_855_179, 3970) + // Standard Error: 35 + .saturating_add(Weight::from_parts(13_927, 0).saturating_mul(c.into())) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) } /// Storage: `Revive::CodeInfoOf` (r:1 w:1) /// Proof: `Revive::CodeInfoOf` (`max_values`: None, `max_size`: Some(96), added: 2571, mode: `Measured`) /// Storage: `Balances::Holds` (r:1 w:1) - /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(409), added: 2884, mode: `Measured`) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(427), added: 2902, mode: `Measured`) /// Storage: `Revive::PristineCode` (r:0 w:1) - /// Proof: `Revive::PristineCode` (`max_values`: None, `max_size`: Some(262180), added: 264655, mode: `Measured`) + /// Proof: `Revive::PristineCode` (`max_values`: None, `max_size`: Some(1048612), added: 1051087, mode: `Measured`) fn remove_code() -> Weight { // Proof Size summary in bytes: // Measured: `658` // Estimated: `4123` - // Minimum execution time: 41_900_000 picoseconds. - Weight::from_parts(42_985_000, 4123) + // Minimum execution time: 47_344_000 picoseconds. + Weight::from_parts(48_892_000, 4123) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) } - /// Storage: `Revive::ContractInfoOf` (r:1 w:1) - /// Proof: `Revive::ContractInfoOf` (`max_values`: None, `max_size`: Some(242), added: 2717, mode: `Measured`) + /// Storage: `Revive::AccountInfoOf` (r:1 w:1) + /// Proof: `Revive::AccountInfoOf` (`max_values`: None, `max_size`: Some(247), added: 2722, mode: `Measured`) /// Storage: `Revive::CodeInfoOf` (r:2 w:2) /// Proof: `Revive::CodeInfoOf` (`max_values`: None, `max_size`: Some(96), added: 2571, mode: `Measured`) fn set_code() -> Weight { // Proof Size summary in bytes: - // Measured: `528` - // Estimated: `6468` - // Minimum execution time: 20_254_000 picoseconds. - Weight::from_parts(21_122_000, 6468) + // Measured: `530` + // Estimated: `6470` + // Minimum execution time: 20_627_000 picoseconds. + Weight::from_parts(21_451_000, 6470) .saturating_add(RocksDbWeight::get().reads(3_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) } /// Storage: `Revive::OriginalAccount` (r:1 w:1) /// Proof: `Revive::OriginalAccount` (`max_values`: None, `max_size`: Some(52), added: 2527, mode: `Measured`) /// Storage: `Balances::Holds` (r:1 w:1) - /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(409), added: 2884, mode: `Measured`) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(427), added: 2902, mode: `Measured`) fn map_account() -> Weight { // Proof Size summary in bytes: // Measured: `813` // Estimated: `4278` - // Minimum execution time: 50_406_000 picoseconds. - Weight::from_parts(51_939_000, 4278) + // Minimum execution time: 57_209_000 picoseconds. + Weight::from_parts(58_942_000, 4278) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } /// Storage: `Balances::Holds` (r:1 w:1) - /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(409), added: 2884, mode: `Measured`) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(427), added: 2902, mode: `Measured`) /// Storage: `Revive::OriginalAccount` (r:0 w:1) /// Proof: `Revive::OriginalAccount` (`max_values`: None, `max_size`: Some(52), added: 2527, mode: `Measured`) fn unmap_account() -> Weight { // Proof Size summary in bytes: // Measured: `395` // Estimated: `3860` - // Minimum execution time: 37_679_000 picoseconds. - Weight::from_parts(39_183_000, 3860) + // Minimum execution time: 42_757_000 picoseconds. + Weight::from_parts(44_178_000, 3860) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } @@ -1371,8 +1517,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `145` // Estimated: `3610` - // Minimum execution time: 12_684_000 picoseconds. - Weight::from_parts(13_240_000, 3610) + // Minimum execution time: 13_062_000 picoseconds. + Weight::from_parts(13_660_000, 3610) .saturating_add(RocksDbWeight::get().reads(2_u64)) } /// The range of component `r` is `[0, 1600]`. @@ -1380,129 +1526,131 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 6_583_000 picoseconds. - Weight::from_parts(8_416_964, 0) - // Standard Error: 170 - .saturating_add(Weight::from_parts(164_523, 0).saturating_mul(r.into())) + // Minimum execution time: 7_588_000 picoseconds. + Weight::from_parts(8_755_261, 0) + // Standard Error: 236 + .saturating_add(Weight::from_parts(182_421, 0).saturating_mul(r.into())) } fn seal_caller() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 199_000 picoseconds. - Weight::from_parts(233_000, 0) + // Minimum execution time: 335_000 picoseconds. + Weight::from_parts(390_000, 0) } fn seal_origin() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 184_000 picoseconds. - Weight::from_parts(206_000, 0) + // Minimum execution time: 350_000 picoseconds. + Weight::from_parts(386_000, 0) } /// Storage: `Revive::OriginalAccount` (r:1 w:0) /// Proof: `Revive::OriginalAccount` (`max_values`: None, `max_size`: Some(52), added: 2527, mode: `Measured`) fn seal_to_account_id() -> Weight { // Proof Size summary in bytes: - // Measured: `538` - // Estimated: `4003` - // Minimum execution time: 9_364_000 picoseconds. - Weight::from_parts(9_672_000, 4003) + // Measured: `571` + // Estimated: `4036` + // Minimum execution time: 9_818_000 picoseconds. + Weight::from_parts(10_279_000, 4036) .saturating_add(RocksDbWeight::get().reads(1_u64)) } - /// Storage: `Revive::ContractInfoOf` (r:1 w:0) - /// Proof: `Revive::ContractInfoOf` (`max_values`: None, `max_size`: Some(242), added: 2717, mode: `Measured`) + /// Storage: `Revive::AccountInfoOf` (r:1 w:0) + /// Proof: `Revive::AccountInfoOf` (`max_values`: None, `max_size`: Some(247), added: 2722, mode: `Measured`) fn seal_code_hash() -> Weight { // Proof Size summary in bytes: - // Measured: `402` - // Estimated: `3867` - // Minimum execution time: 9_183_000 picoseconds. - Weight::from_parts(9_609_000, 3867) + // Measured: `403` + // Estimated: `3868` + // Minimum execution time: 9_222_000 picoseconds. + Weight::from_parts(9_806_000, 3868) .saturating_add(RocksDbWeight::get().reads(1_u64)) } fn seal_own_code_hash() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 131_000 picoseconds. - Weight::from_parts(176_000, 0) + // Minimum execution time: 282_000 picoseconds. + Weight::from_parts(336_000, 0) } - /// Storage: `Revive::ContractInfoOf` (r:1 w:0) - /// Proof: `Revive::ContractInfoOf` (`max_values`: None, `max_size`: Some(242), added: 2717, mode: `Measured`) + /// Storage: `Revive::AccountInfoOf` (r:1 w:0) + /// Proof: `Revive::AccountInfoOf` (`max_values`: None, `max_size`: Some(247), added: 2722, mode: `Measured`) /// Storage: `Revive::CodeInfoOf` (r:1 w:0) /// Proof: `Revive::CodeInfoOf` (`max_values`: None, `max_size`: Some(96), added: 2571, mode: `Measured`) fn seal_code_size() -> Weight { // Proof Size summary in bytes: - // Measured: `472` - // Estimated: `3937` - // Minimum execution time: 12_217_000 picoseconds. - Weight::from_parts(13_005_000, 3937) + // Measured: `474` + // Estimated: `3939` + // Minimum execution time: 12_825_000 picoseconds. + Weight::from_parts(13_490_000, 3939) .saturating_add(RocksDbWeight::get().reads(2_u64)) } fn seal_caller_is_origin() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 208_000 picoseconds. - Weight::from_parts(228_000, 0) + // Minimum execution time: 321_000 picoseconds. + Weight::from_parts(372_000, 0) } fn seal_caller_is_root() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 170_000 picoseconds. - Weight::from_parts(203_000, 0) + // Minimum execution time: 269_000 picoseconds. + Weight::from_parts(327_000, 0) } fn seal_address() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 182_000 picoseconds. - Weight::from_parts(204_000, 0) + // Minimum execution time: 304_000 picoseconds. + Weight::from_parts(343_000, 0) } fn seal_weight_left() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 576_000 picoseconds. - Weight::from_parts(637_000, 0) + // Minimum execution time: 700_000 picoseconds. + Weight::from_parts(802_000, 0) } fn seal_ref_time_left() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 131_000 picoseconds. - Weight::from_parts(168_000, 0) + // Minimum execution time: 263_000 picoseconds. + Weight::from_parts(325_000, 0) } fn seal_balance() -> Weight { // Proof Size summary in bytes: - // Measured: `103` + // Measured: `506` // Estimated: `0` - // Minimum execution time: 4_466_000 picoseconds. - Weight::from_parts(4_813_000, 0) + // Minimum execution time: 13_351_000 picoseconds. + Weight::from_parts(13_878_000, 0) } /// Storage: `Revive::OriginalAccount` (r:1 w:0) /// Proof: `Revive::OriginalAccount` (`max_values`: None, `max_size`: Some(52), added: 2527, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) + /// Storage: `Revive::AccountInfoOf` (r:1 w:0) + /// Proof: `Revive::AccountInfoOf` (`max_values`: None, `max_size`: Some(247), added: 2722, mode: `Measured`) fn seal_balance_of() -> Weight { // Proof Size summary in bytes: - // Measured: `517` - // Estimated: `3982` - // Minimum execution time: 8_786_000 picoseconds. - Weight::from_parts(9_450_000, 3982) - .saturating_add(RocksDbWeight::get().reads(2_u64)) + // Measured: `791` + // Estimated: `4256` + // Minimum execution time: 18_603_000 picoseconds. + Weight::from_parts(19_511_000, 4256) + .saturating_add(RocksDbWeight::get().reads(3_u64)) } /// Storage: `Revive::ImmutableDataOf` (r:1 w:0) /// Proof: `Revive::ImmutableDataOf` (`max_values`: None, `max_size`: Some(4118), added: 6593, mode: `Measured`) /// The range of component `n` is `[1, 4096]`. fn seal_get_immutable_data(n: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `238 + n * (1 ±0)` - // Estimated: `3703 + n * (1 ±0)` - // Minimum execution time: 5_796_000 picoseconds. - Weight::from_parts(6_399_722, 3703) - // Standard Error: 4 - .saturating_add(Weight::from_parts(581, 0).saturating_mul(n.into())) + // Measured: `271 + n * (1 ±0)` + // Estimated: `3736 + n * (1 ±0)` + // Minimum execution time: 6_013_000 picoseconds. + Weight::from_parts(6_757_699, 3736) + // Standard Error: 5 + .saturating_add(Weight::from_parts(483, 0).saturating_mul(n.into())) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(Weight::from_parts(0, 1).saturating_mul(n.into())) } @@ -1513,67 +1661,67 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 1_950_000 picoseconds. - Weight::from_parts(2_072_690, 0) - // Standard Error: 1 - .saturating_add(Weight::from_parts(633, 0).saturating_mul(n.into())) + // Minimum execution time: 2_052_000 picoseconds. + Weight::from_parts(2_330_454, 0) + // Standard Error: 2 + .saturating_add(Weight::from_parts(525, 0).saturating_mul(n.into())) .saturating_add(RocksDbWeight::get().writes(1_u64)) } fn seal_value_transferred() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 151_000 picoseconds. - Weight::from_parts(170_000, 0) + // Minimum execution time: 259_000 picoseconds. + Weight::from_parts(331_000, 0) } fn seal_minimum_balance() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 127_000 picoseconds. - Weight::from_parts(151_000, 0) + // Minimum execution time: 278_000 picoseconds. + Weight::from_parts(339_000, 0) } fn seal_return_data_size() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 112_000 picoseconds. - Weight::from_parts(149_000, 0) + // Minimum execution time: 272_000 picoseconds. + Weight::from_parts(326_000, 0) } fn seal_call_data_size() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 124_000 picoseconds. - Weight::from_parts(154_000, 0) + // Minimum execution time: 268_000 picoseconds. + Weight::from_parts(313_000, 0) } fn seal_gas_limit() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 331_000 picoseconds. - Weight::from_parts(370_000, 0) + // Minimum execution time: 436_000 picoseconds. + Weight::from_parts(509_000, 0) } fn seal_gas_price() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 137_000 picoseconds. - Weight::from_parts(163_000, 0) + // Minimum execution time: 262_000 picoseconds. + Weight::from_parts(317_000, 0) } fn seal_base_fee() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 130_000 picoseconds. - Weight::from_parts(154_000, 0) + // Minimum execution time: 289_000 picoseconds. + Weight::from_parts(347_000, 0) } fn seal_block_number() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 150_000 picoseconds. - Weight::from_parts(167_000, 0) + // Minimum execution time: 305_000 picoseconds. + Weight::from_parts(358_000, 0) } /// Storage: `Session::Validators` (r:1 w:0) /// Proof: `Session::Validators` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) @@ -1581,8 +1729,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `141` // Estimated: `1626` - // Minimum execution time: 19_205_000 picoseconds. - Weight::from_parts(19_687_000, 1626) + // Minimum execution time: 22_975_000 picoseconds. + Weight::from_parts(23_506_000, 1626) .saturating_add(RocksDbWeight::get().reads(1_u64)) } /// Storage: `System::BlockHash` (r:1 w:0) @@ -1591,60 +1739,60 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `30` // Estimated: `3495` - // Minimum execution time: 3_333_000 picoseconds. - Weight::from_parts(3_522_000, 3495) + // Minimum execution time: 3_631_000 picoseconds. + Weight::from_parts(3_829_000, 3495) .saturating_add(RocksDbWeight::get().reads(1_u64)) } fn seal_now() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 126_000 picoseconds. - Weight::from_parts(156_000, 0) + // Minimum execution time: 271_000 picoseconds. + Weight::from_parts(337_000, 0) } fn seal_weight_to_fee() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 1_364_000 picoseconds. - Weight::from_parts(1_477_000, 0) + // Minimum execution time: 1_603_000 picoseconds. + Weight::from_parts(1_712_000, 0) } - /// The range of component `n` is `[0, 262140]`. + /// The range of component `n` is `[0, 1048572]`. fn seal_copy_to_contract(n: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 309_000 picoseconds. - Weight::from_parts(603_516, 0) + // Minimum execution time: 433_000 picoseconds. + Weight::from_parts(460_000, 0) // Standard Error: 0 - .saturating_add(Weight::from_parts(294, 0).saturating_mul(n.into())) + .saturating_add(Weight::from_parts(203, 0).saturating_mul(n.into())) } fn seal_call_data_load() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 120_000 picoseconds. - Weight::from_parts(142_000, 0) + // Minimum execution time: 293_000 picoseconds. + Weight::from_parts(325_000, 0) } - /// The range of component `n` is `[0, 262144]`. + /// The range of component `n` is `[0, 1048576]`. fn seal_call_data_copy(n: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 121_000 picoseconds. - Weight::from_parts(125_420, 0) + // Minimum execution time: 269_000 picoseconds. + Weight::from_parts(806_378, 0) // Standard Error: 0 - .saturating_add(Weight::from_parts(149, 0).saturating_mul(n.into())) + .saturating_add(Weight::from_parts(112, 0).saturating_mul(n.into())) } - /// The range of component `n` is `[0, 262140]`. + /// The range of component `n` is `[0, 131072]`. fn seal_return(n: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 150_000 picoseconds. - Weight::from_parts(445_753, 0) + // Minimum execution time: 290_000 picoseconds. + Weight::from_parts(488_982, 0) // Standard Error: 0 - .saturating_add(Weight::from_parts(296, 0).saturating_mul(n.into())) + .saturating_add(Weight::from_parts(201, 0).saturating_mul(n.into())) } /// Storage: `Revive::OriginalAccount` (r:1 w:0) /// Proof: `Revive::OriginalAccount` (`max_values`: None, `max_size`: Some(52), added: 2527, mode: `Measured`) @@ -1658,10 +1806,10 @@ impl WeightInfo for () { /// Proof: `Revive::ImmutableDataOf` (`max_values`: None, `max_size`: Some(4118), added: 6593, mode: `Measured`) fn seal_terminate() -> Weight { // Proof Size summary in bytes: - // Measured: `585` - // Estimated: `4050` - // Minimum execution time: 16_990_000 picoseconds. - Weight::from_parts(17_538_000, 4050) + // Measured: `582` + // Estimated: `4047` + // Minimum execution time: 17_674_000 picoseconds. + Weight::from_parts(18_031_000, 4047) .saturating_add(RocksDbWeight::get().reads(3_u64)) .saturating_add(RocksDbWeight::get().writes(4_u64)) } @@ -1671,12 +1819,12 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 4_218_000 picoseconds. - Weight::from_parts(4_143_231, 0) - // Standard Error: 3_302 - .saturating_add(Weight::from_parts(235_681, 0).saturating_mul(t.into())) - // Standard Error: 36 - .saturating_add(Weight::from_parts(1_298, 0).saturating_mul(n.into())) + // Minimum execution time: 4_375_000 picoseconds. + Weight::from_parts(4_568_155, 0) + // Standard Error: 3_591 + .saturating_add(Weight::from_parts(223_460, 0).saturating_mul(t.into())) + // Standard Error: 39 + .saturating_add(Weight::from_parts(854, 0).saturating_mul(n.into())) } /// Storage: `Skipped::Metadata` (r:0 w:0) /// Proof: `Skipped::Metadata` (`max_values`: None, `max_size`: None, mode: `Measured`) @@ -1684,8 +1832,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `648` // Estimated: `648` - // Minimum execution time: 6_942_000 picoseconds. - Weight::from_parts(7_454_000, 648) + // Minimum execution time: 7_272_000 picoseconds. + Weight::from_parts(7_635_000, 648) .saturating_add(RocksDbWeight::get().reads(1_u64)) } /// Storage: `Skipped::Metadata` (r:0 w:0) @@ -1694,8 +1842,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `10658` // Estimated: `10658` - // Minimum execution time: 41_245_000 picoseconds. - Weight::from_parts(42_033_000, 10658) + // Minimum execution time: 41_207_000 picoseconds. + Weight::from_parts(41_863_000, 10658) .saturating_add(RocksDbWeight::get().reads(1_u64)) } /// Storage: `Skipped::Metadata` (r:0 w:0) @@ -1704,8 +1852,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `648` // Estimated: `648` - // Minimum execution time: 7_877_000 picoseconds. - Weight::from_parts(8_376_000, 648) + // Minimum execution time: 8_492_000 picoseconds. + Weight::from_parts(9_013_000, 648) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -1715,8 +1863,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `10658` // Estimated: `10658` - // Minimum execution time: 42_844_000 picoseconds. - Weight::from_parts(43_778_000, 10658) + // Minimum execution time: 42_398_000 picoseconds. + Weight::from_parts(44_113_000, 10658) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -1728,12 +1876,12 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `248 + o * (1 ±0)` // Estimated: `247 + o * (1 ±0)` - // Minimum execution time: 8_517_000 picoseconds. - Weight::from_parts(9_327_675, 247) - // Standard Error: 52 - .saturating_add(Weight::from_parts(407, 0).saturating_mul(n.into())) - // Standard Error: 52 - .saturating_add(Weight::from_parts(434, 0).saturating_mul(o.into())) + // Minimum execution time: 8_728_000 picoseconds. + Weight::from_parts(9_632_969, 247) + // Standard Error: 56 + .saturating_add(Weight::from_parts(556, 0).saturating_mul(n.into())) + // Standard Error: 56 + .saturating_add(Weight::from_parts(958, 0).saturating_mul(o.into())) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) .saturating_add(Weight::from_parts(0, 1).saturating_mul(o.into())) @@ -1745,10 +1893,10 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `248 + n * (1 ±0)` // Estimated: `247 + n * (1 ±0)` - // Minimum execution time: 8_144_000 picoseconds. - Weight::from_parts(9_105_918, 247) - // Standard Error: 72 - .saturating_add(Weight::from_parts(684, 0).saturating_mul(n.into())) + // Minimum execution time: 9_032_000 picoseconds. + Weight::from_parts(9_816_471, 247) + // Standard Error: 82 + .saturating_add(Weight::from_parts(582, 0).saturating_mul(n.into())) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) .saturating_add(Weight::from_parts(0, 1).saturating_mul(n.into())) @@ -1760,10 +1908,10 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `248 + n * (1 ±0)` // Estimated: `247 + n * (1 ±0)` - // Minimum execution time: 7_914_000 picoseconds. - Weight::from_parts(8_683_792, 247) - // Standard Error: 65 - .saturating_add(Weight::from_parts(1_267, 0).saturating_mul(n.into())) + // Minimum execution time: 8_313_000 picoseconds. + Weight::from_parts(9_381_907, 247) + // Standard Error: 91 + .saturating_add(Weight::from_parts(1_184, 0).saturating_mul(n.into())) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(Weight::from_parts(0, 1).saturating_mul(n.into())) } @@ -1774,10 +1922,10 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `248 + n * (1 ±0)` // Estimated: `247 + n * (1 ±0)` - // Minimum execution time: 7_287_000 picoseconds. - Weight::from_parts(8_027_630, 247) - // Standard Error: 56 - .saturating_add(Weight::from_parts(698, 0).saturating_mul(n.into())) + // Minimum execution time: 7_645_000 picoseconds. + Weight::from_parts(8_714_974, 247) + // Standard Error: 87 + .saturating_add(Weight::from_parts(717, 0).saturating_mul(n.into())) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(Weight::from_parts(0, 1).saturating_mul(n.into())) } @@ -1788,10 +1936,10 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `248 + n * (1 ±0)` // Estimated: `247 + n * (1 ±0)` - // Minimum execution time: 8_870_000 picoseconds. - Weight::from_parts(9_939_099, 247) - // Standard Error: 225 - .saturating_add(Weight::from_parts(832, 0).saturating_mul(n.into())) + // Minimum execution time: 9_388_000 picoseconds. + Weight::from_parts(10_430_193, 247) + // Standard Error: 77 + .saturating_add(Weight::from_parts(1_346, 0).saturating_mul(n.into())) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) .saturating_add(Weight::from_parts(0, 1).saturating_mul(n.into())) @@ -1800,36 +1948,36 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 1_306_000 picoseconds. - Weight::from_parts(1_404_000, 0) + // Minimum execution time: 1_597_000 picoseconds. + Weight::from_parts(1_691_000, 0) } fn set_transient_storage_full() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 1_689_000 picoseconds. - Weight::from_parts(1_811_000, 0) + // Minimum execution time: 2_005_000 picoseconds. + Weight::from_parts(2_129_000, 0) } fn get_transient_storage_empty() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 1_302_000 picoseconds. - Weight::from_parts(1_387_000, 0) + // Minimum execution time: 1_602_000 picoseconds. + Weight::from_parts(1_721_000, 0) } fn get_transient_storage_full() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 1_450_000 picoseconds. - Weight::from_parts(1_531_000, 0) + // Minimum execution time: 1_796_000 picoseconds. + Weight::from_parts(1_951_000, 0) } fn rollback_transient_storage() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 1_003_000 picoseconds. - Weight::from_parts(1_083_000, 0) + // Minimum execution time: 1_279_000 picoseconds. + Weight::from_parts(1_353_000, 0) } /// The range of component `n` is `[0, 416]`. /// The range of component `o` is `[0, 416]`. @@ -1837,258 +1985,266 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 2_147_000 picoseconds. - Weight::from_parts(2_400_128, 0) - // Standard Error: 15 - .saturating_add(Weight::from_parts(305, 0).saturating_mul(n.into())) - // Standard Error: 15 - .saturating_add(Weight::from_parts(275, 0).saturating_mul(o.into())) + // Minimum execution time: 2_407_000 picoseconds. + Weight::from_parts(2_715_278, 0) + // Standard Error: 18 + .saturating_add(Weight::from_parts(147, 0).saturating_mul(n.into())) + // Standard Error: 18 + .saturating_add(Weight::from_parts(292, 0).saturating_mul(o.into())) } /// The range of component `n` is `[0, 416]`. fn seal_clear_transient_storage(n: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 1_941_000 picoseconds. - Weight::from_parts(2_245_468, 0) - // Standard Error: 18 - .saturating_add(Weight::from_parts(407, 0).saturating_mul(n.into())) + // Minimum execution time: 2_140_000 picoseconds. + Weight::from_parts(2_612_392, 0) + // Standard Error: 25 + .saturating_add(Weight::from_parts(305, 0).saturating_mul(n.into())) } /// The range of component `n` is `[0, 416]`. fn seal_get_transient_storage(n: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 1_738_000 picoseconds. - Weight::from_parts(1_944_507, 0) - // Standard Error: 16 - .saturating_add(Weight::from_parts(275, 0).saturating_mul(n.into())) + // Minimum execution time: 2_034_000 picoseconds. + Weight::from_parts(2_357_344, 0) + // Standard Error: 21 + .saturating_add(Weight::from_parts(276, 0).saturating_mul(n.into())) } /// The range of component `n` is `[0, 416]`. fn seal_contains_transient_storage(n: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 1_521_000 picoseconds. - Weight::from_parts(1_725_877, 0) - // Standard Error: 13 - .saturating_add(Weight::from_parts(184, 0).saturating_mul(n.into())) + // Minimum execution time: 1_888_000 picoseconds. + Weight::from_parts(2_137_193, 0) + // Standard Error: 16 + .saturating_add(Weight::from_parts(172, 0).saturating_mul(n.into())) } /// The range of component `n` is `[0, 416]`. fn seal_take_transient_storage(_n: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 2_366_000 picoseconds. - Weight::from_parts(2_590_846, 0) + // Minimum execution time: 2_733_000 picoseconds. + Weight::from_parts(3_004_772, 0) } /// Storage: `Revive::OriginalAccount` (r:1 w:0) /// Proof: `Revive::OriginalAccount` (`max_values`: None, `max_size`: Some(52), added: 2527, mode: `Measured`) - /// Storage: `Revive::ContractInfoOf` (r:1 w:0) - /// Proof: `Revive::ContractInfoOf` (`max_values`: None, `max_size`: Some(242), added: 2717, mode: `Measured`) + /// Storage: `Revive::AccountInfoOf` (r:1 w:1) + /// Proof: `Revive::AccountInfoOf` (`max_values`: None, `max_size`: Some(247), added: 2722, mode: `Measured`) /// Storage: `Revive::CodeInfoOf` (r:1 w:0) /// Proof: `Revive::CodeInfoOf` (`max_values`: None, `max_size`: Some(96), added: 2571, mode: `Measured`) /// Storage: `Revive::PristineCode` (r:1 w:0) - /// Proof: `Revive::PristineCode` (`max_values`: None, `max_size`: Some(262180), added: 264655, mode: `Measured`) - /// Storage: `System::Account` (r:1 w:0) + /// Proof: `Revive::PristineCode` (`max_values`: None, `max_size`: Some(1048612), added: 1051087, mode: `Measured`) + /// Storage: `System::Account` (r:1 w:1) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) /// The range of component `t` is `[0, 1]`. - /// The range of component `i` is `[0, 262144]`. - fn seal_call(t: u32, i: u32, ) -> Weight { - // Proof Size summary in bytes: - // Measured: `1545 + t * (206 ±0)` - // Estimated: `5010 + t * (2608 ±0)` - // Minimum execution time: 34_508_000 picoseconds. - Weight::from_parts(35_724_702, 5010) - // Standard Error: 42_504 - .saturating_add(Weight::from_parts(5_295_834, 0).saturating_mul(t.into())) + /// The range of component `d` is `[0, 1]`. + /// The range of component `i` is `[0, 1048576]`. + fn seal_call(t: u32, d: u32, i: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `2005` + // Estimated: `5470` + // Minimum execution time: 91_390_000 picoseconds. + Weight::from_parts(71_229_693, 5470) + // Standard Error: 146_616 + .saturating_add(Weight::from_parts(19_125_819, 0).saturating_mul(t.into())) + // Standard Error: 146_616 + .saturating_add(Weight::from_parts(26_490_547, 0).saturating_mul(d.into())) // Standard Error: 0 - .saturating_add(Weight::from_parts(2, 0).saturating_mul(i.into())) - .saturating_add(RocksDbWeight::get().reads(4_u64)) - .saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(t.into()))) + .saturating_add(Weight::from_parts(4, 0).saturating_mul(i.into())) + .saturating_add(RocksDbWeight::get().reads(5_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) - .saturating_add(Weight::from_parts(0, 2608).saturating_mul(t.into())) + .saturating_add(RocksDbWeight::get().writes((1_u64).saturating_mul(t.into()))) } - /// Storage: `Revive::ContractInfoOf` (r:1 w:1) - /// Proof: `Revive::ContractInfoOf` (`max_values`: None, `max_size`: Some(242), added: 2717, mode: `Measured`) + /// Storage: `Revive::AccountInfoOf` (r:1 w:1) + /// Proof: `Revive::AccountInfoOf` (`max_values`: None, `max_size`: Some(247), added: 2722, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) /// The range of component `d` is `[0, 1]`. - /// The range of component `i` is `[0, 262144]`. + /// The range of component `i` is `[0, 130972]`. fn seal_call_precompile(d: u32, i: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `0 + d * (453 ±0)` - // Estimated: `1959 + d * (1959 ±0)` - // Minimum execution time: 19_412_000 picoseconds. - Weight::from_parts(3_906_222, 1959) - // Standard Error: 378_943 - .saturating_add(Weight::from_parts(16_405_804, 0).saturating_mul(d.into())) - // Standard Error: 2 - .saturating_add(Weight::from_parts(1_205, 0).saturating_mul(i.into())) + // Measured: `366 + d * (212 ±0)` + // Estimated: `2021 + d * (2021 ±0)` + // Minimum execution time: 24_210_000 picoseconds. + Weight::from_parts(11_783_977, 2021) + // Standard Error: 49_916 + .saturating_add(Weight::from_parts(14_132_066, 0).saturating_mul(d.into())) + // Standard Error: 0 + .saturating_add(Weight::from_parts(325, 0).saturating_mul(i.into())) .saturating_add(RocksDbWeight::get().reads((2_u64).saturating_mul(d.into()))) .saturating_add(RocksDbWeight::get().writes((1_u64).saturating_mul(d.into()))) - .saturating_add(Weight::from_parts(0, 1959).saturating_mul(d.into())) + .saturating_add(Weight::from_parts(0, 2021).saturating_mul(d.into())) } - /// Storage: `Revive::ContractInfoOf` (r:1 w:0) - /// Proof: `Revive::ContractInfoOf` (`max_values`: None, `max_size`: Some(242), added: 2717, mode: `Measured`) + /// Storage: `Revive::AccountInfoOf` (r:1 w:0) + /// Proof: `Revive::AccountInfoOf` (`max_values`: None, `max_size`: Some(247), added: 2722, mode: `Measured`) /// Storage: `Revive::CodeInfoOf` (r:1 w:0) /// Proof: `Revive::CodeInfoOf` (`max_values`: None, `max_size`: Some(96), added: 2571, mode: `Measured`) /// Storage: `Revive::PristineCode` (r:1 w:0) - /// Proof: `Revive::PristineCode` (`max_values`: None, `max_size`: Some(262180), added: 264655, mode: `Measured`) + /// Proof: `Revive::PristineCode` (`max_values`: None, `max_size`: Some(1048612), added: 1051087, mode: `Measured`) fn seal_delegate_call() -> Weight { // Proof Size summary in bytes: - // Measured: `1236` - // Estimated: `4701` - // Minimum execution time: 28_834_000 picoseconds. - Weight::from_parts(30_072_000, 4701) + // Measured: `1362` + // Estimated: `4827` + // Minimum execution time: 31_948_000 picoseconds. + Weight::from_parts(33_936_000, 4827) .saturating_add(RocksDbWeight::get().reads(3_u64)) } /// Storage: `Revive::CodeInfoOf` (r:1 w:1) /// Proof: `Revive::CodeInfoOf` (`max_values`: None, `max_size`: Some(96), added: 2571, mode: `Measured`) /// Storage: `Revive::PristineCode` (r:1 w:0) - /// Proof: `Revive::PristineCode` (`max_values`: None, `max_size`: Some(262180), added: 264655, mode: `Measured`) - /// Storage: `Revive::ContractInfoOf` (r:1 w:1) - /// Proof: `Revive::ContractInfoOf` (`max_values`: None, `max_size`: Some(242), added: 2717, mode: `Measured`) + /// Proof: `Revive::PristineCode` (`max_values`: None, `max_size`: Some(1048612), added: 1051087, mode: `Measured`) + /// Storage: `Revive::AccountInfoOf` (r:1 w:1) + /// Proof: `Revive::AccountInfoOf` (`max_values`: None, `max_size`: Some(247), added: 2722, mode: `Measured`) /// Storage: `System::Account` (r:1 w:1) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) - /// The range of component `i` is `[0, 262144]`. - fn seal_instantiate(i: u32, ) -> Weight { - // Proof Size summary in bytes: - // Measured: `1260` - // Estimated: `4728` - // Minimum execution time: 112_787_000 picoseconds. - Weight::from_parts(105_258_744, 4728) - // Standard Error: 10 - .saturating_add(Weight::from_parts(4_163, 0).saturating_mul(i.into())) + /// The range of component `t` is `[0, 1]`. + /// The range of component `d` is `[0, 1]`. + /// The range of component `i` is `[0, 131072]`. + fn seal_instantiate(t: u32, d: u32, i: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `1417` + // Estimated: `4876` + // Minimum execution time: 150_079_000 picoseconds. + Weight::from_parts(104_920_700, 4876) + // Standard Error: 456_076 + .saturating_add(Weight::from_parts(20_263_777, 0).saturating_mul(t.into())) + // Standard Error: 456_076 + .saturating_add(Weight::from_parts(30_617_352, 0).saturating_mul(d.into())) + // Standard Error: 5 + .saturating_add(Weight::from_parts(3_949, 0).saturating_mul(i.into())) .saturating_add(RocksDbWeight::get().reads(4_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) } - /// The range of component `n` is `[0, 262144]`. + /// The range of component `n` is `[0, 1048576]`. fn sha2_256(n: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 792_000 picoseconds. - Weight::from_parts(4_505_628, 0) - // Standard Error: 3 - .saturating_add(Weight::from_parts(1_285, 0).saturating_mul(n.into())) + // Minimum execution time: 1_165_000 picoseconds. + Weight::from_parts(9_566_786, 0) + // Standard Error: 0 + .saturating_add(Weight::from_parts(1_251, 0).saturating_mul(n.into())) } - /// The range of component `n` is `[0, 262144]`. + /// The range of component `n` is `[0, 1048576]`. fn identity(n: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 300_000 picoseconds. - Weight::from_parts(468_743, 0) + // Minimum execution time: 727_000 picoseconds. + Weight::from_parts(868_990, 0) // Standard Error: 0 - .saturating_add(Weight::from_parts(148, 0).saturating_mul(n.into())) + .saturating_add(Weight::from_parts(112, 0).saturating_mul(n.into())) } - /// The range of component `n` is `[0, 262144]`. + /// The range of component `n` is `[0, 1048576]`. fn ripemd_160(n: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 744_000 picoseconds. - Weight::from_parts(771_000, 0) - // Standard Error: 1 - .saturating_add(Weight::from_parts(3_928, 0).saturating_mul(n.into())) + // Minimum execution time: 1_228_000 picoseconds. + Weight::from_parts(8_112_183, 0) + // Standard Error: 0 + .saturating_add(Weight::from_parts(3_718, 0).saturating_mul(n.into())) } - /// The range of component `n` is `[0, 262144]`. + /// The range of component `n` is `[0, 1048576]`. fn seal_hash_keccak_256(n: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 1_002_000 picoseconds. - Weight::from_parts(3_889_121, 0) - // Standard Error: 3 - .saturating_add(Weight::from_parts(3_666, 0).saturating_mul(n.into())) + // Minimum execution time: 1_142_000 picoseconds. + Weight::from_parts(12_135_609, 0) + // Standard Error: 1 + .saturating_add(Weight::from_parts(3_539, 0).saturating_mul(n.into())) } - /// The range of component `n` is `[0, 262144]`. - fn seal_hash_blake2_256(n: u32, ) -> Weight { + /// The range of component `n` is `[0, 1048576]`. + fn hash_blake2_256(n: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 562_000 picoseconds. - Weight::from_parts(3_823_066, 0) - // Standard Error: 3 - .saturating_add(Weight::from_parts(1_569, 0).saturating_mul(n.into())) + // Minimum execution time: 1_520_000 picoseconds. + Weight::from_parts(10_863_970, 0) + // Standard Error: 0 + .saturating_add(Weight::from_parts(1_405, 0).saturating_mul(n.into())) } - /// The range of component `n` is `[0, 262144]`. + /// The range of component `n` is `[0, 1048576]`. fn seal_hash_blake2_128(n: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 543_000 picoseconds. - Weight::from_parts(3_582_133, 0) - // Standard Error: 2 - .saturating_add(Weight::from_parts(1_576, 0).saturating_mul(n.into())) + // Minimum execution time: 713_000 picoseconds. + Weight::from_parts(5_972_288, 0) + // Standard Error: 0 + .saturating_add(Weight::from_parts(1_498, 0).saturating_mul(n.into())) } - /// The range of component `n` is `[0, 261889]`. + /// The range of component `n` is `[0, 1048321]`. fn seal_sr25519_verify(n: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 42_702_000 picoseconds. - Weight::from_parts(30_839_817, 0) - // Standard Error: 10 - .saturating_add(Weight::from_parts(5_086, 0).saturating_mul(n.into())) + // Minimum execution time: 42_872_000 picoseconds. + Weight::from_parts(83_548_865, 0) + // Standard Error: 3 + .saturating_add(Weight::from_parts(4_865, 0).saturating_mul(n.into())) } fn ecdsa_recover() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 44_770_000 picoseconds. - Weight::from_parts(45_791_000, 0) + // Minimum execution time: 45_827_000 picoseconds. + Weight::from_parts(46_613_000, 0) } fn bn128_add() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 15_705_000 picoseconds. - Weight::from_parts(16_885_000, 0) + // Minimum execution time: 14_422_000 picoseconds. + Weight::from_parts(15_942_000, 0) } fn bn128_mul() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 1_018_103_000 picoseconds. - Weight::from_parts(1_023_315_000, 0) + // Minimum execution time: 974_593_000 picoseconds. + Weight::from_parts(980_966_000, 0) } /// The range of component `n` is `[0, 20]`. fn bn128_pairing(n: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 378_000 picoseconds. - Weight::from_parts(5_119_381_361, 0) - // Standard Error: 10_821_771 - .saturating_add(Weight::from_parts(6_202_434_383, 0).saturating_mul(n.into())) + // Minimum execution time: 851_000 picoseconds. + Weight::from_parts(4_760_087_459, 0) + // Standard Error: 10_485_749 + .saturating_add(Weight::from_parts(5_940_723_809, 0).saturating_mul(n.into())) } /// The range of component `n` is `[0, 1200]`. fn blake2f(n: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 435_000 picoseconds. - Weight::from_parts(658_540, 0) - // Standard Error: 6 - .saturating_add(Weight::from_parts(22_679, 0).saturating_mul(n.into())) + // Minimum execution time: 953_000 picoseconds. + Weight::from_parts(1_258_163, 0) + // Standard Error: 50 + .saturating_add(Weight::from_parts(28_977, 0).saturating_mul(n.into())) } fn seal_ecdsa_to_eth_address() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 12_639_000 picoseconds. - Weight::from_parts(12_782_000, 0) + // Minimum execution time: 13_049_000 picoseconds. + Weight::from_parts(13_232_000, 0) } /// Storage: `Revive::CodeInfoOf` (r:1 w:1) /// Proof: `Revive::CodeInfoOf` (`max_values`: None, `max_size`: Some(96), added: 2571, mode: `Measured`) fn seal_set_code_hash() -> Weight { // Proof Size summary in bytes: - // Measured: `300` - // Estimated: `3765` - // Minimum execution time: 12_210_000 picoseconds. - Weight::from_parts(12_747_000, 3765) + // Measured: `296` + // Estimated: `3761` + // Minimum execution time: 10_342_000 picoseconds. + Weight::from_parts(10_818_000, 3761) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -2097,19 +2253,32 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 11_244_000 picoseconds. - Weight::from_parts(48_207_913, 0) - // Standard Error: 495 - .saturating_add(Weight::from_parts(125_133, 0).saturating_mul(r.into())) + // Minimum execution time: 11_081_000 picoseconds. + Weight::from_parts(39_209_404, 0) + // Standard Error: 395 + .saturating_add(Weight::from_parts(106_585, 0).saturating_mul(r.into())) } /// The range of component `r` is `[0, 100000]`. fn instr_empty_loop(r: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 2_776_000 picoseconds. - Weight::from_parts(6_412_428, 0) - // Standard Error: 17 - .saturating_add(Weight::from_parts(72_988, 0).saturating_mul(r.into())) + // Minimum execution time: 3_146_000 picoseconds. + Weight::from_parts(4_731_872, 0) + // Standard Error: 13 + .saturating_add(Weight::from_parts(73_452, 0).saturating_mul(r.into())) + } + /// Storage: UNKNOWN KEY `0x735f040a5d490f1107ad9c56f5ca00d2060e99e5378e562537cf3bc983e17b91` (r:2 w:1) + /// Proof: UNKNOWN KEY `0x735f040a5d490f1107ad9c56f5ca00d2060e99e5378e562537cf3bc983e17b91` (r:2 w:1) + /// Storage: `Revive::AccountInfoOf` (r:0 w:1) + /// Proof: `Revive::AccountInfoOf` (`max_values`: None, `max_size`: Some(247), added: 2722, mode: `MaxEncodedLen`) + fn v1_migration_step() -> Weight { + // Proof Size summary in bytes: + // Measured: `316` + // Estimated: `6256` + // Minimum execution time: 12_136_000 picoseconds. + Weight::from_parts(12_668_000, 6256) + .saturating_add(RocksDbWeight::get().reads(2_u64)) + .saturating_add(RocksDbWeight::get().writes(2_u64)) } } diff --git a/substrate/frame/revive/uapi/Cargo.toml b/substrate/frame/revive/uapi/Cargo.toml index 52eb2287b5a9e..4e6dad1393c7f 100644 --- a/substrate/frame/revive/uapi/Cargo.toml +++ b/substrate/frame/revive/uapi/Cargo.toml @@ -22,7 +22,7 @@ pallet-revive-proc-macro.workspace = true scale-info = { features = ["derive"], optional = true, workspace = true } [target.'cfg(target_arch = "riscv64")'.dependencies] -polkavm-derive = { version = "0.26.0" } +polkavm-derive = { version = "0.27.0" } [features] default = ["scale"] diff --git a/substrate/frame/revive/uapi/src/host.rs b/substrate/frame/revive/uapi/src/host.rs index 7b11e12990d2e..f87fb1a54b887 100644 --- a/substrate/frame/revive/uapi/src/host.rs +++ b/substrate/frame/revive/uapi/src/host.rs @@ -539,20 +539,6 @@ pub trait HostFn: private::Sealed { #[unstable_hostfn] fn ecdsa_to_eth_address(pubkey: &[u8; 33], output: &mut [u8; 20]) -> Result; - /// Computes the blake2_256 32-bit hash on the given input buffer. - /// - /// - The `input` and `output` buffer may overlap. - /// - The output buffer is expected to hold at least 32 bits. - /// - It is the callers responsibility to provide an output buffer that is large enough to hold - /// the expected amount of bytes returned by the hash function. - /// - /// # Parameters - /// */ - /// - `input`: The input data buffer. - /// - `output`: The output buffer to write the hash result to. - #[unstable_hostfn] - fn hash_blake2_256(input: &[u8], output: &mut [u8; 32]); - /// Computes the blake2_128 16-bit hash on the given input buffer. /// /// - The `input` and `output` buffer may overlap. diff --git a/substrate/frame/revive/uapi/src/host/riscv64.rs b/substrate/frame/revive/uapi/src/host/riscv64.rs index 4ca1c27c1732f..adfd8f2789594 100644 --- a/substrate/frame/revive/uapi/src/host/riscv64.rs +++ b/substrate/frame/revive/uapi/src/host/riscv64.rs @@ -127,7 +127,6 @@ mod sys { pub fn block_hash(block_number_ptr: *const u8, out_ptr: *mut u8); pub fn block_author(out_ptr: *mut u8); pub fn hash_keccak_256(input_ptr: *const u8, input_len: u32, out_ptr: *mut u8); - pub fn hash_blake2_256(input_ptr: *const u8, input_len: u32, out_ptr: *mut u8); pub fn hash_blake2_128(input_ptr: *const u8, input_len: u32, out_ptr: *mut u8); pub fn call_chain_extension( id: u32, @@ -515,11 +514,6 @@ impl HostFn for HostFnImpl { ret_code.into() } - #[unstable_hostfn] - fn hash_blake2_256(input: &[u8], output: &mut [u8; 32]) { - unsafe { sys::hash_blake2_256(input.as_ptr(), input.len() as u32, output.as_mut_ptr()) } - } - #[unstable_hostfn] fn hash_blake2_128(input: &[u8], output: &mut [u8; 16]) { unsafe { sys::hash_blake2_128(input.as_ptr(), input.len() as u32, output.as_mut_ptr()) }