From fadb3965d75551a002cddebeb27af8b8cb7ae875 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexandre=20Bald=C3=A9?= Date: Thu, 12 Dec 2024 21:17:47 +0000 Subject: [PATCH 01/34] Fix typo in integration test --- .../tests/people/people-westend/src/tests/governance.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cumulus/parachains/integration-tests/emulated/tests/people/people-westend/src/tests/governance.rs b/cumulus/parachains/integration-tests/emulated/tests/people/people-westend/src/tests/governance.rs index ea438f80552e..3b1779e40b60 100644 --- a/cumulus/parachains/integration-tests/emulated/tests/people/people-westend/src/tests/governance.rs +++ b/cumulus/parachains/integration-tests/emulated/tests/people/people-westend/src/tests/governance.rs @@ -396,7 +396,7 @@ fn relay_commands_add_remove_username_authority() { ); }); - // Now, remove the username authority with another priviledged XCM call. + // Now, remove the username authority with another privileged XCM call. Westend::execute_with(|| { type Runtime = ::Runtime; type RuntimeCall = ::RuntimeCall; From db02307a23a89c6741c82525d0d58b3686bb223d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexandre=20Bald=C3=A9?= Date: Thu, 12 Dec 2024 21:18:02 +0000 Subject: [PATCH 02/34] Add unit tests to current behavior of `GasMeter.nested` --- substrate/frame/revive/src/gas.rs | 47 +++++++++++++++++++++++++++---- 1 file changed, 42 insertions(+), 5 deletions(-) diff --git a/substrate/frame/revive/src/gas.rs b/substrate/frame/revive/src/gas.rs index 9aad84e69201..4609f4dcac18 100644 --- a/substrate/frame/revive/src/gas.rs +++ b/substrate/frame/revive/src/gas.rs @@ -168,11 +168,7 @@ impl GasMeter { } } - /// Create a new gas meter by removing gas from the current meter. - /// - /// # Note - /// - /// Passing `0` as amount is interpreted as "all remaining gas". + /// Create a new gas meter for a nested call by removing gas from the current meter. pub fn nested(&mut self, amount: Weight) -> Self { let amount = Weight::from_parts( if amount.ref_time().is_zero() { @@ -392,6 +388,47 @@ mod tests { assert!(gas_meter.charge(SimpleToken(1)).is_err()); } + #[test] + /// Currently, passing a `Weight` of 0 to `nested` will consume all of the meter's current gas. + fn nested_zero_gas_requested() { + let test_weight = 50000.into(); + let mut gas_meter = GasMeter::::new(test_weight); + let gas_for_nested_call = gas_meter.nested(0.into()); + + assert_eq!(gas_meter.gas_left(), 0.into()); + assert_eq!(gas_for_nested_call.gas_left(), test_weight) + } + + #[test] + fn nested_some_gas_requested() { + let test_weight = 50000.into(); + let mut gas_meter = GasMeter::::new(test_weight); + let gas_for_nested_call = gas_meter.nested(10000.into()); + + assert_eq!(gas_meter.gas_left(), 40000.into()); + assert_eq!(gas_for_nested_call.gas_left(), 10000.into()) + } + + #[test] + fn nested_all_gas_requested() { + let test_weight = Weight::from_parts(50000, 50000); + let mut gas_meter = GasMeter::::new(test_weight); + let gas_for_nested_call = gas_meter.nested(test_weight); + + assert_eq!(gas_meter.gas_left(), Weight::from_parts(0, 0)); + assert_eq!(gas_for_nested_call.gas_left(), test_weight) + } + + #[test] + fn nested_excess_gas_requested() { + let test_weight = Weight::from_parts(50000, 50000); + let mut gas_meter = GasMeter::::new(test_weight); + let gas_for_nested_call = gas_meter.nested(test_weight + 10000.into()); + + assert_eq!(gas_meter.gas_left(), Weight::from_parts(0, 0)); + assert_eq!(gas_for_nested_call.gas_left(), test_weight) + } + // Make sure that the gas meter does not charge in case of overcharge #[test] fn overcharge_does_not_charge() { From 2c2a7f77d71084057a977502c7711740e85f1ee9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexandre=20Bald=C3=A9?= Date: Fri, 13 Dec 2024 18:22:19 +0000 Subject: [PATCH 03/34] Add unit tests to simplest behavior of `RawMeter` --- substrate/frame/revive/src/storage/meter.rs | 40 +++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/substrate/frame/revive/src/storage/meter.rs b/substrate/frame/revive/src/storage/meter.rs index 6eddf048be98..7ef80ce9e6b7 100644 --- a/substrate/frame/revive/src/storage/meter.rs +++ b/substrate/frame/revive/src/storage/meter.rs @@ -724,6 +724,46 @@ mod tests { ) } + #[test] + fn nested_zero_limit_requested() { + clear_ext(); + + let meter = TestMeter::new(&Origin::from_account_id(ALICE), 1_000, 0).unwrap(); + assert_eq!(meter.available(), 1_000); + let nested0 = meter.nested(BalanceOf::::zero()); + assert_eq!(nested0.available(), 1_000); + } + + #[test] + fn nested_some_limit_requested() { + clear_ext(); + + let meter = TestMeter::new(&Origin::from_account_id(ALICE), 1_000, 0).unwrap(); + assert_eq!(meter.available(), 1_000); + let nested0 = meter.nested(500); + assert_eq!(nested0.available(), 500); + } + + #[test] + fn nested_all_limit_requested() { + clear_ext(); + + let meter = TestMeter::new(&Origin::from_account_id(ALICE), 1_000, 0).unwrap(); + assert_eq!(meter.available(), 1_000); + let nested0 = meter.nested(1_000); + assert_eq!(nested0.available(), 1_000); + } + + #[test] + fn nested_over_limit_requested() { + clear_ext(); + + let meter = TestMeter::new(&Origin::from_account_id(ALICE), 1_000, 0).unwrap(); + assert_eq!(meter.available(), 1_000); + let nested0 = meter.nested(2_000); + assert_eq!(nested0.available(), 1_000); + } + #[test] fn empty_charge_works() { clear_ext(); From 11dd382abd27e4a9cb9cfe357ee6803dc086e048 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexandre=20Bald=C3=A9?= Date: Fri, 13 Dec 2024 18:27:53 +0000 Subject: [PATCH 04/34] Add PRDoc --- prdoc/pr_6890.prdoc | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 prdoc/pr_6890.prdoc diff --git a/prdoc/pr_6890.prdoc b/prdoc/pr_6890.prdoc new file mode 100644 index 000000000000..286d89222723 --- /dev/null +++ b/prdoc/pr_6890.prdoc @@ -0,0 +1,13 @@ +# 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: Bound resources for nested EVM contract calls + +doc: + - audience: [ Runtime Dev, Runtime User ] + description: | + Implementation of EIP-150 for `pallet-revive`-based EVM contracts. + +crates: + - name: pallet-revive + bump: minor From 5a8312add50547042c5f970da1ed6cef5b116d57 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexandre=20Bald=C3=A9?= Date: Fri, 13 Dec 2024 21:05:53 +0000 Subject: [PATCH 05/34] Limit gas for nested calls per EIP-150 --- substrate/frame/revive/src/exec.rs | 4 ++-- substrate/frame/revive/src/gas.rs | 20 +++++--------------- 2 files changed, 7 insertions(+), 17 deletions(-) diff --git a/substrate/frame/revive/src/exec.rs b/substrate/frame/revive/src/exec.rs index b6f0e3ae1a81..013102047eca 100644 --- a/substrate/frame/revive/src/exec.rs +++ b/substrate/frame/revive/src/exec.rs @@ -53,7 +53,7 @@ use sp_core::{ }; use sp_io::{crypto::secp256k1_ecdsa_recover_compressed, hashing::blake2_256}; use sp_runtime::{ - traits::{BadOrigin, Convert, Dispatchable, Saturating, Zero}, + traits::{BadOrigin, Bounded, Convert, Dispatchable, Saturating, Zero}, DispatchError, SaturatedConversion, }; @@ -885,7 +885,7 @@ where args, value, gas_meter, - Weight::zero(), + Weight::max_value(), storage_meter, BalanceOf::::zero(), false, diff --git a/substrate/frame/revive/src/gas.rs b/substrate/frame/revive/src/gas.rs index 4609f4dcac18..e1c611e20fb6 100644 --- a/substrate/frame/revive/src/gas.rs +++ b/substrate/frame/revive/src/gas.rs @@ -170,21 +170,11 @@ impl GasMeter { /// Create a new gas meter for a nested call by removing gas from the current meter. pub fn nested(&mut self, amount: Weight) -> Self { - let amount = Weight::from_parts( - if amount.ref_time().is_zero() { - self.gas_left().ref_time() - } else { - amount.ref_time() - }, - if amount.proof_size().is_zero() { - self.gas_left().proof_size() - } else { - amount.proof_size() - }, - ) - .min(self.gas_left); - self.gas_left -= amount; - GasMeter::new(amount) + // The reduction to 63/64 is to emulate EIP-150 + // https://github.com/ethereum/EIPs/blob/master/EIPS/eip-150.md + let amt = amount.min(self.gas_left - self.gas_left / 64); + self.gas_left -= amt; + GasMeter::new(amt) } /// Absorb the remaining gas of a nested meter after we are done using it. From a7781c4acd22b1bee08d935b0cb6fa8d32f6864f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexandre=20Bald=C3=A9?= Date: Fri, 13 Dec 2024 21:24:55 +0000 Subject: [PATCH 06/34] Reflect EIP-150 change in some unit tests --- substrate/frame/revive/src/gas.rs | 19 +++++++++++-------- substrate/frame/revive/src/primitives.rs | 2 +- 2 files changed, 12 insertions(+), 9 deletions(-) diff --git a/substrate/frame/revive/src/gas.rs b/substrate/frame/revive/src/gas.rs index e1c611e20fb6..6f20cf54edad 100644 --- a/substrate/frame/revive/src/gas.rs +++ b/substrate/frame/revive/src/gas.rs @@ -22,7 +22,7 @@ use frame_support::{ weights::Weight, DefaultNoBound, }; -use sp_runtime::{traits::Zero, DispatchError}; +use sp_runtime::DispatchError; #[cfg(test)] use std::{any::Any, fmt::Debug}; @@ -379,14 +379,15 @@ mod tests { } #[test] - /// Currently, passing a `Weight` of 0 to `nested` will consume all of the meter's current gas. + /// Currently, passing a `Weight` of 0 to `nested` will consume all of the meter's current gas, + /// which with EIP-150 is limited to 63/64ths of the total. fn nested_zero_gas_requested() { let test_weight = 50000.into(); let mut gas_meter = GasMeter::::new(test_weight); let gas_for_nested_call = gas_meter.nested(0.into()); - assert_eq!(gas_meter.gas_left(), 0.into()); - assert_eq!(gas_for_nested_call.gas_left(), test_weight) + assert_eq!(gas_meter.gas_left(), 781.into()); + assert_eq!(gas_for_nested_call.gas_left(), 49219.into()) } #[test] @@ -405,8 +406,10 @@ mod tests { let mut gas_meter = GasMeter::::new(test_weight); let gas_for_nested_call = gas_meter.nested(test_weight); - assert_eq!(gas_meter.gas_left(), Weight::from_parts(0, 0)); - assert_eq!(gas_for_nested_call.gas_left(), test_weight) + // With EIP-150, it is not possible for subcalls to consume all available gas. + // They are limited to 63/64ths; 50000 / 64 ≈ 781 + assert_eq!(gas_meter.gas_left(), Weight::from_parts(781, 781)); + assert_eq!(gas_for_nested_call.gas_left(), 49219.into()) } #[test] @@ -415,8 +418,8 @@ mod tests { let mut gas_meter = GasMeter::::new(test_weight); let gas_for_nested_call = gas_meter.nested(test_weight + 10000.into()); - assert_eq!(gas_meter.gas_left(), Weight::from_parts(0, 0)); - assert_eq!(gas_for_nested_call.gas_left(), test_weight) + assert_eq!(gas_meter.gas_left(), Weight::from_parts(781, 781)); + assert_eq!(gas_for_nested_call.gas_left(), 49219.into()) } // Make sure that the gas meter does not charge in case of overcharge diff --git a/substrate/frame/revive/src/primitives.rs b/substrate/frame/revive/src/primitives.rs index a7127f812b4b..452d2c8a3067 100644 --- a/substrate/frame/revive/src/primitives.rs +++ b/substrate/frame/revive/src/primitives.rs @@ -72,7 +72,7 @@ pub struct ContractResult { /// /// # Note /// - /// This can only different from [`Self::gas_consumed`] when weight pre charging + /// This can only be different from [`Self::gas_consumed`] when weight pre charging /// is used. Currently, only `seal_call_runtime` makes use of pre charging. /// Additionally, any `seal_call` or `seal_instantiate` makes use of pre-charging /// when a non-zero `gas_limit` argument is supplied. From b6e7290a65721795246907f841a5633a200bb256 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexandre=20Bald=C3=A9?= Date: Fri, 13 Dec 2024 21:38:58 +0000 Subject: [PATCH 07/34] Address missing EIP-150 fix in one gas meter unit test --- substrate/frame/revive/src/gas.rs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/substrate/frame/revive/src/gas.rs b/substrate/frame/revive/src/gas.rs index 6f20cf54edad..e360a4ad6b2f 100644 --- a/substrate/frame/revive/src/gas.rs +++ b/substrate/frame/revive/src/gas.rs @@ -379,15 +379,16 @@ mod tests { } #[test] - /// Currently, passing a `Weight` of 0 to `nested` will consume all of the meter's current gas, - /// which with EIP-150 is limited to 63/64ths of the total. + /// Previously, passing a `Weight` of 0 to `nested` would consume all of the meter's current gas. + /// + /// Now, a `Weight` of 0 means no gas for the nested call. fn nested_zero_gas_requested() { let test_weight = 50000.into(); let mut gas_meter = GasMeter::::new(test_weight); let gas_for_nested_call = gas_meter.nested(0.into()); - assert_eq!(gas_meter.gas_left(), 781.into()); - assert_eq!(gas_for_nested_call.gas_left(), 49219.into()) + assert_eq!(gas_meter.gas_left(), 50000.into()); + assert_eq!(gas_for_nested_call.gas_left(), 0.into()) } #[test] From 8d7be23fa21e79336b304538f2e76635433f2f17 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexandre=20Bald=C3=A9?= Date: Fri, 13 Dec 2024 22:10:19 +0000 Subject: [PATCH 08/34] Apply EIP-150 to storage metering Also, a limit of 0 when determining a nested call's metering limit would mean it was free to use all of the callee's resources. Now, a limit of 0 means that the nested call will have an empty storage meter. --- substrate/frame/revive/src/exec.rs | 2 +- substrate/frame/revive/src/storage/meter.rs | 14 +++++++------- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/substrate/frame/revive/src/exec.rs b/substrate/frame/revive/src/exec.rs index 013102047eca..5e1474859d8d 100644 --- a/substrate/frame/revive/src/exec.rs +++ b/substrate/frame/revive/src/exec.rs @@ -887,7 +887,7 @@ where gas_meter, Weight::max_value(), storage_meter, - BalanceOf::::zero(), + BalanceOf::::max_value(), false, true, )? diff --git a/substrate/frame/revive/src/storage/meter.rs b/substrate/frame/revive/src/storage/meter.rs index 7ef80ce9e6b7..27113cf3a1a4 100644 --- a/substrate/frame/revive/src/storage/meter.rs +++ b/substrate/frame/revive/src/storage/meter.rs @@ -286,16 +286,16 @@ where /// This is called whenever a new subcall is initiated in order to track the storage /// usage for this sub call separately. This is necessary because we want to exchange balance /// with the current contract we are interacting with. - pub fn nested(&self, limit: BalanceOf) -> RawMeter { + pub fn nested(&self, lim: BalanceOf) -> RawMeter { debug_assert!(matches!(self.contract_state(), ContractState::Alive)); + + // Limit gas for nested call, per EIP-150. + let available = self.available() - self.available() / (BalanceOf::::from(64u32)); + // If a special limit is specified higher than it is available, // we want to enforce the lesser limit to the nested meter, to fail in the sub-call. - let limit = self.available().min(limit); - if limit.is_zero() { - RawMeter { limit: self.available(), ..Default::default() } - } else { - RawMeter { limit, nested: Nested::OwnLimit, ..Default::default() } - } + let limit = available.min(lim); + RawMeter { limit, nested: Nested::OwnLimit, ..Default::default() } } /// Absorb a child that was spawned to handle a sub call. From ee2a18381f464c1364ce70f9fccb271ec8b46ad1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexandre=20Bald=C3=A9?= Date: Sat, 14 Dec 2024 03:37:25 +0000 Subject: [PATCH 09/34] Fix storage meter unit test for `fn nested` --- substrate/frame/revive/src/storage/meter.rs | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/substrate/frame/revive/src/storage/meter.rs b/substrate/frame/revive/src/storage/meter.rs index 27113cf3a1a4..6621f8b9d500 100644 --- a/substrate/frame/revive/src/storage/meter.rs +++ b/substrate/frame/revive/src/storage/meter.rs @@ -725,13 +725,16 @@ mod tests { } #[test] + /// Previously, passing a limit of 0 meant unlimited storage for a nested call. + /// + /// Now, a limit of 0 means the subcall will not be able to use any storage. fn nested_zero_limit_requested() { clear_ext(); let meter = TestMeter::new(&Origin::from_account_id(ALICE), 1_000, 0).unwrap(); assert_eq!(meter.available(), 1_000); let nested0 = meter.nested(BalanceOf::::zero()); - assert_eq!(nested0.available(), 1_000); + assert_eq!(nested0.available(), 0); } #[test] @@ -751,7 +754,7 @@ mod tests { let meter = TestMeter::new(&Origin::from_account_id(ALICE), 1_000, 0).unwrap(); assert_eq!(meter.available(), 1_000); let nested0 = meter.nested(1_000); - assert_eq!(nested0.available(), 1_000); + assert_eq!(nested0.available(), 985); } #[test] @@ -761,7 +764,7 @@ mod tests { let meter = TestMeter::new(&Origin::from_account_id(ALICE), 1_000, 0).unwrap(); assert_eq!(meter.available(), 1_000); let nested0 = meter.nested(2_000); - assert_eq!(nested0.available(), 1_000); + assert_eq!(nested0.available(), 985); } #[test] From b89495fe5606983a3005c29d1e79907bc4893cb8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexandre=20Bald=C3=A9?= Date: Tue, 17 Dec 2024 17:57:57 +0000 Subject: [PATCH 10/34] Remove usage of 0 as unlimited storage meter in test --- substrate/frame/contracts/src/storage/meter.rs | 4 ++-- substrate/frame/revive/src/storage/meter.rs | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/substrate/frame/contracts/src/storage/meter.rs b/substrate/frame/contracts/src/storage/meter.rs index 951cb25994e1..b48d0c5280b4 100644 --- a/substrate/frame/contracts/src/storage/meter.rs +++ b/substrate/frame/contracts/src/storage/meter.rs @@ -878,7 +878,7 @@ mod tests { let mut meter = TestMeter::new(&test_case.origin, Some(1_000), 0).unwrap(); assert_eq!(meter.available(), 1_000); - let mut nested0 = meter.nested(BalanceOf::::zero()); + let mut nested0 = meter.nested(BalanceOf::::max_value()); nested0.charge(&Diff { bytes_added: 5, bytes_removed: 1, @@ -893,7 +893,7 @@ mod tests { bytes_deposit: 100, items_deposit: 20, }); - let mut nested1 = nested0.nested(BalanceOf::::zero()); + let mut nested1 = nested0.nested(BalanceOf::::max_value()); nested1.charge(&Diff { items_removed: 5, ..Default::default() }); nested1.charge(&Diff { bytes_added: 20, ..Default::default() }); nested1.terminate(&nested1_info, CHARLIE); diff --git a/substrate/frame/revive/src/storage/meter.rs b/substrate/frame/revive/src/storage/meter.rs index 6621f8b9d500..13d4de576f01 100644 --- a/substrate/frame/revive/src/storage/meter.rs +++ b/substrate/frame/revive/src/storage/meter.rs @@ -922,7 +922,7 @@ mod tests { let mut meter = TestMeter::new(&test_case.origin, 1_000, 0).unwrap(); assert_eq!(meter.available(), 1_000); - let mut nested0 = meter.nested(BalanceOf::::zero()); + let mut nested0 = meter.nested(BalanceOf::::max_value()); nested0.charge(&Diff { bytes_added: 5, bytes_removed: 1, @@ -938,7 +938,7 @@ mod tests { items_deposit: 20, immutable_data_len: 0, }); - let mut nested1 = nested0.nested(BalanceOf::::zero()); + let mut nested1 = nested0.nested(BalanceOf::::max_value()); nested1.charge(&Diff { items_removed: 5, ..Default::default() }); nested1.charge(&Diff { bytes_added: 20, ..Default::default() }); nested1.terminate(&nested1_info, CHARLIE); From 8e66f509b0df8d0120c5e3b2413eaf3580a1866d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexandre=20Bald=C3=A9?= Date: Tue, 17 Dec 2024 18:00:28 +0000 Subject: [PATCH 11/34] Fix tests in `exec::tests` In particular, this commit removes the usage of `0` as unlimited metering in the following tests: - `nonce` - `last_frame_output_works_on_instantiate` - `instantiation_from_contract` - `immutable_data_set_works_only_once` - `immutable_data_set_errors_with_empty_data` - `immutable_data_access_checks_work` --- substrate/frame/revive/src/exec.rs | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/substrate/frame/revive/src/exec.rs b/substrate/frame/revive/src/exec.rs index 5e1474859d8d..efd9e8e41462 100644 --- a/substrate/frame/revive/src/exec.rs +++ b/substrate/frame/revive/src/exec.rs @@ -3098,8 +3098,8 @@ mod tests { let (address, output) = ctx .ext .instantiate( - Weight::zero(), - U256::zero(), + Weight::MAX, + U256::from(u64::MAX), dummy_ch, ::Currency::minimum_balance().into(), vec![], @@ -3802,8 +3802,8 @@ mod tests { let succ_fail_code = MockLoader::insert(Constructor, move |ctx, _| { ctx.ext .instantiate( - Weight::zero(), - U256::zero(), + Weight::MAX, + U256::from(u64::MAX), fail_code, ctx.ext.minimum_balance() * 100, vec![], @@ -3819,8 +3819,8 @@ mod tests { let addr = ctx .ext .instantiate( - Weight::zero(), - U256::zero(), + Weight::MAX, + U256::from(u64::MAX), success_code, ctx.ext.minimum_balance() * 100, vec![], @@ -4597,7 +4597,7 @@ mod tests { // Successful instantiation should set the output let address = ctx .ext - .instantiate(Weight::zero(), U256::zero(), ok_ch, value, vec![], None) + .instantiate(Weight::MAX, U256::from(u64::MAX), ok_ch, value, vec![], None) .unwrap(); assert_eq!( ctx.ext.last_frame_output(), @@ -4607,8 +4607,8 @@ mod tests { // Balance transfers should reset the output ctx.ext .call( - Weight::zero(), - U256::zero(), + Weight::MAX, + U256::from(u64::MAX), &address, U256::from(1), vec![], @@ -4827,7 +4827,7 @@ mod tests { // Constructors can not access the immutable data ctx.ext - .instantiate(Weight::zero(), U256::zero(), dummy_ch, value, vec![], None) + .instantiate(Weight::MAX, U256::from(u64::MAX), dummy_ch, value, vec![], None) .unwrap(); exec_success() @@ -4944,7 +4944,7 @@ mod tests { move |ctx, _| { let value = ::Currency::minimum_balance().into(); ctx.ext - .instantiate(Weight::zero(), U256::zero(), dummy_ch, value, vec![], None) + .instantiate(Weight::MAX, U256::from(u64::MAX), dummy_ch, value, vec![], None) .unwrap(); exec_success() @@ -4989,7 +4989,7 @@ mod tests { move |ctx, _| { let value = ::Currency::minimum_balance().into(); ctx.ext - .instantiate(Weight::zero(), U256::zero(), dummy_ch, value, vec![], None) + .instantiate(Weight::MAX, U256::from(u64::MAX), dummy_ch, value, vec![], None) .unwrap(); exec_success() From 8938008070f876924d1b782d68f97882f7abdf5b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexandre=20Bald=C3=A9?= Date: Tue, 17 Dec 2024 21:27:19 +0000 Subject: [PATCH 12/34] Rework 0 as unlimited metering in test contracts This fixes, among other tests: * `tests::gas_consumed_is_linear_for_nested_calls` test * `tests::deposit_limit_in_nested_calls` * `tests::transient_storage_limit_in_call` * `tests::call_return_code` * `test::chain_extension_temp_storage_works` * `tests::origin_api_works` * `tests::read_only_call_works` --- .../frame/contracts/src/benchmarking/mod.rs | 8 +++---- .../frame/revive/fixtures/contracts/call.rs | 4 ++-- .../contracts/call_diverging_out_len.rs | 8 +++---- .../fixtures/contracts/call_return_code.rs | 4 ++-- .../contracts/call_runtime_and_call.rs | 4 ++-- .../contracts/call_with_flags_and_value.rs | 4 ++-- .../fixtures/contracts/caller_contract.rs | 24 +++++++++---------- .../contracts/chain_extension_temp_storage.rs | 4 ++-- .../fixtures/contracts/create1_with_value.rs | 2 +- .../contracts/create_storage_and_call.rs | 4 ++-- .../create_storage_and_instantiate.rs | 4 ++-- .../create_transient_storage_and_call.rs | 4 ++-- .../contracts/delegate_call_deposit_limit.rs | 2 +- .../contracts/delegate_call_simple.rs | 2 +- .../contracts/destroy_and_transfer.rs | 12 +++++----- .../contracts/instantiate_return_code.rs | 5 ++-- .../contracts/locking_delegate_dependency.rs | 2 +- .../frame/revive/fixtures/contracts/origin.rs | 4 ++-- .../fixtures/contracts/read_only_call.rs | 4 ++-- .../revive/fixtures/contracts/recurse.rs | 4 ++-- .../fixtures/contracts/return_data_api.rs | 10 ++++---- .../fixtures/contracts/self_destruct.rs | 4 ++-- substrate/frame/revive/fixtures/src/lib.rs | 2 +- .../frame/revive/src/benchmarking/mod.rs | 12 +++++----- 24 files changed, 68 insertions(+), 69 deletions(-) diff --git a/substrate/frame/contracts/src/benchmarking/mod.rs b/substrate/frame/contracts/src/benchmarking/mod.rs index 669279f12b27..47996d2713a8 100644 --- a/substrate/frame/contracts/src/benchmarking/mod.rs +++ b/substrate/frame/contracts/src/benchmarking/mod.rs @@ -1650,8 +1650,8 @@ mod benchmarks { &mut memory, CallFlags::CLONE_INPUT.bits(), // flags 0, // callee_ptr - 0, // ref_time_limit - 0, // proof_size_limit + u64::MAX, // ref_time_limit + u64::MAX, // proof_size_limit callee_len, // deposit_ptr callee_len + deposit_len, // value_ptr 0, // input_data_ptr @@ -1744,8 +1744,8 @@ mod benchmarks { &mut runtime, &mut memory, 0, // code_hash_ptr - 0, // ref_time_limit - 0, // proof_size_limit + u64::MAX, // ref_time_limit + u64::MAX, // proof_size_limit offset(hash_len), // deposit_ptr offset(deposit_len), // value_ptr offset(value_len), // input_data_ptr diff --git a/substrate/frame/revive/fixtures/contracts/call.rs b/substrate/frame/revive/fixtures/contracts/call.rs index ee51548879d9..2b41b7d8fe09 100644 --- a/substrate/frame/revive/fixtures/contracts/call.rs +++ b/substrate/frame/revive/fixtures/contracts/call.rs @@ -38,8 +38,8 @@ pub extern "C" fn call() { api::call( uapi::CallFlags::empty(), callee_addr, - 0u64, // How much ref_time to devote for the execution. 0 = all. - 0u64, // How much proof_size to devote for the execution. 0 = all. + 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. None, // No deposit limit. &[0u8; 32], // Value transferred to the contract. callee_input, diff --git a/substrate/frame/revive/fixtures/contracts/call_diverging_out_len.rs b/substrate/frame/revive/fixtures/contracts/call_diverging_out_len.rs index 129adde2cec9..1e9048588c5c 100644 --- a/substrate/frame/revive/fixtures/contracts/call_diverging_out_len.rs +++ b/substrate/frame/revive/fixtures/contracts/call_diverging_out_len.rs @@ -42,8 +42,8 @@ fn assert_call(callee_address: &[u8; 20], expected_output: [u8; api::call( uapi::CallFlags::ALLOW_REENTRY, callee_address, - 0u64, - 0u64, + u64::MAX, + u64::MAX, None, &[0u8; 32], &[], @@ -67,8 +67,8 @@ fn assert_instantiate(expected_output: [u8; BUF_SIZE]) { api::instantiate( &code_hash, - 0u64, - 0u64, + u64::MAX, + u64::MAX, None, &[0; 32], &[0; 32], diff --git a/substrate/frame/revive/fixtures/contracts/call_return_code.rs b/substrate/frame/revive/fixtures/contracts/call_return_code.rs index 2d13b9f70956..4cbc925eaaed 100644 --- a/substrate/frame/revive/fixtures/contracts/call_return_code.rs +++ b/substrate/frame/revive/fixtures/contracts/call_return_code.rs @@ -42,8 +42,8 @@ pub extern "C" fn call() { let err_code = match api::call( uapi::CallFlags::empty(), callee_addr, - 0u64, // How much ref_time to devote for the execution. 0 = all. - 0u64, // How much proof_size to devote for the execution. 0 = all. + 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. None, // No deposit limit. value, // Value transferred to the contract. input, diff --git a/substrate/frame/revive/fixtures/contracts/call_runtime_and_call.rs b/substrate/frame/revive/fixtures/contracts/call_runtime_and_call.rs index 8c8aee962849..a3e1c2394cfd 100644 --- a/substrate/frame/revive/fixtures/contracts/call_runtime_and_call.rs +++ b/substrate/frame/revive/fixtures/contracts/call_runtime_and_call.rs @@ -42,8 +42,8 @@ pub extern "C" fn call() { api::call( uapi::CallFlags::empty(), callee_addr, - 0u64, // How much ref_time to devote for the execution. 0 = all. - 0u64, // How much proof_size to devote for the execution. 0 = all. + 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. None, // No deposit limit. &[0u8; 32], // Value transferred to the contract. callee_input, diff --git a/substrate/frame/revive/fixtures/contracts/call_with_flags_and_value.rs b/substrate/frame/revive/fixtures/contracts/call_with_flags_and_value.rs index 330393e706e9..703dd00fb7f9 100644 --- a/substrate/frame/revive/fixtures/contracts/call_with_flags_and_value.rs +++ b/substrate/frame/revive/fixtures/contracts/call_with_flags_and_value.rs @@ -40,8 +40,8 @@ pub extern "C" fn call() { api::call( uapi::CallFlags::from_bits(flags).unwrap(), callee_addr, - 0u64, // How much ref_time to devote for the execution. 0 = all. - 0u64, // How much proof_size to devote for the execution. 0 = all. + 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. None, // No deposit limit. &u256_bytes(value), // Value transferred to the contract. forwarded_input, diff --git a/substrate/frame/revive/fixtures/contracts/caller_contract.rs b/substrate/frame/revive/fixtures/contracts/caller_contract.rs index edad43fae251..e5cbbc116997 100644 --- a/substrate/frame/revive/fixtures/contracts/caller_contract.rs +++ b/substrate/frame/revive/fixtures/contracts/caller_contract.rs @@ -42,8 +42,8 @@ pub extern "C" fn call() { // Fail to deploy the contract since it returns a non-zero exit status. let res = api::instantiate( code_hash, - 0u64, // How much ref_time weight to devote for the execution. 0 = all. - 0u64, // How much proof_size weight to devote for the execution. 0 = all. + u64::MAX, // How much ref_time weight to devote for the execution. u64::MAX = use all. + u64::MAX, // How much proof_size weight to devote for the execution. u64::MAX = use all. None, // No deposit limit. &value, &reverted_input, @@ -57,7 +57,7 @@ pub extern "C" fn call() { let res = api::instantiate( code_hash, 1u64, // too little ref_time weight - 0u64, // How much proof_size weight to devote for the execution. 0 = all. + u64::MAX, // How much proof_size weight to devote for the execution. u64::MAX = use all. None, // No deposit limit. &value, &input, @@ -70,7 +70,7 @@ pub extern "C" fn call() { // Fail to deploy the contract due to insufficient proof_size weight. let res = api::instantiate( code_hash, - 0u64, // How much ref_time weight to devote for the execution. 0 = all. + u64::MAX, // How much ref_time weight to devote for the execution. u64::MAX = use all. 1u64, // Too little proof_size weight None, // No deposit limit. &value, @@ -86,8 +86,8 @@ pub extern "C" fn call() { api::instantiate( code_hash, - 0u64, // How much ref_time weight to devote for the execution. 0 = all. - 0u64, // How much proof_size weight to devote for the execution. 0 = all. + u64::MAX, // How much ref_time weight to devote for the execution. u64::MAX = use all. + u64::MAX, // How much proof_size weight to devote for the execution. u64::MAX = use all. None, // No deposit limit. &value, &input, @@ -101,8 +101,8 @@ pub extern "C" fn call() { let res = api::call( uapi::CallFlags::empty(), &callee, - 0u64, // How much ref_time weight to devote for the execution. 0 = all. - 0u64, // How much proof_size weight to devote for the execution. 0 = all. + u64::MAX, // How much ref_time weight to devote for the execution. u64::MAX = use all. + u64::MAX, // How much proof_size weight to devote for the execution. u64::MAX = use all. None, // No deposit limit. &value, &reverted_input, @@ -115,7 +115,7 @@ pub extern "C" fn call() { uapi::CallFlags::empty(), &callee, 1u64, // Too little ref_time weight. - 0u64, // How much proof_size weight to devote for the execution. 0 = all. + u64::MAX, // How much proof_size weight to devote for the execution. u64::MAX = use all. None, // No deposit limit. &value, &input, @@ -127,7 +127,7 @@ pub extern "C" fn call() { let res = api::call( uapi::CallFlags::empty(), &callee, - 0u64, // How much ref_time weight to devote for the execution. 0 = all. + u64::MAX, // How much ref_time weight to devote for the execution. u64::MAX = use all. 1u64, // too little proof_size weight None, // No deposit limit. &value, @@ -141,8 +141,8 @@ pub extern "C" fn call() { api::call( uapi::CallFlags::empty(), &callee, - 0u64, // How much ref_time weight to devote for the execution. 0 = all. - 0u64, // How much proof_size weight to devote for the execution. 0 = all. + u64::MAX, // How much ref_time weight to devote for the execution. u64::MAX = use all. + u64::MAX, // How much proof_size weight to devote for the execution. u64::MAX = use all. None, // No deposit limit. &value, &input, diff --git a/substrate/frame/revive/fixtures/contracts/chain_extension_temp_storage.rs b/substrate/frame/revive/fixtures/contracts/chain_extension_temp_storage.rs index 22d6c5b548d8..a6e4720c0563 100644 --- a/substrate/frame/revive/fixtures/contracts/chain_extension_temp_storage.rs +++ b/substrate/frame/revive/fixtures/contracts/chain_extension_temp_storage.rs @@ -54,8 +54,8 @@ pub extern "C" fn call() { api::call( uapi::CallFlags::ALLOW_REENTRY, &addr, - 0u64, // How much ref_time to devote for the execution. 0 = all. - 0u64, // How much proof_size to devote for the execution. 0 = all. + 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. None, // No deposit limit. &[0u8; 32], // Value transferred to the contract. input, diff --git a/substrate/frame/revive/fixtures/contracts/create1_with_value.rs b/substrate/frame/revive/fixtures/contracts/create1_with_value.rs index c6adab828860..29c7b9f2ed81 100644 --- a/substrate/frame/revive/fixtures/contracts/create1_with_value.rs +++ b/substrate/frame/revive/fixtures/contracts/create1_with_value.rs @@ -34,6 +34,6 @@ pub extern "C" fn call() { api::value_transferred(&mut value); // Deploy the contract with no salt (equivalent to create1). - let ret = api::instantiate(code_hash, 0u64, 0u64, None, &value, &[], None, None, None); + let ret = api::instantiate(code_hash, u64::MAX, u64::MAX, None, &value, &[], None, None, None); assert!(ret.is_ok()); } diff --git a/substrate/frame/revive/fixtures/contracts/create_storage_and_call.rs b/substrate/frame/revive/fixtures/contracts/create_storage_and_call.rs index a12c36af856a..429efde51c65 100644 --- a/substrate/frame/revive/fixtures/contracts/create_storage_and_call.rs +++ b/substrate/frame/revive/fixtures/contracts/create_storage_and_call.rs @@ -43,8 +43,8 @@ pub extern "C" fn call() { let ret = api::call( uapi::CallFlags::empty(), callee, - 0u64, // How much ref_time weight to devote for the execution. 0 = all. - 0u64, // How much proof_size weight to devote for the execution. 0 = all. + u64::MAX, // How much ref_time weight to devote for the execution. u64::MAX = use all resources. + u64::MAX, // How much proof_size weight to devote for the execution. u64::MAX = use all resources. Some(deposit_limit), &[0u8; 32], // Value transferred to the contract. input, 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 ecc0fc79e6fd..c9ed851076e9 100644 --- a/substrate/frame/revive/fixtures/contracts/create_storage_and_instantiate.rs +++ b/substrate/frame/revive/fixtures/contracts/create_storage_and_instantiate.rs @@ -41,8 +41,8 @@ pub extern "C" fn call() { let ret = api::instantiate( code_hash, - 0u64, // How much ref_time weight to devote for the execution. 0 = all. - 0u64, // How much proof_size weight to devote for the execution. 0 = all. + u64::MAX, // How much ref_time weight to devote for the execution. u64::MAX = use all. + u64::MAX, // How much proof_size weight to devote for the execution. u64::MAX = use all. Some(deposit_limit), &value, input, diff --git a/substrate/frame/revive/fixtures/contracts/create_transient_storage_and_call.rs b/substrate/frame/revive/fixtures/contracts/create_transient_storage_and_call.rs index d2efb26e5ceb..66a46cf6ac32 100644 --- a/substrate/frame/revive/fixtures/contracts/create_transient_storage_and_call.rs +++ b/substrate/frame/revive/fixtures/contracts/create_transient_storage_and_call.rs @@ -49,8 +49,8 @@ pub extern "C" fn call() { api::call( uapi::CallFlags::empty(), callee, - 0u64, // How much ref_time weight to devote for the execution. 0 = all. - 0u64, // How much proof_size weight to devote for the execution. 0 = all. + u64::MAX, // How much ref_time weight to devote for the execution. u64::MAX = all. + u64::MAX, // How much proof_size weight to devote for the execution. u64::MAX = all. None, &[0u8; 32], // Value transferred to the contract. input, diff --git a/substrate/frame/revive/fixtures/contracts/delegate_call_deposit_limit.rs b/substrate/frame/revive/fixtures/contracts/delegate_call_deposit_limit.rs index 0f157f5a18ac..2e43e1d1ff6c 100644 --- a/substrate/frame/revive/fixtures/contracts/delegate_call_deposit_limit.rs +++ b/substrate/frame/revive/fixtures/contracts/delegate_call_deposit_limit.rs @@ -34,7 +34,7 @@ pub extern "C" fn call() { ); let input = [0u8; 0]; - let ret = api::delegate_call(uapi::CallFlags::empty(), address, 0, 0, Some(&u256_bytes(deposit_limit)), &input, None); + let ret = api::delegate_call(uapi::CallFlags::empty(), address, u64::MAX, u64::MAX, Some(&u256_bytes(deposit_limit)), &input, None); if let Err(code) = ret { api::return_value(uapi::ReturnFlags::REVERT, &(code as u32).to_le_bytes()); diff --git a/substrate/frame/revive/fixtures/contracts/delegate_call_simple.rs b/substrate/frame/revive/fixtures/contracts/delegate_call_simple.rs index a8501dad4692..e9c0fb6327bb 100644 --- a/substrate/frame/revive/fixtures/contracts/delegate_call_simple.rs +++ b/substrate/frame/revive/fixtures/contracts/delegate_call_simple.rs @@ -32,5 +32,5 @@ pub extern "C" fn call() { // Delegate call into passed address. let input = [0u8; 0]; - api::delegate_call(uapi::CallFlags::empty(), address, 0, 0, None, &input, None).unwrap(); + api::delegate_call(uapi::CallFlags::empty(), address, u64::MAX, u64::MAX, None, &input, None).unwrap(); } diff --git a/substrate/frame/revive/fixtures/contracts/destroy_and_transfer.rs b/substrate/frame/revive/fixtures/contracts/destroy_and_transfer.rs index 8342f4acf952..34ea1510f1a2 100644 --- a/substrate/frame/revive/fixtures/contracts/destroy_and_transfer.rs +++ b/substrate/frame/revive/fixtures/contracts/destroy_and_transfer.rs @@ -35,8 +35,8 @@ pub extern "C" fn deploy() { api::instantiate( code_hash, - 0u64, // How much ref_time weight to devote for the execution. 0 = all. - 0u64, // How much proof_size weight to devote for the execution. 0 = all. + u64::MAX, // How much ref_time weight to devote for the execution. u64::MAX = use all. + u64::MAX, // How much proof_size weight to devote for the execution. u64::MAX = use all. None, // No deposit limit. &VALUE, &input, @@ -62,8 +62,8 @@ pub extern "C" fn call() { let res = api::call( uapi::CallFlags::empty(), &callee_addr, - 0u64, // How much ref_time weight to devote for the execution. 0 = all. - 0u64, // How much proof_size weight to devote for the execution. 0 = all. + u64::MAX, // How much ref_time weight to devote for the execution. u64::MAX = use all. + u64::MAX, // How much proof_size weight to devote for the execution. u64::MAX = use all. None, // No deposit limit. &VALUE, &[0u8; 1], @@ -75,8 +75,8 @@ pub extern "C" fn call() { api::call( uapi::CallFlags::empty(), &callee_addr, - 0u64, // How much ref_time weight to devote for the execution. 0 = all. - 0u64, // How much proof_size weight to devote for the execution. 0 = all. + u64::MAX, // How much ref_time weight to devote for the execution. u64::MAX = use all. + u64::MAX, // How much proof_size weight to devote for the execution. u64::MAX = use all. None, // No deposit limit. &VALUE, &[0u8; 0], diff --git a/substrate/frame/revive/fixtures/contracts/instantiate_return_code.rs b/substrate/frame/revive/fixtures/contracts/instantiate_return_code.rs index 9764859c619b..f311f1537b49 100644 --- a/substrate/frame/revive/fixtures/contracts/instantiate_return_code.rs +++ b/substrate/frame/revive/fixtures/contracts/instantiate_return_code.rs @@ -33,9 +33,8 @@ pub extern "C" fn call() { let err_code = match api::instantiate( code_hash, - 0u64, // How much ref_time weight to devote for the execution. 0 = all. - 0u64, /* How much proof_size weight to devote for the execution. 0 = - * all. */ + u64::MAX, // How much ref_time weight to devote for the execution. u64::MAX = use all. + u64::MAX, // How much proof_size weight to devote for the execution. u64::MAX = use all. None, // No deposit limit. &u256_bytes(10_000u64), // Value to transfer. input, diff --git a/substrate/frame/revive/fixtures/contracts/locking_delegate_dependency.rs b/substrate/frame/revive/fixtures/contracts/locking_delegate_dependency.rs index 3d7702c6537a..454c649f636a 100644 --- a/substrate/frame/revive/fixtures/contracts/locking_delegate_dependency.rs +++ b/substrate/frame/revive/fixtures/contracts/locking_delegate_dependency.rs @@ -52,7 +52,7 @@ fn load_input(delegate_call: bool) { } if delegate_call { - api::delegate_call(uapi::CallFlags::empty(), address, 0, 0, None, &[], None).unwrap(); + api::delegate_call(uapi::CallFlags::empty(), address, u64::MAX, u64::MAX, None, &[], None).unwrap(); } } diff --git a/substrate/frame/revive/fixtures/contracts/origin.rs b/substrate/frame/revive/fixtures/contracts/origin.rs index 8e9afd8e8052..bd79c58eff06 100644 --- a/substrate/frame/revive/fixtures/contracts/origin.rs +++ b/substrate/frame/revive/fixtures/contracts/origin.rs @@ -49,8 +49,8 @@ pub extern "C" fn call() { api::call( uapi::CallFlags::ALLOW_REENTRY, &addr, - 0u64, - 0u64, + u64::MAX, + u64::MAX, None, &[0; 32], &[], diff --git a/substrate/frame/revive/fixtures/contracts/read_only_call.rs b/substrate/frame/revive/fixtures/contracts/read_only_call.rs index ea74d56867f5..79a44f8b1d39 100644 --- a/substrate/frame/revive/fixtures/contracts/read_only_call.rs +++ b/substrate/frame/revive/fixtures/contracts/read_only_call.rs @@ -39,8 +39,8 @@ pub extern "C" fn call() { api::call( uapi::CallFlags::READ_ONLY, callee_addr, - 0u64, // How much ref_time to devote for the execution. 0 = all. - 0u64, // How much proof_size to devote for the execution. 0 = all. + u64::MAX, // How much ref_time to devote for the execution. u64::MAX = all. + u64::MAX, // How much proof_size to devote for the execution. u64::MAX = all. None, // No deposit limit. &[0u8; 32], // Value transferred to the contract. callee_input, diff --git a/substrate/frame/revive/fixtures/contracts/recurse.rs b/substrate/frame/revive/fixtures/contracts/recurse.rs index 2e70d67d8c73..2e69a777d844 100644 --- a/substrate/frame/revive/fixtures/contracts/recurse.rs +++ b/substrate/frame/revive/fixtures/contracts/recurse.rs @@ -43,8 +43,8 @@ pub extern "C" fn call() { api::call( uapi::CallFlags::ALLOW_REENTRY, &addr, - 0u64, // How much ref_time to devote for the execution. 0 = all. - 0u64, // How much deposit_limit to devote for the execution. 0 = all. + u64::MAX, // How much ref_time to devote for the execution. u64::MAX = use all resources. + u64::MAX, // How much deposit_limit to devote for the execution. u64::MAX = use all resources. None, // No deposit limit. &[0u8; 32], // Value transferred to the contract. &(calls_left - 1).to_le_bytes(), diff --git a/substrate/frame/revive/fixtures/contracts/return_data_api.rs b/substrate/frame/revive/fixtures/contracts/return_data_api.rs index 2a390296a419..48a411161943 100644 --- a/substrate/frame/revive/fixtures/contracts/return_data_api.rs +++ b/substrate/frame/revive/fixtures/contracts/return_data_api.rs @@ -82,7 +82,7 @@ fn assert_return_data_size_of(expected: u64) { /// Assert the return data to be reset after a balance transfer. fn assert_balance_transfer_does_reset() { - api::call(uapi::CallFlags::empty(), &[0u8; 20], 0, 0, None, &u256_bytes(128), &[], None) + api::call(uapi::CallFlags::empty(), &[0u8; 20], u64::MAX, u64::MAX, None, &u256_bytes(128), &[], None) .unwrap(); assert_return_data_size_of(0); } @@ -113,8 +113,8 @@ pub extern "C" fn call() { let mut instantiate = |exit_flag| { api::instantiate( code_hash, - 0u64, - 0u64, + u64::MAX, + u64::MAX, None, &[0; 32], &construct_input(exit_flag), @@ -127,8 +127,8 @@ pub extern "C" fn call() { api::call( uapi::CallFlags::empty(), address_buf, - 0u64, - 0u64, + u64::MAX, + u64::MAX, None, &[0; 32], &construct_input(exit_flag), diff --git a/substrate/frame/revive/fixtures/contracts/self_destruct.rs b/substrate/frame/revive/fixtures/contracts/self_destruct.rs index 2f37706634bd..ff969d4c57cc 100644 --- a/substrate/frame/revive/fixtures/contracts/self_destruct.rs +++ b/substrate/frame/revive/fixtures/contracts/self_destruct.rs @@ -42,8 +42,8 @@ pub extern "C" fn call() { api::call( uapi::CallFlags::ALLOW_REENTRY, &addr, - 0u64, // How much ref_time to devote for the execution. 0 = all. - 0u64, // How much proof_size to devote for the execution. 0 = all. + u64::MAX, // How much ref_time to devote for the execution. u64 = all. + u64::MAX, // How much proof_size to devote for the execution. u64 = all. None, // No deposit limit. &[0u8; 32], // Value to transfer. &[0u8; 0], diff --git a/substrate/frame/revive/fixtures/src/lib.rs b/substrate/frame/revive/fixtures/src/lib.rs index 24f6ee547dc7..987903f43800 100644 --- a/substrate/frame/revive/fixtures/src/lib.rs +++ b/substrate/frame/revive/fixtures/src/lib.rs @@ -22,7 +22,7 @@ extern crate alloc; // generated file that tells us where to find the fixtures include!(concat!(env!("OUT_DIR"), "/fixture_location.rs")); -/// Load a given wasm module and returns a wasm binary contents along with it's hash. +/// Load a given wasm module and returns a wasm binary contents along with its hash. #[cfg(feature = "std")] pub fn compile_module(fixture_name: &str) -> anyhow::Result<(Vec, sp_core::H256)> { let out_dir: std::path::PathBuf = FIXTURE_DIR.into(); diff --git a/substrate/frame/revive/src/benchmarking/mod.rs b/substrate/frame/revive/src/benchmarking/mod.rs index 1fb4d7ab58a4..c114efb41a75 100644 --- a/substrate/frame/revive/src/benchmarking/mod.rs +++ b/substrate/frame/revive/src/benchmarking/mod.rs @@ -1567,8 +1567,8 @@ mod benchmarks { memory.as_mut_slice(), CallFlags::CLONE_INPUT.bits(), // flags 0, // callee_ptr - 0, // ref_time_limit - 0, // proof_size_limit + u64::MAX, // ref_time_limit + u64::MAX, // proof_size_limit callee_len, // deposit_ptr callee_len + deposit_len, // value_ptr 0, // input_data_ptr @@ -1607,8 +1607,8 @@ mod benchmarks { memory.as_mut_slice(), 0, // flags 0, // address_ptr - 0, // ref_time_limit - 0, // proof_size_limit + u64::MAX, // ref_time_limit + u64::MAX, // proof_size_limit address_len, // deposit_ptr 0, // input_data_ptr 0, // input_data_len @@ -1669,8 +1669,8 @@ mod benchmarks { result = runtime.bench_instantiate( memory.as_mut_slice(), 0, // code_hash_ptr - 0, // ref_time_limit - 0, // proof_size_limit + u64::MAX, // ref_time_limit + u64::MAX, // proof_size_limit offset(hash_len), // deposit_ptr offset(deposit_len), // value_ptr offset(value_len), // input_data_ptr From f5e6b2b1b7246ac74d892159f6b5dccc9de76d84 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexandre=20Bald=C3=A9?= Date: Thu, 19 Dec 2024 10:52:39 +0100 Subject: [PATCH 13/34] Rollback changes in `frame/contracts` --- substrate/frame/contracts/src/benchmarking/mod.rs | 8 ++++---- substrate/frame/contracts/src/storage/meter.rs | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/substrate/frame/contracts/src/benchmarking/mod.rs b/substrate/frame/contracts/src/benchmarking/mod.rs index 47996d2713a8..669279f12b27 100644 --- a/substrate/frame/contracts/src/benchmarking/mod.rs +++ b/substrate/frame/contracts/src/benchmarking/mod.rs @@ -1650,8 +1650,8 @@ mod benchmarks { &mut memory, CallFlags::CLONE_INPUT.bits(), // flags 0, // callee_ptr - u64::MAX, // ref_time_limit - u64::MAX, // proof_size_limit + 0, // ref_time_limit + 0, // proof_size_limit callee_len, // deposit_ptr callee_len + deposit_len, // value_ptr 0, // input_data_ptr @@ -1744,8 +1744,8 @@ mod benchmarks { &mut runtime, &mut memory, 0, // code_hash_ptr - u64::MAX, // ref_time_limit - u64::MAX, // proof_size_limit + 0, // ref_time_limit + 0, // proof_size_limit offset(hash_len), // deposit_ptr offset(deposit_len), // value_ptr offset(value_len), // input_data_ptr diff --git a/substrate/frame/contracts/src/storage/meter.rs b/substrate/frame/contracts/src/storage/meter.rs index b48d0c5280b4..951cb25994e1 100644 --- a/substrate/frame/contracts/src/storage/meter.rs +++ b/substrate/frame/contracts/src/storage/meter.rs @@ -878,7 +878,7 @@ mod tests { let mut meter = TestMeter::new(&test_case.origin, Some(1_000), 0).unwrap(); assert_eq!(meter.available(), 1_000); - let mut nested0 = meter.nested(BalanceOf::::max_value()); + let mut nested0 = meter.nested(BalanceOf::::zero()); nested0.charge(&Diff { bytes_added: 5, bytes_removed: 1, @@ -893,7 +893,7 @@ mod tests { bytes_deposit: 100, items_deposit: 20, }); - let mut nested1 = nested0.nested(BalanceOf::::max_value()); + let mut nested1 = nested0.nested(BalanceOf::::zero()); nested1.charge(&Diff { items_removed: 5, ..Default::default() }); nested1.charge(&Diff { bytes_added: 20, ..Default::default() }); nested1.terminate(&nested1_info, CHARLIE); From 33758aad3cbc7e499ee99b9765ccf32bc1e43b15 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexandre=20Bald=C3=A9?= Date: Thu, 19 Dec 2024 11:10:56 +0100 Subject: [PATCH 14/34] Add EIP-150 note to doc comment --- substrate/frame/contracts/src/benchmarking/mod.rs | 8 ++++---- substrate/frame/revive/src/gas.rs | 5 +++-- substrate/frame/revive/src/storage/meter.rs | 9 +++++---- 3 files changed, 12 insertions(+), 10 deletions(-) diff --git a/substrate/frame/contracts/src/benchmarking/mod.rs b/substrate/frame/contracts/src/benchmarking/mod.rs index 669279f12b27..47996d2713a8 100644 --- a/substrate/frame/contracts/src/benchmarking/mod.rs +++ b/substrate/frame/contracts/src/benchmarking/mod.rs @@ -1650,8 +1650,8 @@ mod benchmarks { &mut memory, CallFlags::CLONE_INPUT.bits(), // flags 0, // callee_ptr - 0, // ref_time_limit - 0, // proof_size_limit + u64::MAX, // ref_time_limit + u64::MAX, // proof_size_limit callee_len, // deposit_ptr callee_len + deposit_len, // value_ptr 0, // input_data_ptr @@ -1744,8 +1744,8 @@ mod benchmarks { &mut runtime, &mut memory, 0, // code_hash_ptr - 0, // ref_time_limit - 0, // proof_size_limit + u64::MAX, // ref_time_limit + u64::MAX, // proof_size_limit offset(hash_len), // deposit_ptr offset(deposit_len), // value_ptr offset(value_len), // input_data_ptr diff --git a/substrate/frame/revive/src/gas.rs b/substrate/frame/revive/src/gas.rs index e360a4ad6b2f..5fe2e758c960 100644 --- a/substrate/frame/revive/src/gas.rs +++ b/substrate/frame/revive/src/gas.rs @@ -169,9 +169,10 @@ impl GasMeter { } /// Create a new gas meter for a nested call by removing gas from the current meter. + /// + /// Per [EIP-150](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-150.md), this is + /// capped at 63/64ths of the caller's gas limit. pub fn nested(&mut self, amount: Weight) -> Self { - // The reduction to 63/64 is to emulate EIP-150 - // https://github.com/ethereum/EIPs/blob/master/EIPS/eip-150.md let amt = amount.min(self.gas_left - self.gas_left / 64); self.gas_left -= amt; GasMeter::new(amt) diff --git a/substrate/frame/revive/src/storage/meter.rs b/substrate/frame/revive/src/storage/meter.rs index 13d4de576f01..67a074ac9c66 100644 --- a/substrate/frame/revive/src/storage/meter.rs +++ b/substrate/frame/revive/src/storage/meter.rs @@ -281,20 +281,21 @@ where S: State + Default + Debug, { /// Create a new child that has its `limit`. - /// Passing `0` as the limit is interpreted as to take whatever is remaining from its parent. /// /// This is called whenever a new subcall is initiated in order to track the storage /// usage for this sub call separately. This is necessary because we want to exchange balance /// with the current contract we are interacting with. - pub fn nested(&self, lim: BalanceOf) -> RawMeter { + /// + /// Gas for nested calls are capped to 63/64ths of the caller's originally available limit, per + /// EIP-150. + pub fn nested(&self, limit: BalanceOf) -> RawMeter { debug_assert!(matches!(self.contract_state(), ContractState::Alive)); - // Limit gas for nested call, per EIP-150. let available = self.available() - self.available() / (BalanceOf::::from(64u32)); // If a special limit is specified higher than it is available, // we want to enforce the lesser limit to the nested meter, to fail in the sub-call. - let limit = available.min(lim); + let limit = available.min(limit); RawMeter { limit, nested: Nested::OwnLimit, ..Default::default() } } From d1b40ed4f48bbf62092b8c3688fdd13626027ba6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexandre=20Bald=C3=A9?= Date: Thu, 19 Dec 2024 11:15:19 +0100 Subject: [PATCH 15/34] Run `fmt` --- substrate/frame/revive/src/gas.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/substrate/frame/revive/src/gas.rs b/substrate/frame/revive/src/gas.rs index 5fe2e758c960..264a47993325 100644 --- a/substrate/frame/revive/src/gas.rs +++ b/substrate/frame/revive/src/gas.rs @@ -380,7 +380,8 @@ mod tests { } #[test] - /// Previously, passing a `Weight` of 0 to `nested` would consume all of the meter's current gas. + /// Previously, passing a `Weight` of 0 to `nested` would consume all of the meter's current + /// gas. /// /// Now, a `Weight` of 0 means no gas for the nested call. fn nested_zero_gas_requested() { From 36690cdb21537f3d93d2fa8c9dc71fb9d41ef4e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexandre=20Bald=C3=A9?= Date: Fri, 20 Dec 2024 15:45:21 +0100 Subject: [PATCH 16/34] Address latest PR comments (`enum Nested`) --- .../frame/contracts/src/benchmarking/mod.rs | 8 ++--- substrate/frame/revive/src/exec.rs | 2 +- substrate/frame/revive/src/gas.rs | 8 ++--- substrate/frame/revive/src/storage/meter.rs | 30 ++++--------------- 4 files changed, 15 insertions(+), 33 deletions(-) diff --git a/substrate/frame/contracts/src/benchmarking/mod.rs b/substrate/frame/contracts/src/benchmarking/mod.rs index 47996d2713a8..669279f12b27 100644 --- a/substrate/frame/contracts/src/benchmarking/mod.rs +++ b/substrate/frame/contracts/src/benchmarking/mod.rs @@ -1650,8 +1650,8 @@ mod benchmarks { &mut memory, CallFlags::CLONE_INPUT.bits(), // flags 0, // callee_ptr - u64::MAX, // ref_time_limit - u64::MAX, // proof_size_limit + 0, // ref_time_limit + 0, // proof_size_limit callee_len, // deposit_ptr callee_len + deposit_len, // value_ptr 0, // input_data_ptr @@ -1744,8 +1744,8 @@ mod benchmarks { &mut runtime, &mut memory, 0, // code_hash_ptr - u64::MAX, // ref_time_limit - u64::MAX, // proof_size_limit + 0, // ref_time_limit + 0, // proof_size_limit offset(hash_len), // deposit_ptr offset(deposit_len), // value_ptr offset(value_len), // input_data_ptr diff --git a/substrate/frame/revive/src/exec.rs b/substrate/frame/revive/src/exec.rs index efd9e8e41462..206425e67c55 100644 --- a/substrate/frame/revive/src/exec.rs +++ b/substrate/frame/revive/src/exec.rs @@ -1135,7 +1135,7 @@ where let contract = frame.contract_info.as_contract(); frame .nested_storage - .enforce_subcall_limit(contract) + .enforce_limit(contract) .map_err(|e| ExecError { error: e, origin: ErrorOrigin::Callee })?; let account_id = T::AddressMapper::to_address(&frame.account_id); diff --git a/substrate/frame/revive/src/gas.rs b/substrate/frame/revive/src/gas.rs index 264a47993325..cc04aa3c1dcf 100644 --- a/substrate/frame/revive/src/gas.rs +++ b/substrate/frame/revive/src/gas.rs @@ -173,9 +173,9 @@ impl GasMeter { /// Per [EIP-150](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-150.md), this is /// capped at 63/64ths of the caller's gas limit. pub fn nested(&mut self, amount: Weight) -> Self { - let amt = amount.min(self.gas_left - self.gas_left / 64); - self.gas_left -= amt; - GasMeter::new(amt) + let amount = amount.min(self.gas_left - self.gas_left / 64); + self.gas_left -= amount; + GasMeter::new(amount) } /// Absorb the remaining gas of a nested meter after we are done using it. @@ -379,11 +379,11 @@ mod tests { assert!(gas_meter.charge(SimpleToken(1)).is_err()); } - #[test] /// Previously, passing a `Weight` of 0 to `nested` would consume all of the meter's current /// gas. /// /// Now, a `Weight` of 0 means no gas for the nested call. + #[test] fn nested_zero_gas_requested() { let test_weight = 50000.into(); let mut gas_meter = GasMeter::::new(test_weight); diff --git a/substrate/frame/revive/src/storage/meter.rs b/substrate/frame/revive/src/storage/meter.rs index 67a074ac9c66..82051dd6e592 100644 --- a/substrate/frame/revive/src/storage/meter.rs +++ b/substrate/frame/revive/src/storage/meter.rs @@ -100,13 +100,8 @@ pub trait State: private::Sealed {} pub struct Root; /// State parameter that constitutes a meter that is in its nested state. -/// Its value indicates whether the nested meter has its own limit. -#[derive(DefaultNoBound, RuntimeDebugNoBound)] -pub enum Nested { - #[default] - DerivedLimit, - OwnLimit, -} +#[derive(Default, Debug)] +pub struct Nested; impl State for Root {} impl State for Nested {} @@ -126,7 +121,7 @@ pub struct RawMeter { /// limited by the maximum call depth. charges: Vec>, /// We store the nested state to determine if it has a special limit for sub-call. - nested: S, + _nested: PhantomData, /// Type parameter only used in impls. _phantom: PhantomData, } @@ -296,7 +291,7 @@ where // If a special limit is specified higher than it is available, // we want to enforce the lesser limit to the nested meter, to fail in the sub-call. let limit = available.min(limit); - RawMeter { limit, nested: Nested::OwnLimit, ..Default::default() } + RawMeter { limit, ..Default::default() } } /// Absorb a child that was spawned to handle a sub call. @@ -483,8 +478,7 @@ impl> RawMeter { /// /// We normally need to call this **once** for every call stack and not for every cross contract /// call. However, if a dedicated limit is specified for a sub-call, this needs to be called - /// once the sub-call has returned. For this, the [`Self::enforce_subcall_limit`] wrapper is - /// used. + /// once the sub-call has returned. pub fn enforce_limit( &mut self, info: Option<&mut ContractInfo>, @@ -503,18 +497,6 @@ impl> RawMeter { } Ok(()) } - - /// This is a wrapper around [`Self::enforce_limit`] to use on the exit from a sub-call to - /// enforce its special limit if needed. - pub fn enforce_subcall_limit( - &mut self, - info: Option<&mut ContractInfo>, - ) -> Result<(), DispatchError> { - match self.nested { - Nested::OwnLimit => self.enforce_limit(info), - Nested::DerivedLimit => Ok(()), - } - } } impl Ext for ReservingExt { @@ -725,10 +707,10 @@ mod tests { ) } - #[test] /// Previously, passing a limit of 0 meant unlimited storage for a nested call. /// /// Now, a limit of 0 means the subcall will not be able to use any storage. + #[test] fn nested_zero_limit_requested() { clear_ext(); From 2c8f49206af561e88039ec1d1d785953ea90e988 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexandre=20Bald=C3=A9?= Date: Sat, 21 Dec 2024 00:36:33 +0100 Subject: [PATCH 17/34] Refactor `RawMeter/Nested` --- substrate/frame/revive/src/exec.rs | 18 ++++++++++++++++-- substrate/frame/revive/src/gas.rs | 6 ++++++ substrate/frame/revive/src/storage/meter.rs | 4 ++++ 3 files changed, 26 insertions(+), 2 deletions(-) diff --git a/substrate/frame/revive/src/exec.rs b/substrate/frame/revive/src/exec.rs index 206425e67c55..fc674fe3b632 100644 --- a/substrate/frame/revive/src/exec.rs +++ b/substrate/frame/revive/src/exec.rs @@ -890,6 +890,7 @@ where BalanceOf::::max_value(), false, true, + true )? else { return Ok(None); @@ -925,6 +926,7 @@ where deposit_limit: BalanceOf, read_only: bool, origin_is_caller: bool, + is_root: bool, ) -> Result, E)>, ExecError> { let (account_id, contract_info, executable, delegate, entry_point) = match frame_args { FrameArgs::Call { dest, cached_info, delegated_call } => { @@ -982,14 +984,25 @@ where }, }; + let nested_gas; + let nested_storage; + + if is_root { + nested_gas = gas_meter.take_all(); + nested_storage = storage_meter.take_all(); + } else { + nested_gas = gas_meter.nested(gas_limit); + nested_storage = storage_meter.nested(deposit_limit); + } + let frame = Frame { delegate, value_transferred, contract_info: CachedContract::Cached(contract_info), account_id, entry_point, - nested_gas: gas_meter.nested(gas_limit), - nested_storage: storage_meter.nested(deposit_limit), + nested_gas, + nested_storage, allows_reentry: true, read_only, last_frame_output: Default::default(), @@ -1037,6 +1050,7 @@ where deposit_limit, read_only, false, + false )? { self.frames.try_push(frame).map_err(|_| Error::::MaxCallDepthReached)?; Ok(Some(executable)) diff --git a/substrate/frame/revive/src/gas.rs b/substrate/frame/revive/src/gas.rs index cc04aa3c1dcf..767165e8f647 100644 --- a/substrate/frame/revive/src/gas.rs +++ b/substrate/frame/revive/src/gas.rs @@ -168,6 +168,12 @@ impl GasMeter { } } + pub(crate) fn take_all(&mut self) -> Self { + let gas_left = self.gas_left; + self.gas_left -= gas_left; + GasMeter::new(gas_left) + } + /// Create a new gas meter for a nested call by removing gas from the current meter. /// /// Per [EIP-150](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-150.md), this is diff --git a/substrate/frame/revive/src/storage/meter.rs b/substrate/frame/revive/src/storage/meter.rs index 82051dd6e592..e5319e3cd670 100644 --- a/substrate/frame/revive/src/storage/meter.rs +++ b/substrate/frame/revive/src/storage/meter.rs @@ -343,6 +343,10 @@ where _ => ContractState::Alive, } } + + pub(crate) fn take_all(&self) -> RawMeter { + RawMeter { limit: self.available(), ..Default::default() } + } } /// Functions that only apply to the root state. From 12473b44e30280ff752b1c662942db443d38abd9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexandre=20Bald=C3=A9?= Date: Sat, 21 Dec 2024 00:45:18 +0100 Subject: [PATCH 18/34] Run `fmt` --- substrate/frame/revive/src/exec.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/substrate/frame/revive/src/exec.rs b/substrate/frame/revive/src/exec.rs index fc674fe3b632..b3292d703400 100644 --- a/substrate/frame/revive/src/exec.rs +++ b/substrate/frame/revive/src/exec.rs @@ -890,7 +890,7 @@ where BalanceOf::::max_value(), false, true, - true + true, )? else { return Ok(None); @@ -1050,7 +1050,7 @@ where deposit_limit, read_only, false, - false + false, )? { self.frames.try_push(frame).map_err(|_| Error::::MaxCallDepthReached)?; Ok(Some(executable)) From 2f8ab21678c0b23c940f5161626a69f2647d4d35 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexandre=20Bald=C3=A9?= Date: Fri, 3 Jan 2025 13:45:37 +0000 Subject: [PATCH 19/34] Address latest review --- substrate/frame/revive/src/exec.rs | 20 +++----------------- substrate/frame/revive/src/gas.rs | 6 +++++- substrate/frame/revive/src/storage/meter.rs | 6 +++++- 3 files changed, 13 insertions(+), 19 deletions(-) diff --git a/substrate/frame/revive/src/exec.rs b/substrate/frame/revive/src/exec.rs index 0ff15811ebfe..f6ec3841d69f 100644 --- a/substrate/frame/revive/src/exec.rs +++ b/substrate/frame/revive/src/exec.rs @@ -890,7 +890,6 @@ where BalanceOf::::max_value(), false, true, - true, )? else { return Ok(None); @@ -926,7 +925,6 @@ where deposit_limit: BalanceOf, read_only: bool, origin_is_caller: bool, - is_root: bool, ) -> Result, E)>, ExecError> { let (account_id, contract_info, executable, delegate, entry_point) = match frame_args { FrameArgs::Call { dest, cached_info, delegated_call } => { @@ -987,9 +985,9 @@ where let nested_gas; let nested_storage; - if is_root { - nested_gas = gas_meter.take_all(); - nested_storage = storage_meter.take_all(); + if origin_is_caller { + nested_gas = gas_meter.nested_take_all(); + nested_storage = storage_meter.nested_take_all(); } else { nested_gas = gas_meter.nested(gas_limit); nested_storage = storage_meter.nested(deposit_limit); @@ -1050,7 +1048,6 @@ where deposit_limit, read_only, false, - false, )? { self.frames.try_push(frame).map_err(|_| Error::::MaxCallDepthReached)?; Ok(Some(executable)) @@ -1131,17 +1128,6 @@ where return Ok(output); } - // Storage limit is normally enforced as late as possible (when the last frame returns) - // so that the ordering of storage accesses does not matter. - // (However, if a special limit was set for a sub-call, it should be enforced right - // after the sub-call returned. See below for this case of enforcement). - if self.frames.is_empty() { - let frame = &mut self.first_frame; - frame.contract_info.load(&frame.account_id); - let contract = frame.contract_info.as_contract(); - frame.nested_storage.enforce_limit(contract)?; - } - let frame = self.top_frame_mut(); // If a special limit was set for the sub-call, we enforce it here. diff --git a/substrate/frame/revive/src/gas.rs b/substrate/frame/revive/src/gas.rs index 767165e8f647..d0fc604b7bc6 100644 --- a/substrate/frame/revive/src/gas.rs +++ b/substrate/frame/revive/src/gas.rs @@ -168,7 +168,11 @@ impl GasMeter { } } - pub(crate) fn take_all(&mut self) -> Self { + /// Create a new gas meter by removing *all* the gas from the current meter. + /// + /// This should only be used by the primordial frame in a sequence of calls - every subsequent + /// frame should use [`nested`](Self::nested). + pub fn nested_take_all(&mut self) -> Self { let gas_left = self.gas_left; self.gas_left -= gas_left; GasMeter::new(gas_left) diff --git a/substrate/frame/revive/src/storage/meter.rs b/substrate/frame/revive/src/storage/meter.rs index e5319e3cd670..47036d79bbdf 100644 --- a/substrate/frame/revive/src/storage/meter.rs +++ b/substrate/frame/revive/src/storage/meter.rs @@ -344,7 +344,11 @@ where } } - pub(crate) fn take_all(&self) -> RawMeter { + /// Create a new storage meter using the calling meter's available limit. + /// + /// This should only be used by the primordial frame in a sequence of calls - every subsequent + /// frame should use [`nested`](Self::nested) + pub fn nested_take_all(&self) -> RawMeter { RawMeter { limit: self.available(), ..Default::default() } } } From acfcf6622038d249249416ae25b149aea65a0cce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexandre=20Bald=C3=A9?= Date: Fri, 3 Jan 2025 17:39:18 +0000 Subject: [PATCH 20/34] Fix tests `delegate_call` and `deposit_limit_in_nested_calls` --- substrate/frame/revive/src/tests.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/substrate/frame/revive/src/tests.rs b/substrate/frame/revive/src/tests.rs index 664578bf7672..e6cb312a0904 100644 --- a/substrate/frame/revive/src/tests.rs +++ b/substrate/frame/revive/src/tests.rs @@ -1149,7 +1149,7 @@ fn delegate_call() { assert_ok!(builder::call(caller_addr) .value(1337) - .data((callee_addr, 0u64, 0u64).encode()) + .data((callee_addr, u64::MAX, u64::MAX).encode()) .build()); }); } @@ -3453,13 +3453,13 @@ fn deposit_limit_in_nested_calls() { // We do not remove any storage but add a storage item of 12 bytes in the caller // contract. This would cost 12 + 2 = 14 Balance. - // The nested call doesn't get a special limit, which is set by passing 0 to it. + // The nested call doesn't get a special limit, which is set by passing `u64::MAX` to it. // This should fail as the specified parent's limit is less than the cost: 13 < // 14. assert_err_ignore_postinfo!( builder::call(addr_caller) .storage_deposit_limit(13) - .data((100u32, &addr_callee, U256::from(0u64)).encode()) + .data((100u32, &addr_callee, U256::from(u64::MAX)).encode()) .build(), >::StorageDepositLimitExhausted, ); @@ -3467,13 +3467,13 @@ fn deposit_limit_in_nested_calls() { // Now we specify the parent's limit high enough to cover the caller's storage // additions. However, we use a single byte more in the callee, hence the storage // deposit should be 15 Balance. - // The nested call doesn't get a special limit, which is set by passing 0 to it. + // The nested call doesn't get a special limit, which is set by passing `u64::MAX` to it. // This should fail as the specified parent's limit is less than the cost: 14 // < 15. assert_err_ignore_postinfo!( builder::call(addr_caller) .storage_deposit_limit(14) - .data((101u32, &addr_callee, U256::from(0u64)).encode()) + .data((101u32, &addr_callee, U256::from(u64::MAX)).encode()) .build(), >::StorageDepositLimitExhausted, ); @@ -3495,7 +3495,7 @@ fn deposit_limit_in_nested_calls() { assert_err_ignore_postinfo!( builder::call(addr_caller) .storage_deposit_limit(0) - .data((87u32, &addr_callee, U256::from(0u64)).encode()) + .data((87u32, &addr_callee, U256::from(u64::MAX)).encode()) .build(), >::StorageDepositLimitExhausted, ); From e0c08459ee574e412d2da7a1b79eebaee6bd63a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexandre=20Bald=C3=A9?= Date: Fri, 3 Jan 2025 19:14:59 +0000 Subject: [PATCH 21/34] Fix `tests::deposit_limit_in_nested_instantiate` Use `BareCallBuilder::bare_call` instead of `CallBuilder::call` to allow scrutiny of contract return code with `assert_return_code`, and disambiguate the cause of the `ContractReverted` error that `CallBuilder::build` would have raised. --- substrate/frame/revive/src/tests.rs | 28 ++++++++++++---------------- 1 file changed, 12 insertions(+), 16 deletions(-) diff --git a/substrate/frame/revive/src/tests.rs b/substrate/frame/revive/src/tests.rs index e6cb312a0904..1bf24d30afd1 100644 --- a/substrate/frame/revive/src/tests.rs +++ b/substrate/frame/revive/src/tests.rs @@ -3551,28 +3551,24 @@ fn deposit_limit_in_nested_instantiate() { // // Provided the limit is set to be 1 Balance less, // this call should fail on the return from the caller contract. - assert_err_ignore_postinfo!( - builder::call(addr_caller) - .origin(RuntimeOrigin::signed(BOB)) - .storage_deposit_limit(callee_info_len + 2 + ED + 1) - .data((0u32, &code_hash_callee, U256::from(0u64)).encode()) - .build(), - >::StorageDepositLimitExhausted, - ); + let ret = builder::bare_call(addr_caller) + .origin(RuntimeOrigin::signed(BOB)) + .storage_deposit_limit(DepositLimit::Balance(callee_info_len + 2 + ED + 1)) + .data((0u32, &code_hash_callee, U256::from(u64::MAX)).encode()) + .build_and_unwrap_result(); + assert_return_code!(ret, RuntimeReturnCode::OutOfResources); // The charges made on instantiation should be rolled back. assert_eq!(::Currency::free_balance(&BOB), 1_000_000); // Now we give enough limit for the instantiation itself, but require for 1 more storage // byte in the constructor. Hence +1 Balance to the limit is needed. This should fail on // the return from constructor. - assert_err_ignore_postinfo!( - builder::call(addr_caller) - .origin(RuntimeOrigin::signed(BOB)) - .storage_deposit_limit(callee_info_len + 2 + ED + 2) - .data((1u32, &code_hash_callee, U256::from(0u64)).encode()) - .build(), - >::StorageDepositLimitExhausted, - ); + let ret = builder::bare_call(addr_caller) + .origin(RuntimeOrigin::signed(BOB)) + .storage_deposit_limit(DepositLimit::Balance(callee_info_len + 2 + ED + 2)) + .data((1u32, &code_hash_callee, U256::from(0u64)).encode()) + .build_and_unwrap_result(); + assert_return_code!(ret, RuntimeReturnCode::OutOfResources); // The charges made on the instantiation should be rolled back. assert_eq!(::Currency::free_balance(&BOB), 1_000_000); From b090e5f4bd80f44b12f26bb958619254d28c298f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexandre=20Bald=C3=A9?= Date: Mon, 6 Jan 2025 14:19:50 +0000 Subject: [PATCH 22/34] Address review comments --- substrate/frame/revive/src/exec.rs | 5 +++-- substrate/frame/revive/src/storage/meter.rs | 10 +--------- 2 files changed, 4 insertions(+), 11 deletions(-) diff --git a/substrate/frame/revive/src/exec.rs b/substrate/frame/revive/src/exec.rs index f6ec3841d69f..359d9608e940 100644 --- a/substrate/frame/revive/src/exec.rs +++ b/substrate/frame/revive/src/exec.rs @@ -1130,8 +1130,9 @@ where let frame = self.top_frame_mut(); - // If a special limit was set for the sub-call, we enforce it here. - // The sub-call will be rolled back in case the limit is exhausted. + // The storage deposit is only charged at the end of every call stack. + // To make sure that no sub call uses more than it is allowed to, + // the limit is manually enforced here. let contract = frame.contract_info.as_contract(); frame .nested_storage diff --git a/substrate/frame/revive/src/storage/meter.rs b/substrate/frame/revive/src/storage/meter.rs index 47036d79bbdf..aa198cfced94 100644 --- a/substrate/frame/revive/src/storage/meter.rs +++ b/substrate/frame/revive/src/storage/meter.rs @@ -120,10 +120,8 @@ 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>, - /// We store the nested state to determine if it has a special limit for sub-call. - _nested: PhantomData, /// Type parameter only used in impls. - _phantom: PhantomData, + _phantom: PhantomData<(E, S)>, } /// This type is used to describe a storage change when charging from the meter. @@ -481,12 +479,6 @@ impl> RawMeter { /// [`Self::charge`] does not enforce the storage limit since we want to do this check as late /// as possible to allow later refunds to offset earlier charges. - /// - /// # Note - /// - /// We normally need to call this **once** for every call stack and not for every cross contract - /// call. However, if a dedicated limit is specified for a sub-call, this needs to be called - /// once the sub-call has returned. pub fn enforce_limit( &mut self, info: Option<&mut ContractInfo>, From 0be40198c519b058df87044ee2233829ec5bafac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexandre=20Bald=C3=A9?= Date: Mon, 6 Jan 2025 15:23:39 +0000 Subject: [PATCH 23/34] Change default deposit limit in WASM runtime checks A limit of `0` no longer signifies "no limit", and must thus be changed to `u64::MAX`. --- substrate/frame/revive/src/wasm/runtime.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/substrate/frame/revive/src/wasm/runtime.rs b/substrate/frame/revive/src/wasm/runtime.rs index 52f79f2eb55a..393f1a5d923a 100644 --- a/substrate/frame/revive/src/wasm/runtime.rs +++ b/substrate/frame/revive/src/wasm/runtime.rs @@ -1005,7 +1005,7 @@ impl<'a, E: Ext, M: ?Sized + Memory> Runtime<'a, E, M> { let callee = memory.read_h160(callee_ptr)?; let deposit_limit = - if deposit_ptr == SENTINEL { U256::zero() } else { memory.read_u256(deposit_ptr)? }; + if deposit_ptr == SENTINEL { U256::from(u64::MAX) } else { memory.read_u256(deposit_ptr)? }; let input_data = if flags.contains(CallFlags::CLONE_INPUT) { let input = self.input_data.as_ref().ok_or(Error::::InputForwarded)?; @@ -1092,7 +1092,7 @@ impl<'a, E: Ext, M: ?Sized + Memory> Runtime<'a, E, M> { ) -> Result { self.charge_gas(RuntimeCosts::Instantiate { input_data_len })?; let deposit_limit: U256 = - if deposit_ptr == SENTINEL { U256::zero() } else { memory.read_u256(deposit_ptr)? }; + if deposit_ptr == SENTINEL { U256::from(u64::MAX) } else { memory.read_u256(deposit_ptr)? }; let value = memory.read_u256(value_ptr)?; let code_hash = memory.read_h256(code_hash_ptr)?; let input_data = memory.read(input_data_ptr, input_data_len)?; From c3b9510114bddeda5e2a89f1f5fcfefb63d1ff01 Mon Sep 17 00:00:00 2001 From: command-bot <> Date: Mon, 6 Jan 2025 15:42:52 +0000 Subject: [PATCH 24/34] Update from rockbmb running command 'fmt' --- substrate/frame/revive/src/wasm/runtime.rs | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/substrate/frame/revive/src/wasm/runtime.rs b/substrate/frame/revive/src/wasm/runtime.rs index 393f1a5d923a..ebc7e211fc70 100644 --- a/substrate/frame/revive/src/wasm/runtime.rs +++ b/substrate/frame/revive/src/wasm/runtime.rs @@ -1004,8 +1004,11 @@ impl<'a, E: Ext, M: ?Sized + Memory> Runtime<'a, E, M> { self.charge_gas(call_type.cost())?; let callee = memory.read_h160(callee_ptr)?; - let deposit_limit = - if deposit_ptr == SENTINEL { U256::from(u64::MAX) } else { memory.read_u256(deposit_ptr)? }; + let deposit_limit = if deposit_ptr == SENTINEL { + U256::from(u64::MAX) + } else { + memory.read_u256(deposit_ptr)? + }; let input_data = if flags.contains(CallFlags::CLONE_INPUT) { let input = self.input_data.as_ref().ok_or(Error::::InputForwarded)?; @@ -1091,8 +1094,11 @@ impl<'a, E: Ext, M: ?Sized + Memory> Runtime<'a, E, M> { salt_ptr: u32, ) -> Result { self.charge_gas(RuntimeCosts::Instantiate { input_data_len })?; - let deposit_limit: U256 = - if deposit_ptr == SENTINEL { U256::from(u64::MAX) } else { memory.read_u256(deposit_ptr)? }; + let deposit_limit: U256 = if deposit_ptr == SENTINEL { + U256::from(u64::MAX) + } else { + memory.read_u256(deposit_ptr)? + }; let value = memory.read_u256(value_ptr)?; let code_hash = memory.read_h256(code_hash_ptr)?; let input_data = memory.read(input_data_ptr, input_data_len)?; From 7531f72eee895357c07c33bad067919c0302117e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexandre=20Bald=C3=A9?= Date: Mon, 6 Jan 2025 18:28:57 +0000 Subject: [PATCH 25/34] Update deposit limit in benchmark A deposit limit of 0 no longer is a special case, and is treated as no limit being available for use in a benchmarking function. --- substrate/frame/revive/src/benchmarking/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/substrate/frame/revive/src/benchmarking/mod.rs b/substrate/frame/revive/src/benchmarking/mod.rs index a4c5767df27c..2cf856f5f0f2 100644 --- a/substrate/frame/revive/src/benchmarking/mod.rs +++ b/substrate/frame/revive/src/benchmarking/mod.rs @@ -1715,7 +1715,7 @@ mod benchmarks { let value_bytes = Into::::into(value).encode(); let value_len = value_bytes.len() as u32; - let deposit: BalanceOf = 0u32.into(); + let deposit: BalanceOf = u32::MAX.into(); let deposit_bytes = Into::::into(deposit).encode(); let deposit_len = deposit_bytes.len() as u32; From 11c8858d343aa7a9edf6c14ba9c694866c49bdd3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexandre=20Bald=C3=A9?= Date: Tue, 7 Jan 2025 14:48:07 +0000 Subject: [PATCH 26/34] Modify how deposit limits are stored in `revive/uapi` --- .../frame/revive/fixtures/contracts/call.rs | 10 ++-- .../contracts/call_diverging_out_len.rs | 6 +-- .../fixtures/contracts/call_return_code.rs | 10 ++-- .../contracts/call_runtime_and_call.rs | 10 ++-- .../contracts/call_with_flags_and_value.rs | 4 +- .../fixtures/contracts/call_with_limit.rs | 6 +-- .../fixtures/contracts/caller_contract.rs | 50 +++++++++---------- .../contracts/chain_extension_temp_storage.rs | 10 ++-- .../fixtures/contracts/create1_with_value.rs | 4 +- .../contracts/create_storage_and_call.rs | 8 +-- .../create_storage_and_instantiate.rs | 2 +- .../create_transient_storage_and_call.rs | 10 ++-- .../fixtures/contracts/delegate_call.rs | 12 ++++- .../contracts/delegate_call_deposit_limit.rs | 10 +++- .../contracts/delegate_call_simple.rs | 12 ++++- .../contracts/destroy_and_transfer.rs | 20 ++++---- .../frame/revive/fixtures/contracts/drain.rs | 4 +- .../contracts/instantiate_return_code.rs | 8 +-- .../contracts/locking_delegate_dependency.rs | 4 +- .../frame/revive/fixtures/contracts/origin.rs | 4 +- .../fixtures/contracts/read_only_call.rs | 10 ++-- .../revive/fixtures/contracts/recurse.rs | 10 ++-- .../fixtures/contracts/return_data_api.rs | 18 +++++-- .../fixtures/contracts/self_destruct.rs | 10 ++-- .../contracts/transfer_return_code.rs | 4 +- substrate/frame/revive/src/wasm/runtime.rs | 12 +---- substrate/frame/revive/uapi/src/host.rs | 6 +-- .../frame/revive/uapi/src/host/riscv64.rs | 12 ++--- substrate/frame/revive/uapi/src/lib.rs | 21 ++++++++ 29 files changed, 176 insertions(+), 131 deletions(-) diff --git a/substrate/frame/revive/fixtures/contracts/call.rs b/substrate/frame/revive/fixtures/contracts/call.rs index 2b41b7d8fe09..c93d951d37dc 100644 --- a/substrate/frame/revive/fixtures/contracts/call.rs +++ b/substrate/frame/revive/fixtures/contracts/call.rs @@ -20,7 +20,7 @@ #![no_main] use common::input; -use uapi::{HostFn, HostFnImpl as api}; +use uapi::{HostFn, HostFnImpl as api, U64_MAX_AS_U256}; #[no_mangle] #[polkavm_derive::polkavm_export] @@ -38,10 +38,10 @@ pub extern "C" fn call() { 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. - None, // No deposit limit. - &[0u8; 32], // Value transferred to the contract. + 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. + &U64_MAX_AS_U256, // No deposit limit. + &[0u8; 32], // Value transferred to the contract. callee_input, None, ) diff --git a/substrate/frame/revive/fixtures/contracts/call_diverging_out_len.rs b/substrate/frame/revive/fixtures/contracts/call_diverging_out_len.rs index 1e9048588c5c..463130a2f8f0 100644 --- a/substrate/frame/revive/fixtures/contracts/call_diverging_out_len.rs +++ b/substrate/frame/revive/fixtures/contracts/call_diverging_out_len.rs @@ -28,7 +28,7 @@ extern crate common; -use uapi::{HostFn, HostFnImpl as api}; +use uapi::{HostFn, HostFnImpl as api, U64_MAX_AS_U256}; const BUF_SIZE: usize = 8; static DATA: [u8; BUF_SIZE] = [1, 2, 3, 4, 5, 6, 7, 8]; @@ -44,7 +44,7 @@ fn assert_call(callee_address: &[u8; 20], expected_output: [u8; callee_address, u64::MAX, u64::MAX, - None, + &U64_MAX_AS_U256, &[0u8; 32], &[], Some(output_buf_capped), @@ -69,7 +69,7 @@ fn assert_instantiate(expected_output: [u8; BUF_SIZE]) { &code_hash, u64::MAX, u64::MAX, - None, + &U64_MAX_AS_U256, &[0; 32], &[0; 32], None, diff --git a/substrate/frame/revive/fixtures/contracts/call_return_code.rs b/substrate/frame/revive/fixtures/contracts/call_return_code.rs index 4cbc925eaaed..3594aa79740f 100644 --- a/substrate/frame/revive/fixtures/contracts/call_return_code.rs +++ b/substrate/frame/revive/fixtures/contracts/call_return_code.rs @@ -22,7 +22,7 @@ #![no_main] use common::input; -use uapi::{HostFn, HostFnImpl as api}; +use uapi::{HostFn, HostFnImpl as api, U64_MAX_AS_U256}; #[no_mangle] #[polkavm_derive::polkavm_export] @@ -42,10 +42,10 @@ pub extern "C" fn call() { let err_code = match 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. - None, // No deposit limit. - value, // Value transferred to the contract. + 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. + &U64_MAX_AS_U256, // No deposit limit. + value, // Value transferred to the contract. input, None, ) { diff --git a/substrate/frame/revive/fixtures/contracts/call_runtime_and_call.rs b/substrate/frame/revive/fixtures/contracts/call_runtime_and_call.rs index a3e1c2394cfd..cec94d18003c 100644 --- a/substrate/frame/revive/fixtures/contracts/call_runtime_and_call.rs +++ b/substrate/frame/revive/fixtures/contracts/call_runtime_and_call.rs @@ -19,7 +19,7 @@ #![no_main] use common::input; -use uapi::{HostFn, HostFnImpl as api}; +use uapi::{HostFn, HostFnImpl as api, U64_MAX_AS_U256}; #[no_mangle] #[polkavm_derive::polkavm_export] @@ -42,10 +42,10 @@ pub extern "C" fn call() { 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. - None, // No deposit limit. - &[0u8; 32], // Value transferred to the contract. + 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. + &U64_MAX_AS_U256, // No deposit limit. + &[0u8; 32], // Value transferred to the contract. callee_input, None, ) diff --git a/substrate/frame/revive/fixtures/contracts/call_with_flags_and_value.rs b/substrate/frame/revive/fixtures/contracts/call_with_flags_and_value.rs index 703dd00fb7f9..5f430a625219 100644 --- a/substrate/frame/revive/fixtures/contracts/call_with_flags_and_value.rs +++ b/substrate/frame/revive/fixtures/contracts/call_with_flags_and_value.rs @@ -20,7 +20,7 @@ #![no_main] use common::{input, u256_bytes}; -use uapi::{HostFn, HostFnImpl as api}; +use uapi::{HostFn, HostFnImpl as api, U64_MAX_AS_U256}; #[no_mangle] #[polkavm_derive::polkavm_export] @@ -42,7 +42,7 @@ pub extern "C" fn call() { 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. - None, // No deposit limit. + &U64_MAX_AS_U256, // No deposit limit. &u256_bytes(value), // Value transferred to the contract. forwarded_input, None, diff --git a/substrate/frame/revive/fixtures/contracts/call_with_limit.rs b/substrate/frame/revive/fixtures/contracts/call_with_limit.rs index 6ab892a6b7ae..10a6b7a90e96 100644 --- a/substrate/frame/revive/fixtures/contracts/call_with_limit.rs +++ b/substrate/frame/revive/fixtures/contracts/call_with_limit.rs @@ -21,7 +21,7 @@ #![no_main] use common::input; -use uapi::{HostFn, HostFnImpl as api}; +use uapi::{HostFn, HostFnImpl as api, U64_MAX_AS_U256}; #[no_mangle] #[polkavm_derive::polkavm_export] @@ -43,8 +43,8 @@ pub extern "C" fn call() { callee_addr, ref_time, proof_size, - None, // No deposit limit. - &[0u8; 32], // value transferred to the contract. + &U64_MAX_AS_U256, // No deposit limit. + &[0u8; 32], // value transferred to the contract. forwarded_input, None, ) diff --git a/substrate/frame/revive/fixtures/contracts/caller_contract.rs b/substrate/frame/revive/fixtures/contracts/caller_contract.rs index e5cbbc116997..7609ca270449 100644 --- a/substrate/frame/revive/fixtures/contracts/caller_contract.rs +++ b/substrate/frame/revive/fixtures/contracts/caller_contract.rs @@ -19,7 +19,7 @@ #![no_main] use common::{input, u256_bytes}; -use uapi::{HostFn, HostFnImpl as api, ReturnErrorCode}; +use uapi::{HostFn, HostFnImpl as api, ReturnErrorCode, U64_MAX_AS_U256}; #[no_mangle] #[polkavm_derive::polkavm_export] @@ -42,9 +42,9 @@ pub extern "C" fn call() { // Fail to deploy the contract since it returns a non-zero exit status. let res = api::instantiate( code_hash, - u64::MAX, // How much ref_time weight to devote for the execution. u64::MAX = use all. - u64::MAX, // How much proof_size weight to devote for the execution. u64::MAX = use all. - None, // No deposit limit. + u64::MAX, // How much ref_time weight to devote for the execution. u64::MAX = use all. + u64::MAX, // How much proof_size weight to devote for the execution. u64::MAX = use all. + &U64_MAX_AS_U256, // No deposit limit. &value, &reverted_input, None, @@ -56,9 +56,9 @@ pub extern "C" fn call() { // Fail to deploy the contract due to insufficient ref_time weight. let res = api::instantiate( code_hash, - 1u64, // too little ref_time weight - u64::MAX, // How much proof_size weight to devote for the execution. u64::MAX = use all. - None, // No deposit limit. + 1u64, // too little ref_time weight + u64::MAX, // How much proof_size weight to devote for the execution. u64::MAX = use all. + &U64_MAX_AS_U256, // No deposit limit. &value, &input, None, @@ -70,9 +70,9 @@ pub extern "C" fn call() { // Fail to deploy the contract due to insufficient proof_size weight. let res = api::instantiate( code_hash, - u64::MAX, // How much ref_time weight to devote for the execution. u64::MAX = use all. - 1u64, // Too little proof_size weight - None, // No deposit limit. + u64::MAX, // How much ref_time weight to devote for the execution. u64::MAX = use all. + 1u64, // Too little proof_size weight + &U64_MAX_AS_U256, // No deposit limit. &value, &input, None, @@ -86,9 +86,9 @@ pub extern "C" fn call() { api::instantiate( code_hash, - u64::MAX, // How much ref_time weight to devote for the execution. u64::MAX = use all. - u64::MAX, // How much proof_size weight to devote for the execution. u64::MAX = use all. - None, // No deposit limit. + u64::MAX, // How much ref_time weight to devote for the execution. u64::MAX = use all. + u64::MAX, // How much proof_size weight to devote for the execution. u64::MAX = use all. + &U64_MAX_AS_U256, // No deposit limit. &value, &input, Some(&mut callee), @@ -101,9 +101,9 @@ pub extern "C" fn call() { let res = api::call( uapi::CallFlags::empty(), &callee, - u64::MAX, // How much ref_time weight to devote for the execution. u64::MAX = use all. - u64::MAX, // How much proof_size weight to devote for the execution. u64::MAX = use all. - None, // No deposit limit. + u64::MAX, // How much ref_time weight to devote for the execution. u64::MAX = use all. + u64::MAX, // How much proof_size weight to devote for the execution. u64::MAX = use all. + &U64_MAX_AS_U256, // No deposit limit. &value, &reverted_input, None, @@ -114,9 +114,9 @@ pub extern "C" fn call() { let res = api::call( uapi::CallFlags::empty(), &callee, - 1u64, // Too little ref_time weight. - u64::MAX, // How much proof_size weight to devote for the execution. u64::MAX = use all. - None, // No deposit limit. + 1u64, // Too little ref_time weight. + u64::MAX, // How much proof_size weight to devote for the execution. u64::MAX = use all. + &U64_MAX_AS_U256, // No deposit limit. &value, &input, None, @@ -127,9 +127,9 @@ pub extern "C" fn call() { let res = api::call( uapi::CallFlags::empty(), &callee, - u64::MAX, // How much ref_time weight to devote for the execution. u64::MAX = use all. - 1u64, // too little proof_size weight - None, // No deposit limit. + u64::MAX, // How much ref_time weight to devote for the execution. u64::MAX = use all. + 1u64, // too little proof_size weight + &U64_MAX_AS_U256, // No deposit limit. &value, &input, None, @@ -141,9 +141,9 @@ pub extern "C" fn call() { api::call( uapi::CallFlags::empty(), &callee, - u64::MAX, // How much ref_time weight to devote for the execution. u64::MAX = use all. - u64::MAX, // How much proof_size weight to devote for the execution. u64::MAX = use all. - None, // No deposit limit. + u64::MAX, // How much ref_time weight to devote for the execution. u64::MAX = use all. + u64::MAX, // How much proof_size weight to devote for the execution. u64::MAX = use all. + &U64_MAX_AS_U256, // No deposit limit. &value, &input, Some(&mut &mut output[..]), diff --git a/substrate/frame/revive/fixtures/contracts/chain_extension_temp_storage.rs b/substrate/frame/revive/fixtures/contracts/chain_extension_temp_storage.rs index a6e4720c0563..f949aa09ad7b 100644 --- a/substrate/frame/revive/fixtures/contracts/chain_extension_temp_storage.rs +++ b/substrate/frame/revive/fixtures/contracts/chain_extension_temp_storage.rs @@ -21,7 +21,7 @@ #![no_main] use common::input; -use uapi::{HostFn, HostFnImpl as api}; +use uapi::{HostFn, HostFnImpl as api, U64_MAX_AS_U256}; #[no_mangle] #[polkavm_derive::polkavm_export] @@ -54,10 +54,10 @@ pub extern "C" fn call() { api::call( uapi::CallFlags::ALLOW_REENTRY, &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. - None, // No deposit limit. - &[0u8; 32], // Value transferred to the contract. + 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. + &U64_MAX_AS_U256, // No deposit limit. + &[0u8; 32], // Value transferred to the contract. input, None, ) diff --git a/substrate/frame/revive/fixtures/contracts/create1_with_value.rs b/substrate/frame/revive/fixtures/contracts/create1_with_value.rs index 29c7b9f2ed81..afeaaec020b0 100644 --- a/substrate/frame/revive/fixtures/contracts/create1_with_value.rs +++ b/substrate/frame/revive/fixtures/contracts/create1_with_value.rs @@ -19,7 +19,7 @@ #![no_main] use common::input; -use uapi::{HostFn, HostFnImpl as api}; +use uapi::{HostFn, HostFnImpl as api, U64_MAX_AS_U256}; #[no_mangle] #[polkavm_derive::polkavm_export] @@ -34,6 +34,6 @@ pub extern "C" fn call() { api::value_transferred(&mut value); // Deploy the contract with no salt (equivalent to create1). - let ret = api::instantiate(code_hash, u64::MAX, u64::MAX, None, &value, &[], None, None, None); + let ret = api::instantiate(code_hash, u64::MAX, u64::MAX, &U64_MAX_AS_U256, &value, &[], None, None, None); assert!(ret.is_ok()); } diff --git a/substrate/frame/revive/fixtures/contracts/create_storage_and_call.rs b/substrate/frame/revive/fixtures/contracts/create_storage_and_call.rs index 429efde51c65..5bb11e27903e 100644 --- a/substrate/frame/revive/fixtures/contracts/create_storage_and_call.rs +++ b/substrate/frame/revive/fixtures/contracts/create_storage_and_call.rs @@ -43,10 +43,10 @@ pub extern "C" fn call() { let ret = api::call( uapi::CallFlags::empty(), callee, - u64::MAX, // How much ref_time weight to devote for the execution. u64::MAX = use all resources. - u64::MAX, // How much proof_size weight to devote for the execution. u64::MAX = use all resources. - Some(deposit_limit), - &[0u8; 32], // Value transferred to the contract. + u64::MAX, // How much ref_time weight to devote for the execution. u64::MAX = use all resources. + u64::MAX, // How much proof_size weight to devote for the execution. u64::MAX = use all resources. + deposit_limit, + &[0u8; 32], // Value transferred to the contract. input, None, ); 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 c9ed851076e9..f627bc8ba6c4 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() { code_hash, u64::MAX, // How much ref_time weight to devote for the execution. u64::MAX = use all. u64::MAX, // How much proof_size weight to devote for the execution. u64::MAX = use all. - Some(deposit_limit), + deposit_limit, &value, input, Some(&mut address), diff --git a/substrate/frame/revive/fixtures/contracts/create_transient_storage_and_call.rs b/substrate/frame/revive/fixtures/contracts/create_transient_storage_and_call.rs index 3ba64bc7195b..3651277f7d09 100644 --- a/substrate/frame/revive/fixtures/contracts/create_transient_storage_and_call.rs +++ b/substrate/frame/revive/fixtures/contracts/create_transient_storage_and_call.rs @@ -20,7 +20,7 @@ #![no_main] use common::input; -use uapi::{HostFn, HostFnImpl as api, StorageFlags}; +use uapi::{HostFn, HostFnImpl as api, StorageFlags, U64_MAX_AS_U256}; static BUFFER: [u8; 448] = [0u8; 448]; @@ -49,10 +49,10 @@ pub extern "C" fn call() { api::call( uapi::CallFlags::empty(), callee, - u64::MAX, // How much ref_time weight to devote for the execution. u64::MAX = all. - u64::MAX, // How much proof_size weight to devote for the execution. u64::MAX = all. - None, - &[0u8; 32], // Value transferred to the contract. + u64::MAX, // How much ref_time weight to devote for the execution. u64::MAX = all. + u64::MAX, // How much proof_size weight to devote for the execution. u64::MAX = all. + &U64_MAX_AS_U256, // No deposit limit. + &[0u8; 32], // Value transferred to the contract. input, None, ) diff --git a/substrate/frame/revive/fixtures/contracts/delegate_call.rs b/substrate/frame/revive/fixtures/contracts/delegate_call.rs index 3cf74acf1321..a9da24efe741 100644 --- a/substrate/frame/revive/fixtures/contracts/delegate_call.rs +++ b/substrate/frame/revive/fixtures/contracts/delegate_call.rs @@ -19,7 +19,7 @@ #![no_main] use common::input; -use uapi::{HostFn, HostFnImpl as api, StorageFlags}; +use uapi::{HostFn, HostFnImpl as api, StorageFlags, U64_MAX_AS_U256}; #[no_mangle] #[polkavm_derive::polkavm_export] @@ -46,7 +46,15 @@ pub extern "C" fn call() { assert!(value[0] == 2u8); let input = [0u8; 0]; - api::delegate_call(uapi::CallFlags::empty(), address, ref_time, proof_size, None, &input, None).unwrap(); + api::delegate_call( + uapi::CallFlags::empty(), + address, + ref_time, + proof_size, + &U64_MAX_AS_U256, + &input, + None + ).unwrap(); api::get_storage(StorageFlags::empty(), &key, value).unwrap(); assert!(value[0] == 1u8); diff --git a/substrate/frame/revive/fixtures/contracts/delegate_call_deposit_limit.rs b/substrate/frame/revive/fixtures/contracts/delegate_call_deposit_limit.rs index 2e43e1d1ff6c..0c503aa93c56 100644 --- a/substrate/frame/revive/fixtures/contracts/delegate_call_deposit_limit.rs +++ b/substrate/frame/revive/fixtures/contracts/delegate_call_deposit_limit.rs @@ -34,7 +34,15 @@ pub extern "C" fn call() { ); let input = [0u8; 0]; - let ret = api::delegate_call(uapi::CallFlags::empty(), address, u64::MAX, u64::MAX, Some(&u256_bytes(deposit_limit)), &input, None); + let ret = api::delegate_call( + uapi::CallFlags::empty(), + address, + u64::MAX, + u64::MAX, + &u256_bytes(deposit_limit), + &input, + None + ); if let Err(code) = ret { api::return_value(uapi::ReturnFlags::REVERT, &(code as u32).to_le_bytes()); diff --git a/substrate/frame/revive/fixtures/contracts/delegate_call_simple.rs b/substrate/frame/revive/fixtures/contracts/delegate_call_simple.rs index e9c0fb6327bb..d8b1d696f294 100644 --- a/substrate/frame/revive/fixtures/contracts/delegate_call_simple.rs +++ b/substrate/frame/revive/fixtures/contracts/delegate_call_simple.rs @@ -19,7 +19,7 @@ #![no_main] use common::input; -use uapi::{HostFn, HostFnImpl as api}; +use uapi::{HostFn, HostFnImpl as api, U64_MAX_AS_U256}; #[no_mangle] #[polkavm_derive::polkavm_export] @@ -32,5 +32,13 @@ pub extern "C" fn call() { // Delegate call into passed address. let input = [0u8; 0]; - api::delegate_call(uapi::CallFlags::empty(), address, u64::MAX, u64::MAX, None, &input, None).unwrap(); + api::delegate_call( + uapi::CallFlags::empty(), + address, + u64::MAX, + u64::MAX, + &U64_MAX_AS_U256, + &input, + None + ).unwrap(); } diff --git a/substrate/frame/revive/fixtures/contracts/destroy_and_transfer.rs b/substrate/frame/revive/fixtures/contracts/destroy_and_transfer.rs index 34ea1510f1a2..a472b7fdf840 100644 --- a/substrate/frame/revive/fixtures/contracts/destroy_and_transfer.rs +++ b/substrate/frame/revive/fixtures/contracts/destroy_and_transfer.rs @@ -19,7 +19,7 @@ #![no_main] use common::{input, u256_bytes}; -use uapi::{HostFn, HostFnImpl as api, StorageFlags}; +use uapi::{HostFn, HostFnImpl as api, StorageFlags, U64_MAX_AS_U256}; const ADDRESS_KEY: [u8; 32] = [0u8; 32]; const VALUE: [u8; 32] = u256_bytes(65536); @@ -35,9 +35,9 @@ pub extern "C" fn deploy() { api::instantiate( code_hash, - u64::MAX, // How much ref_time weight to devote for the execution. u64::MAX = use all. - u64::MAX, // How much proof_size weight to devote for the execution. u64::MAX = use all. - None, // No deposit limit. + u64::MAX, // How much ref_time weight to devote for the execution. u64::MAX = use all. + u64::MAX, // How much proof_size weight to devote for the execution. u64::MAX = use all. + &U64_MAX_AS_U256, // No deposit limit. &VALUE, &input, Some(&mut address), @@ -62,9 +62,9 @@ pub extern "C" fn call() { let res = api::call( uapi::CallFlags::empty(), &callee_addr, - u64::MAX, // How much ref_time weight to devote for the execution. u64::MAX = use all. - u64::MAX, // How much proof_size weight to devote for the execution. u64::MAX = use all. - None, // No deposit limit. + u64::MAX, // How much ref_time weight to devote for the execution. u64::MAX = use all. + u64::MAX, // How much proof_size weight to devote for the execution. u64::MAX = use all. + &U64_MAX_AS_U256, // No deposit limit. &VALUE, &[0u8; 1], None, @@ -75,9 +75,9 @@ pub extern "C" fn call() { api::call( uapi::CallFlags::empty(), &callee_addr, - u64::MAX, // How much ref_time weight to devote for the execution. u64::MAX = use all. - u64::MAX, // How much proof_size weight to devote for the execution. u64::MAX = use all. - None, // No deposit limit. + u64::MAX, // How much ref_time weight to devote for the execution. u64::MAX = use all. + u64::MAX, // How much proof_size weight to devote for the execution. u64::MAX = use all. + &U64_MAX_AS_U256, // No deposit limit. &VALUE, &[0u8; 0], None, diff --git a/substrate/frame/revive/fixtures/contracts/drain.rs b/substrate/frame/revive/fixtures/contracts/drain.rs index 6e3e708a6b3d..78e7f2d19716 100644 --- a/substrate/frame/revive/fixtures/contracts/drain.rs +++ b/substrate/frame/revive/fixtures/contracts/drain.rs @@ -19,7 +19,7 @@ #![no_main] use common::{u256_bytes, u64_output}; -use uapi::{HostFn, HostFnImpl as api}; +use uapi::{HostFn, HostFnImpl as api, U64_MAX_AS_U256}; #[no_mangle] #[polkavm_derive::polkavm_export] @@ -41,7 +41,7 @@ pub extern "C" fn call() { &[0u8; 20], 0, 0, - None, + &U64_MAX_AS_U256, &u256_bytes(balance), &[], None, diff --git a/substrate/frame/revive/fixtures/contracts/instantiate_return_code.rs b/substrate/frame/revive/fixtures/contracts/instantiate_return_code.rs index f311f1537b49..90d65248e4f8 100644 --- a/substrate/frame/revive/fixtures/contracts/instantiate_return_code.rs +++ b/substrate/frame/revive/fixtures/contracts/instantiate_return_code.rs @@ -19,7 +19,7 @@ #![no_main] use common::{input, u256_bytes}; -use uapi::{HostFn, HostFnImpl as api}; +use uapi::{HostFn, HostFnImpl as api, U64_MAX_AS_U256}; #[no_mangle] #[polkavm_derive::polkavm_export] @@ -33,9 +33,9 @@ pub extern "C" fn call() { let err_code = match api::instantiate( code_hash, - u64::MAX, // How much ref_time weight to devote for the execution. u64::MAX = use all. - u64::MAX, // How much proof_size weight to devote for the execution. u64::MAX = use all. - None, // No deposit limit. + u64::MAX, // How much ref_time weight to devote for the execution. u64::MAX = use all. + u64::MAX, // How much proof_size weight to devote for the execution. u64::MAX = use all. + &U64_MAX_AS_U256, // No deposit limit. &u256_bytes(10_000u64), // Value to transfer. input, None, diff --git a/substrate/frame/revive/fixtures/contracts/locking_delegate_dependency.rs b/substrate/frame/revive/fixtures/contracts/locking_delegate_dependency.rs index 454c649f636a..8d81acff81f0 100644 --- a/substrate/frame/revive/fixtures/contracts/locking_delegate_dependency.rs +++ b/substrate/frame/revive/fixtures/contracts/locking_delegate_dependency.rs @@ -21,7 +21,7 @@ #![no_main] use common::input; -use uapi::{HostFn, HostFnImpl as api}; +use uapi::{HostFn, HostFnImpl as api, U64_MAX_AS_U256}; const ALICE_FALLBACK: [u8; 20] = [1u8; 20]; @@ -52,7 +52,7 @@ fn load_input(delegate_call: bool) { } if delegate_call { - api::delegate_call(uapi::CallFlags::empty(), address, u64::MAX, u64::MAX, None, &[], None).unwrap(); + api::delegate_call(uapi::CallFlags::empty(), address, u64::MAX, u64::MAX, &U64_MAX_AS_U256, &[], None).unwrap(); } } diff --git a/substrate/frame/revive/fixtures/contracts/origin.rs b/substrate/frame/revive/fixtures/contracts/origin.rs index bd79c58eff06..3a3ce93d331c 100644 --- a/substrate/frame/revive/fixtures/contracts/origin.rs +++ b/substrate/frame/revive/fixtures/contracts/origin.rs @@ -23,7 +23,7 @@ #![no_main] extern crate common; -use uapi::{HostFn, HostFnImpl as api}; +use uapi::{HostFn, HostFnImpl as api, U64_MAX_AS_U256}; #[no_mangle] #[polkavm_derive::polkavm_export] @@ -51,7 +51,7 @@ pub extern "C" fn call() { &addr, u64::MAX, u64::MAX, - None, + &U64_MAX_AS_U256, &[0; 32], &[], Some(&mut &mut buf[..]), diff --git a/substrate/frame/revive/fixtures/contracts/read_only_call.rs b/substrate/frame/revive/fixtures/contracts/read_only_call.rs index 79a44f8b1d39..6bf405d4c28a 100644 --- a/substrate/frame/revive/fixtures/contracts/read_only_call.rs +++ b/substrate/frame/revive/fixtures/contracts/read_only_call.rs @@ -20,7 +20,7 @@ #![no_main] use common::input; -use uapi::{HostFn, HostFnImpl as api}; +use uapi::{HostFn, HostFnImpl as api, U64_MAX_AS_U256}; #[no_mangle] #[polkavm_derive::polkavm_export] @@ -39,10 +39,10 @@ pub extern "C" fn call() { api::call( uapi::CallFlags::READ_ONLY, callee_addr, - u64::MAX, // How much ref_time to devote for the execution. u64::MAX = all. - u64::MAX, // How much proof_size to devote for the execution. u64::MAX = all. - None, // No deposit limit. - &[0u8; 32], // Value transferred to the contract. + u64::MAX, // How much ref_time to devote for the execution. u64::MAX = all. + u64::MAX, // How much proof_size to devote for the execution. u64::MAX = all. + &U64_MAX_AS_U256, // No deposit limit. + &[0u8; 32], // Value transferred to the contract. callee_input, None, ) diff --git a/substrate/frame/revive/fixtures/contracts/recurse.rs b/substrate/frame/revive/fixtures/contracts/recurse.rs index 2e69a777d844..e46c9621eb0f 100644 --- a/substrate/frame/revive/fixtures/contracts/recurse.rs +++ b/substrate/frame/revive/fixtures/contracts/recurse.rs @@ -21,7 +21,7 @@ #![no_main] use common::input; -use uapi::{HostFn, HostFnImpl as api}; +use uapi::{HostFn, HostFnImpl as api, U64_MAX_AS_U256}; #[no_mangle] #[polkavm_derive::polkavm_export] @@ -43,10 +43,10 @@ pub extern "C" fn call() { 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 deposit_limit to devote for the execution. u64::MAX = use all resources. - None, // No deposit limit. - &[0u8; 32], // Value transferred to the contract. + 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. + &U64_MAX_AS_U256, // No deposit limit. + &[0u8; 32], // Value transferred to the contract. &(calls_left - 1).to_le_bytes(), None, ) diff --git a/substrate/frame/revive/fixtures/contracts/return_data_api.rs b/substrate/frame/revive/fixtures/contracts/return_data_api.rs index 2e7291f7b81d..92a927a8ed63 100644 --- a/substrate/frame/revive/fixtures/contracts/return_data_api.rs +++ b/substrate/frame/revive/fixtures/contracts/return_data_api.rs @@ -27,7 +27,7 @@ #![no_main] use common::{input, u256_bytes}; -use uapi::{HostFn, HostFnImpl as api}; +use uapi::{HostFn, HostFnImpl as api, U64_MAX_AS_U256}; const INPUT_BUF_SIZE: usize = 128; static INPUT_DATA: [u8; INPUT_BUF_SIZE] = [0xFF; INPUT_BUF_SIZE]; @@ -80,8 +80,16 @@ fn assert_return_data_size_of(expected: u64) { /// Assert the return data to be reset after a balance transfer. fn assert_balance_transfer_does_reset() { - api::call(uapi::CallFlags::empty(), &[0u8; 20], u64::MAX, u64::MAX, None, &u256_bytes(128), &[], None) - .unwrap(); + api::call( + uapi::CallFlags::empty(), + &[0u8; 20], + u64::MAX, + u64::MAX, + &U64_MAX_AS_U256, + &u256_bytes(128), + &[], + None + ).unwrap(); assert_return_data_size_of(0); } @@ -113,7 +121,7 @@ pub extern "C" fn call() { code_hash, u64::MAX, u64::MAX, - None, + &U64_MAX_AS_U256, &[0; 32], &construct_input(exit_flag), Some(&mut address_buf), @@ -127,7 +135,7 @@ pub extern "C" fn call() { address_buf, u64::MAX, u64::MAX, - None, + &U64_MAX_AS_U256, &[0; 32], &construct_input(exit_flag), None, diff --git a/substrate/frame/revive/fixtures/contracts/self_destruct.rs b/substrate/frame/revive/fixtures/contracts/self_destruct.rs index ff969d4c57cc..ee3813e77d53 100644 --- a/substrate/frame/revive/fixtures/contracts/self_destruct.rs +++ b/substrate/frame/revive/fixtures/contracts/self_destruct.rs @@ -19,7 +19,7 @@ #![no_main] use common::input; -use uapi::{HostFn, HostFnImpl as api}; +use uapi::{HostFn, HostFnImpl as api, U64_MAX_AS_U256}; const DJANGO_FALLBACK: [u8; 20] = [4u8; 20]; @@ -42,10 +42,10 @@ pub extern "C" fn call() { api::call( uapi::CallFlags::ALLOW_REENTRY, &addr, - u64::MAX, // How much ref_time to devote for the execution. u64 = all. - u64::MAX, // How much proof_size to devote for the execution. u64 = all. - None, // No deposit limit. - &[0u8; 32], // Value to transfer. + u64::MAX, // How much ref_time to devote for the execution. u64 = all. + u64::MAX, // How much proof_size to devote for the execution. u64 = all. + &U64_MAX_AS_U256, // No deposit limit. + &[0u8; 32], // Value to transfer. &[0u8; 0], None, ) diff --git a/substrate/frame/revive/fixtures/contracts/transfer_return_code.rs b/substrate/frame/revive/fixtures/contracts/transfer_return_code.rs index 09d45d0a8411..d4987820f050 100644 --- a/substrate/frame/revive/fixtures/contracts/transfer_return_code.rs +++ b/substrate/frame/revive/fixtures/contracts/transfer_return_code.rs @@ -19,7 +19,7 @@ #![no_main] use common::u256_bytes; -use uapi::{HostFn, HostFnImpl as api}; +use uapi::{HostFn, HostFnImpl as api, U64_MAX_AS_U256}; #[no_mangle] #[polkavm_derive::polkavm_export] @@ -33,7 +33,7 @@ pub extern "C" fn call() { &[0u8; 20], 0, 0, - None, + &U64_MAX_AS_U256, &u256_bytes(100u64), &[], None, diff --git a/substrate/frame/revive/src/wasm/runtime.rs b/substrate/frame/revive/src/wasm/runtime.rs index ebc7e211fc70..8529c7d9e73b 100644 --- a/substrate/frame/revive/src/wasm/runtime.rs +++ b/substrate/frame/revive/src/wasm/runtime.rs @@ -1004,11 +1004,7 @@ impl<'a, E: Ext, M: ?Sized + Memory> Runtime<'a, E, M> { self.charge_gas(call_type.cost())?; let callee = memory.read_h160(callee_ptr)?; - let deposit_limit = if deposit_ptr == SENTINEL { - U256::from(u64::MAX) - } else { - memory.read_u256(deposit_ptr)? - }; + let deposit_limit = memory.read_u256(deposit_ptr)?; let input_data = if flags.contains(CallFlags::CLONE_INPUT) { let input = self.input_data.as_ref().ok_or(Error::::InputForwarded)?; @@ -1094,11 +1090,7 @@ impl<'a, E: Ext, M: ?Sized + Memory> Runtime<'a, E, M> { salt_ptr: u32, ) -> Result { self.charge_gas(RuntimeCosts::Instantiate { input_data_len })?; - let deposit_limit: U256 = if deposit_ptr == SENTINEL { - U256::from(u64::MAX) - } else { - memory.read_u256(deposit_ptr)? - }; + 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)?; let input_data = memory.read(input_data_ptr, input_data_len)?; diff --git a/substrate/frame/revive/uapi/src/host.rs b/substrate/frame/revive/uapi/src/host.rs index eced4843b552..6156b6eba76a 100644 --- a/substrate/frame/revive/uapi/src/host.rs +++ b/substrate/frame/revive/uapi/src/host.rs @@ -113,7 +113,7 @@ pub trait HostFn: private::Sealed { callee: &[u8; 20], ref_time_limit: u64, proof_size_limit: u64, - deposit: Option<&[u8; 32]>, + deposit: &[u8; 32], value: &[u8; 32], input_data: &[u8], output: Option<&mut &mut [u8]>, @@ -202,7 +202,7 @@ pub trait HostFn: private::Sealed { address: &[u8; 20], ref_time_limit: u64, proof_size_limit: u64, - deposit_limit: Option<&[u8; 32]>, + deposit_limit: &[u8; 32], input_data: &[u8], output: Option<&mut &mut [u8]>, ) -> Result; @@ -318,7 +318,7 @@ pub trait HostFn: private::Sealed { code_hash: &[u8; 32], ref_time_limit: u64, proof_size_limit: u64, - deposit: Option<&[u8; 32]>, + deposit: &[u8; 32], value: &[u8; 32], input: &[u8], address: Option<&mut [u8; 20]>, diff --git a/substrate/frame/revive/uapi/src/host/riscv64.rs b/substrate/frame/revive/uapi/src/host/riscv64.rs index 6fdda86892d5..bb608cfe49d0 100644 --- a/substrate/frame/revive/uapi/src/host/riscv64.rs +++ b/substrate/frame/revive/uapi/src/host/riscv64.rs @@ -168,7 +168,7 @@ impl HostFn for HostFnImpl { code_hash: &[u8; 32], ref_time_limit: u64, proof_size_limit: u64, - deposit_limit: Option<&[u8; 32]>, + deposit_limit: &[u8; 32], value: &[u8; 32], input: &[u8], mut address: Option<&mut [u8; 20]>, @@ -180,7 +180,7 @@ impl HostFn for HostFnImpl { None => crate::SENTINEL as _, }; let (output_ptr, mut output_len) = ptr_len_or_sentinel(&mut output); - let deposit_limit_ptr = ptr_or_sentinel(&deposit_limit); + let deposit_limit_ptr = deposit_limit.as_ptr(); let salt_ptr = ptr_or_sentinel(&salt); #[repr(C)] #[allow(dead_code)] @@ -225,13 +225,13 @@ impl HostFn for HostFnImpl { callee: &[u8; 20], ref_time_limit: u64, proof_size_limit: u64, - deposit_limit: Option<&[u8; 32]>, + deposit_limit: &[u8; 32], value: &[u8; 32], input: &[u8], mut output: Option<&mut &mut [u8]>, ) -> Result { let (output_ptr, mut output_len) = ptr_len_or_sentinel(&mut output); - let deposit_limit_ptr = ptr_or_sentinel(&deposit_limit); + let deposit_limit_ptr = deposit_limit.as_ptr(); #[repr(C)] #[allow(dead_code)] struct Args { @@ -273,12 +273,12 @@ impl HostFn for HostFnImpl { address: &[u8; 20], ref_time_limit: u64, proof_size_limit: u64, - deposit_limit: Option<&[u8; 32]>, + deposit_limit: &[u8; 32], input: &[u8], mut output: Option<&mut &mut [u8]>, ) -> Result { let (output_ptr, mut output_len) = ptr_len_or_sentinel(&mut output); - let deposit_limit_ptr = ptr_or_sentinel(&deposit_limit); + let deposit_limit_ptr = deposit_limit.as_ptr(); #[repr(C)] #[allow(dead_code)] struct Args { diff --git a/substrate/frame/revive/uapi/src/lib.rs b/substrate/frame/revive/uapi/src/lib.rs index ef1798b4bf61..827d28f8b70c 100644 --- a/substrate/frame/revive/uapi/src/lib.rs +++ b/substrate/frame/revive/uapi/src/lib.rs @@ -116,6 +116,27 @@ pub struct ReturnCode(u32); /// make sense for a memory location or length. const SENTINEL: u32 = u32::MAX; +/// Converts a `u64` to a 32-byte array, encoded little-endian. +/// +/// The `u64` value will be placed in the first 8 bytes, +/// and the remaining bytes are set to zero. +const fn u64_to_u256_bytes(value: u64) -> [u8; 32] { + let mut bytes = [0u8; 32]; + let value_bytes = value.to_le_bytes(); + let mut i = 0; + while i < 8 { + bytes[i] = value_bytes[i]; + i += 1; + } + bytes +} + +/// A constant representing `u64::MAX` as a 32-byte array, in little-endian encoding. +/// +/// Deposit limits are `U256`, but balances are represented as `u64`. +/// To represent no deposit limits on an operation, this should be used. +pub const U64_MAX_AS_U256: [u8; 32] = u64_to_u256_bytes(u64::MAX); + impl From for Option { fn from(code: ReturnCode) -> Self { (code.0 < SENTINEL).then_some(code.0) From 222e6df0791cf43066e5b7961e8dc8b9dc5ee704 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexandre=20Bald=C3=A9?= Date: Wed, 8 Jan 2025 14:15:09 +0000 Subject: [PATCH 27/34] Rename `const` with confusing name --- .../frame/revive/fixtures/contracts/call.rs | 4 ++-- .../contracts/call_diverging_out_len.rs | 6 +++--- .../fixtures/contracts/call_return_code.rs | 4 ++-- .../contracts/call_runtime_and_call.rs | 4 ++-- .../contracts/call_with_flags_and_value.rs | 4 ++-- .../fixtures/contracts/call_with_limit.rs | 4 ++-- .../fixtures/contracts/caller_contract.rs | 18 +++++++++--------- .../contracts/chain_extension_temp_storage.rs | 4 ++-- .../fixtures/contracts/create1_with_value.rs | 4 ++-- .../create_transient_storage_and_call.rs | 4 ++-- .../revive/fixtures/contracts/delegate_call.rs | 4 ++-- .../fixtures/contracts/delegate_call_simple.rs | 4 ++-- .../fixtures/contracts/destroy_and_transfer.rs | 8 ++++---- .../frame/revive/fixtures/contracts/drain.rs | 4 ++-- .../contracts/instantiate_return_code.rs | 4 ++-- .../contracts/locking_delegate_dependency.rs | 4 ++-- .../frame/revive/fixtures/contracts/origin.rs | 4 ++-- .../fixtures/contracts/read_only_call.rs | 4 ++-- .../frame/revive/fixtures/contracts/recurse.rs | 4 ++-- .../fixtures/contracts/return_data_api.rs | 8 ++++---- .../revive/fixtures/contracts/self_destruct.rs | 4 ++-- .../fixtures/contracts/transfer_return_code.rs | 4 ++-- substrate/frame/revive/uapi/src/lib.rs | 4 ++-- 23 files changed, 58 insertions(+), 58 deletions(-) diff --git a/substrate/frame/revive/fixtures/contracts/call.rs b/substrate/frame/revive/fixtures/contracts/call.rs index c93d951d37dc..d01fc31ac872 100644 --- a/substrate/frame/revive/fixtures/contracts/call.rs +++ b/substrate/frame/revive/fixtures/contracts/call.rs @@ -20,7 +20,7 @@ #![no_main] use common::input; -use uapi::{HostFn, HostFnImpl as api, U64_MAX_AS_U256}; +use uapi::{HostFn, HostFnImpl as api, U256_MAX}; #[no_mangle] #[polkavm_derive::polkavm_export] @@ -40,7 +40,7 @@ pub extern "C" fn call() { 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. - &U64_MAX_AS_U256, // No deposit limit. + &U256_MAX, // No deposit limit. &[0u8; 32], // Value transferred to the contract. callee_input, None, diff --git a/substrate/frame/revive/fixtures/contracts/call_diverging_out_len.rs b/substrate/frame/revive/fixtures/contracts/call_diverging_out_len.rs index 463130a2f8f0..069ec0a483e1 100644 --- a/substrate/frame/revive/fixtures/contracts/call_diverging_out_len.rs +++ b/substrate/frame/revive/fixtures/contracts/call_diverging_out_len.rs @@ -28,7 +28,7 @@ extern crate common; -use uapi::{HostFn, HostFnImpl as api, U64_MAX_AS_U256}; +use uapi::{HostFn, HostFnImpl as api, U256_MAX}; const BUF_SIZE: usize = 8; static DATA: [u8; BUF_SIZE] = [1, 2, 3, 4, 5, 6, 7, 8]; @@ -44,7 +44,7 @@ fn assert_call(callee_address: &[u8; 20], expected_output: [u8; callee_address, u64::MAX, u64::MAX, - &U64_MAX_AS_U256, + &U256_MAX, &[0u8; 32], &[], Some(output_buf_capped), @@ -69,7 +69,7 @@ fn assert_instantiate(expected_output: [u8; BUF_SIZE]) { &code_hash, u64::MAX, u64::MAX, - &U64_MAX_AS_U256, + &U256_MAX, &[0; 32], &[0; 32], None, diff --git a/substrate/frame/revive/fixtures/contracts/call_return_code.rs b/substrate/frame/revive/fixtures/contracts/call_return_code.rs index 3594aa79740f..00ac4e51f5fe 100644 --- a/substrate/frame/revive/fixtures/contracts/call_return_code.rs +++ b/substrate/frame/revive/fixtures/contracts/call_return_code.rs @@ -22,7 +22,7 @@ #![no_main] use common::input; -use uapi::{HostFn, HostFnImpl as api, U64_MAX_AS_U256}; +use uapi::{HostFn, HostFnImpl as api, U256_MAX}; #[no_mangle] #[polkavm_derive::polkavm_export] @@ -44,7 +44,7 @@ pub extern "C" fn call() { 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. - &U64_MAX_AS_U256, // No deposit limit. + &U256_MAX, // No deposit limit. value, // Value transferred to the contract. input, None, diff --git a/substrate/frame/revive/fixtures/contracts/call_runtime_and_call.rs b/substrate/frame/revive/fixtures/contracts/call_runtime_and_call.rs index cec94d18003c..5fc3242cf3ba 100644 --- a/substrate/frame/revive/fixtures/contracts/call_runtime_and_call.rs +++ b/substrate/frame/revive/fixtures/contracts/call_runtime_and_call.rs @@ -19,7 +19,7 @@ #![no_main] use common::input; -use uapi::{HostFn, HostFnImpl as api, U64_MAX_AS_U256}; +use uapi::{HostFn, HostFnImpl as api, U256_MAX}; #[no_mangle] #[polkavm_derive::polkavm_export] @@ -44,7 +44,7 @@ pub extern "C" fn call() { 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. - &U64_MAX_AS_U256, // No deposit limit. + &U256_MAX, // No deposit limit. &[0u8; 32], // Value transferred to the contract. callee_input, None, diff --git a/substrate/frame/revive/fixtures/contracts/call_with_flags_and_value.rs b/substrate/frame/revive/fixtures/contracts/call_with_flags_and_value.rs index 5f430a625219..d90b71aa73a5 100644 --- a/substrate/frame/revive/fixtures/contracts/call_with_flags_and_value.rs +++ b/substrate/frame/revive/fixtures/contracts/call_with_flags_and_value.rs @@ -20,7 +20,7 @@ #![no_main] use common::{input, u256_bytes}; -use uapi::{HostFn, HostFnImpl as api, U64_MAX_AS_U256}; +use uapi::{HostFn, HostFnImpl as api, U256_MAX}; #[no_mangle] #[polkavm_derive::polkavm_export] @@ -42,7 +42,7 @@ pub extern "C" fn call() { 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. - &U64_MAX_AS_U256, // No deposit limit. + &U256_MAX, // No deposit limit. &u256_bytes(value), // Value transferred to the contract. forwarded_input, None, diff --git a/substrate/frame/revive/fixtures/contracts/call_with_limit.rs b/substrate/frame/revive/fixtures/contracts/call_with_limit.rs index 10a6b7a90e96..4ff0352dfe51 100644 --- a/substrate/frame/revive/fixtures/contracts/call_with_limit.rs +++ b/substrate/frame/revive/fixtures/contracts/call_with_limit.rs @@ -21,7 +21,7 @@ #![no_main] use common::input; -use uapi::{HostFn, HostFnImpl as api, U64_MAX_AS_U256}; +use uapi::{HostFn, HostFnImpl as api, U256_MAX}; #[no_mangle] #[polkavm_derive::polkavm_export] @@ -43,7 +43,7 @@ pub extern "C" fn call() { callee_addr, ref_time, proof_size, - &U64_MAX_AS_U256, // No deposit limit. + &U256_MAX, // No deposit limit. &[0u8; 32], // value transferred to the contract. forwarded_input, None, diff --git a/substrate/frame/revive/fixtures/contracts/caller_contract.rs b/substrate/frame/revive/fixtures/contracts/caller_contract.rs index 7609ca270449..99a821ebc0e8 100644 --- a/substrate/frame/revive/fixtures/contracts/caller_contract.rs +++ b/substrate/frame/revive/fixtures/contracts/caller_contract.rs @@ -19,7 +19,7 @@ #![no_main] use common::{input, u256_bytes}; -use uapi::{HostFn, HostFnImpl as api, ReturnErrorCode, U64_MAX_AS_U256}; +use uapi::{HostFn, HostFnImpl as api, ReturnErrorCode, U256_MAX}; #[no_mangle] #[polkavm_derive::polkavm_export] @@ -44,7 +44,7 @@ pub extern "C" fn call() { code_hash, u64::MAX, // How much ref_time weight to devote for the execution. u64::MAX = use all. u64::MAX, // How much proof_size weight to devote for the execution. u64::MAX = use all. - &U64_MAX_AS_U256, // No deposit limit. + &U256_MAX, // No deposit limit. &value, &reverted_input, None, @@ -58,7 +58,7 @@ pub extern "C" fn call() { code_hash, 1u64, // too little ref_time weight u64::MAX, // How much proof_size weight to devote for the execution. u64::MAX = use all. - &U64_MAX_AS_U256, // No deposit limit. + &U256_MAX, // No deposit limit. &value, &input, None, @@ -72,7 +72,7 @@ pub extern "C" fn call() { code_hash, u64::MAX, // How much ref_time weight to devote for the execution. u64::MAX = use all. 1u64, // Too little proof_size weight - &U64_MAX_AS_U256, // No deposit limit. + &U256_MAX, // No deposit limit. &value, &input, None, @@ -88,7 +88,7 @@ pub extern "C" fn call() { code_hash, u64::MAX, // How much ref_time weight to devote for the execution. u64::MAX = use all. u64::MAX, // How much proof_size weight to devote for the execution. u64::MAX = use all. - &U64_MAX_AS_U256, // No deposit limit. + &U256_MAX, // No deposit limit. &value, &input, Some(&mut callee), @@ -103,7 +103,7 @@ pub extern "C" fn call() { &callee, u64::MAX, // How much ref_time weight to devote for the execution. u64::MAX = use all. u64::MAX, // How much proof_size weight to devote for the execution. u64::MAX = use all. - &U64_MAX_AS_U256, // No deposit limit. + &U256_MAX, // No deposit limit. &value, &reverted_input, None, @@ -116,7 +116,7 @@ pub extern "C" fn call() { &callee, 1u64, // Too little ref_time weight. u64::MAX, // How much proof_size weight to devote for the execution. u64::MAX = use all. - &U64_MAX_AS_U256, // No deposit limit. + &U256_MAX, // No deposit limit. &value, &input, None, @@ -129,7 +129,7 @@ pub extern "C" fn call() { &callee, u64::MAX, // How much ref_time weight to devote for the execution. u64::MAX = use all. 1u64, // too little proof_size weight - &U64_MAX_AS_U256, // No deposit limit. + &U256_MAX, // No deposit limit. &value, &input, None, @@ -143,7 +143,7 @@ pub extern "C" fn call() { &callee, u64::MAX, // How much ref_time weight to devote for the execution. u64::MAX = use all. u64::MAX, // How much proof_size weight to devote for the execution. u64::MAX = use all. - &U64_MAX_AS_U256, // No deposit limit. + &U256_MAX, // No deposit limit. &value, &input, Some(&mut &mut output[..]), diff --git a/substrate/frame/revive/fixtures/contracts/chain_extension_temp_storage.rs b/substrate/frame/revive/fixtures/contracts/chain_extension_temp_storage.rs index f949aa09ad7b..8c3e897df813 100644 --- a/substrate/frame/revive/fixtures/contracts/chain_extension_temp_storage.rs +++ b/substrate/frame/revive/fixtures/contracts/chain_extension_temp_storage.rs @@ -21,7 +21,7 @@ #![no_main] use common::input; -use uapi::{HostFn, HostFnImpl as api, U64_MAX_AS_U256}; +use uapi::{HostFn, HostFnImpl as api, U256_MAX}; #[no_mangle] #[polkavm_derive::polkavm_export] @@ -56,7 +56,7 @@ pub extern "C" fn call() { &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. - &U64_MAX_AS_U256, // No deposit limit. + &U256_MAX, // No deposit limit. &[0u8; 32], // Value transferred to the contract. input, None, diff --git a/substrate/frame/revive/fixtures/contracts/create1_with_value.rs b/substrate/frame/revive/fixtures/contracts/create1_with_value.rs index afeaaec020b0..22de069db5e6 100644 --- a/substrate/frame/revive/fixtures/contracts/create1_with_value.rs +++ b/substrate/frame/revive/fixtures/contracts/create1_with_value.rs @@ -19,7 +19,7 @@ #![no_main] use common::input; -use uapi::{HostFn, HostFnImpl as api, U64_MAX_AS_U256}; +use uapi::{HostFn, HostFnImpl as api, U256_MAX}; #[no_mangle] #[polkavm_derive::polkavm_export] @@ -34,6 +34,6 @@ pub extern "C" fn call() { api::value_transferred(&mut value); // Deploy the contract with no salt (equivalent to create1). - let ret = api::instantiate(code_hash, u64::MAX, u64::MAX, &U64_MAX_AS_U256, &value, &[], None, None, None); + let ret = api::instantiate(code_hash, u64::MAX, u64::MAX, &U256_MAX, &value, &[], None, None, None); assert!(ret.is_ok()); } diff --git a/substrate/frame/revive/fixtures/contracts/create_transient_storage_and_call.rs b/substrate/frame/revive/fixtures/contracts/create_transient_storage_and_call.rs index 3651277f7d09..390b6e0735e3 100644 --- a/substrate/frame/revive/fixtures/contracts/create_transient_storage_and_call.rs +++ b/substrate/frame/revive/fixtures/contracts/create_transient_storage_and_call.rs @@ -20,7 +20,7 @@ #![no_main] use common::input; -use uapi::{HostFn, HostFnImpl as api, StorageFlags, U64_MAX_AS_U256}; +use uapi::{HostFn, HostFnImpl as api, StorageFlags, U256_MAX}; static BUFFER: [u8; 448] = [0u8; 448]; @@ -51,7 +51,7 @@ pub extern "C" fn call() { callee, u64::MAX, // How much ref_time weight to devote for the execution. u64::MAX = all. u64::MAX, // How much proof_size weight to devote for the execution. u64::MAX = all. - &U64_MAX_AS_U256, // No deposit limit. + &U256_MAX, // No deposit limit. &[0u8; 32], // Value transferred to the contract. input, None, diff --git a/substrate/frame/revive/fixtures/contracts/delegate_call.rs b/substrate/frame/revive/fixtures/contracts/delegate_call.rs index a9da24efe741..686c459b9da9 100644 --- a/substrate/frame/revive/fixtures/contracts/delegate_call.rs +++ b/substrate/frame/revive/fixtures/contracts/delegate_call.rs @@ -19,7 +19,7 @@ #![no_main] use common::input; -use uapi::{HostFn, HostFnImpl as api, StorageFlags, U64_MAX_AS_U256}; +use uapi::{HostFn, HostFnImpl as api, StorageFlags, U256_MAX}; #[no_mangle] #[polkavm_derive::polkavm_export] @@ -51,7 +51,7 @@ pub extern "C" fn call() { address, ref_time, proof_size, - &U64_MAX_AS_U256, + &U256_MAX, &input, None ).unwrap(); diff --git a/substrate/frame/revive/fixtures/contracts/delegate_call_simple.rs b/substrate/frame/revive/fixtures/contracts/delegate_call_simple.rs index d8b1d696f294..116d648bb60d 100644 --- a/substrate/frame/revive/fixtures/contracts/delegate_call_simple.rs +++ b/substrate/frame/revive/fixtures/contracts/delegate_call_simple.rs @@ -19,7 +19,7 @@ #![no_main] use common::input; -use uapi::{HostFn, HostFnImpl as api, U64_MAX_AS_U256}; +use uapi::{HostFn, HostFnImpl as api, U256_MAX}; #[no_mangle] #[polkavm_derive::polkavm_export] @@ -37,7 +37,7 @@ pub extern "C" fn call() { address, u64::MAX, u64::MAX, - &U64_MAX_AS_U256, + &U256_MAX, &input, None ).unwrap(); diff --git a/substrate/frame/revive/fixtures/contracts/destroy_and_transfer.rs b/substrate/frame/revive/fixtures/contracts/destroy_and_transfer.rs index a472b7fdf840..e921b1b9f336 100644 --- a/substrate/frame/revive/fixtures/contracts/destroy_and_transfer.rs +++ b/substrate/frame/revive/fixtures/contracts/destroy_and_transfer.rs @@ -19,7 +19,7 @@ #![no_main] use common::{input, u256_bytes}; -use uapi::{HostFn, HostFnImpl as api, StorageFlags, U64_MAX_AS_U256}; +use uapi::{HostFn, HostFnImpl as api, StorageFlags, U256_MAX}; const ADDRESS_KEY: [u8; 32] = [0u8; 32]; const VALUE: [u8; 32] = u256_bytes(65536); @@ -37,7 +37,7 @@ pub extern "C" fn deploy() { code_hash, u64::MAX, // How much ref_time weight to devote for the execution. u64::MAX = use all. u64::MAX, // How much proof_size weight to devote for the execution. u64::MAX = use all. - &U64_MAX_AS_U256, // No deposit limit. + &U256_MAX, // No deposit limit. &VALUE, &input, Some(&mut address), @@ -64,7 +64,7 @@ pub extern "C" fn call() { &callee_addr, u64::MAX, // How much ref_time weight to devote for the execution. u64::MAX = use all. u64::MAX, // How much proof_size weight to devote for the execution. u64::MAX = use all. - &U64_MAX_AS_U256, // No deposit limit. + &U256_MAX, // No deposit limit. &VALUE, &[0u8; 1], None, @@ -77,7 +77,7 @@ pub extern "C" fn call() { &callee_addr, u64::MAX, // How much ref_time weight to devote for the execution. u64::MAX = use all. u64::MAX, // How much proof_size weight to devote for the execution. u64::MAX = use all. - &U64_MAX_AS_U256, // No deposit limit. + &U256_MAX, // No deposit limit. &VALUE, &[0u8; 0], None, diff --git a/substrate/frame/revive/fixtures/contracts/drain.rs b/substrate/frame/revive/fixtures/contracts/drain.rs index 78e7f2d19716..23bd6e0a4704 100644 --- a/substrate/frame/revive/fixtures/contracts/drain.rs +++ b/substrate/frame/revive/fixtures/contracts/drain.rs @@ -19,7 +19,7 @@ #![no_main] use common::{u256_bytes, u64_output}; -use uapi::{HostFn, HostFnImpl as api, U64_MAX_AS_U256}; +use uapi::{HostFn, HostFnImpl as api, U256_MAX}; #[no_mangle] #[polkavm_derive::polkavm_export] @@ -41,7 +41,7 @@ pub extern "C" fn call() { &[0u8; 20], 0, 0, - &U64_MAX_AS_U256, + &U256_MAX, &u256_bytes(balance), &[], None, diff --git a/substrate/frame/revive/fixtures/contracts/instantiate_return_code.rs b/substrate/frame/revive/fixtures/contracts/instantiate_return_code.rs index 90d65248e4f8..6b43f9fed9cd 100644 --- a/substrate/frame/revive/fixtures/contracts/instantiate_return_code.rs +++ b/substrate/frame/revive/fixtures/contracts/instantiate_return_code.rs @@ -19,7 +19,7 @@ #![no_main] use common::{input, u256_bytes}; -use uapi::{HostFn, HostFnImpl as api, U64_MAX_AS_U256}; +use uapi::{HostFn, HostFnImpl as api, U256_MAX}; #[no_mangle] #[polkavm_derive::polkavm_export] @@ -35,7 +35,7 @@ pub extern "C" fn call() { code_hash, u64::MAX, // How much ref_time weight to devote for the execution. u64::MAX = use all. u64::MAX, // How much proof_size weight to devote for the execution. u64::MAX = use all. - &U64_MAX_AS_U256, // No deposit limit. + &U256_MAX, // No deposit limit. &u256_bytes(10_000u64), // Value to transfer. input, None, diff --git a/substrate/frame/revive/fixtures/contracts/locking_delegate_dependency.rs b/substrate/frame/revive/fixtures/contracts/locking_delegate_dependency.rs index 8d81acff81f0..9d0bbe5c8b9a 100644 --- a/substrate/frame/revive/fixtures/contracts/locking_delegate_dependency.rs +++ b/substrate/frame/revive/fixtures/contracts/locking_delegate_dependency.rs @@ -21,7 +21,7 @@ #![no_main] use common::input; -use uapi::{HostFn, HostFnImpl as api, U64_MAX_AS_U256}; +use uapi::{HostFn, HostFnImpl as api, U256_MAX}; const ALICE_FALLBACK: [u8; 20] = [1u8; 20]; @@ -52,7 +52,7 @@ fn load_input(delegate_call: bool) { } if delegate_call { - api::delegate_call(uapi::CallFlags::empty(), address, u64::MAX, u64::MAX, &U64_MAX_AS_U256, &[], None).unwrap(); + api::delegate_call(uapi::CallFlags::empty(), address, u64::MAX, u64::MAX, &U256_MAX, &[], None).unwrap(); } } diff --git a/substrate/frame/revive/fixtures/contracts/origin.rs b/substrate/frame/revive/fixtures/contracts/origin.rs index 3a3ce93d331c..b12a45b114f8 100644 --- a/substrate/frame/revive/fixtures/contracts/origin.rs +++ b/substrate/frame/revive/fixtures/contracts/origin.rs @@ -23,7 +23,7 @@ #![no_main] extern crate common; -use uapi::{HostFn, HostFnImpl as api, U64_MAX_AS_U256}; +use uapi::{HostFn, HostFnImpl as api, U256_MAX}; #[no_mangle] #[polkavm_derive::polkavm_export] @@ -51,7 +51,7 @@ pub extern "C" fn call() { &addr, u64::MAX, u64::MAX, - &U64_MAX_AS_U256, + &U256_MAX, &[0; 32], &[], Some(&mut &mut buf[..]), diff --git a/substrate/frame/revive/fixtures/contracts/read_only_call.rs b/substrate/frame/revive/fixtures/contracts/read_only_call.rs index 6bf405d4c28a..96786cf9e370 100644 --- a/substrate/frame/revive/fixtures/contracts/read_only_call.rs +++ b/substrate/frame/revive/fixtures/contracts/read_only_call.rs @@ -20,7 +20,7 @@ #![no_main] use common::input; -use uapi::{HostFn, HostFnImpl as api, U64_MAX_AS_U256}; +use uapi::{HostFn, HostFnImpl as api, U256_MAX}; #[no_mangle] #[polkavm_derive::polkavm_export] @@ -41,7 +41,7 @@ pub extern "C" fn call() { callee_addr, u64::MAX, // How much ref_time to devote for the execution. u64::MAX = all. u64::MAX, // How much proof_size to devote for the execution. u64::MAX = all. - &U64_MAX_AS_U256, // No deposit limit. + &U256_MAX, // No deposit limit. &[0u8; 32], // Value transferred to the contract. callee_input, None, diff --git a/substrate/frame/revive/fixtures/contracts/recurse.rs b/substrate/frame/revive/fixtures/contracts/recurse.rs index e46c9621eb0f..64b4358e5ffb 100644 --- a/substrate/frame/revive/fixtures/contracts/recurse.rs +++ b/substrate/frame/revive/fixtures/contracts/recurse.rs @@ -21,7 +21,7 @@ #![no_main] use common::input; -use uapi::{HostFn, HostFnImpl as api, U64_MAX_AS_U256}; +use uapi::{HostFn, HostFnImpl as api, U256_MAX}; #[no_mangle] #[polkavm_derive::polkavm_export] @@ -45,7 +45,7 @@ pub extern "C" fn call() { &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. - &U64_MAX_AS_U256, // No deposit limit. + &U256_MAX, // No deposit limit. &[0u8; 32], // Value transferred to the contract. &(calls_left - 1).to_le_bytes(), None, diff --git a/substrate/frame/revive/fixtures/contracts/return_data_api.rs b/substrate/frame/revive/fixtures/contracts/return_data_api.rs index 92a927a8ed63..0ce89bc71ca6 100644 --- a/substrate/frame/revive/fixtures/contracts/return_data_api.rs +++ b/substrate/frame/revive/fixtures/contracts/return_data_api.rs @@ -27,7 +27,7 @@ #![no_main] use common::{input, u256_bytes}; -use uapi::{HostFn, HostFnImpl as api, U64_MAX_AS_U256}; +use uapi::{HostFn, HostFnImpl as api, U256_MAX}; const INPUT_BUF_SIZE: usize = 128; static INPUT_DATA: [u8; INPUT_BUF_SIZE] = [0xFF; INPUT_BUF_SIZE]; @@ -85,7 +85,7 @@ fn assert_balance_transfer_does_reset() { &[0u8; 20], u64::MAX, u64::MAX, - &U64_MAX_AS_U256, + &U256_MAX, &u256_bytes(128), &[], None @@ -121,7 +121,7 @@ pub extern "C" fn call() { code_hash, u64::MAX, u64::MAX, - &U64_MAX_AS_U256, + &U256_MAX, &[0; 32], &construct_input(exit_flag), Some(&mut address_buf), @@ -135,7 +135,7 @@ pub extern "C" fn call() { address_buf, u64::MAX, u64::MAX, - &U64_MAX_AS_U256, + &U256_MAX, &[0; 32], &construct_input(exit_flag), None, diff --git a/substrate/frame/revive/fixtures/contracts/self_destruct.rs b/substrate/frame/revive/fixtures/contracts/self_destruct.rs index ee3813e77d53..ea3eedf9ee0c 100644 --- a/substrate/frame/revive/fixtures/contracts/self_destruct.rs +++ b/substrate/frame/revive/fixtures/contracts/self_destruct.rs @@ -19,7 +19,7 @@ #![no_main] use common::input; -use uapi::{HostFn, HostFnImpl as api, U64_MAX_AS_U256}; +use uapi::{HostFn, HostFnImpl as api, U256_MAX}; const DJANGO_FALLBACK: [u8; 20] = [4u8; 20]; @@ -44,7 +44,7 @@ pub extern "C" fn call() { &addr, u64::MAX, // How much ref_time to devote for the execution. u64 = all. u64::MAX, // How much proof_size to devote for the execution. u64 = all. - &U64_MAX_AS_U256, // No deposit limit. + &U256_MAX, // No deposit limit. &[0u8; 32], // Value to transfer. &[0u8; 0], None, diff --git a/substrate/frame/revive/fixtures/contracts/transfer_return_code.rs b/substrate/frame/revive/fixtures/contracts/transfer_return_code.rs index d4987820f050..cbfe34f96964 100644 --- a/substrate/frame/revive/fixtures/contracts/transfer_return_code.rs +++ b/substrate/frame/revive/fixtures/contracts/transfer_return_code.rs @@ -19,7 +19,7 @@ #![no_main] use common::u256_bytes; -use uapi::{HostFn, HostFnImpl as api, U64_MAX_AS_U256}; +use uapi::{HostFn, HostFnImpl as api, U256_MAX}; #[no_mangle] #[polkavm_derive::polkavm_export] @@ -33,7 +33,7 @@ pub extern "C" fn call() { &[0u8; 20], 0, 0, - &U64_MAX_AS_U256, + &U256_MAX, &u256_bytes(100u64), &[], None, diff --git a/substrate/frame/revive/uapi/src/lib.rs b/substrate/frame/revive/uapi/src/lib.rs index 827d28f8b70c..0715532c61e7 100644 --- a/substrate/frame/revive/uapi/src/lib.rs +++ b/substrate/frame/revive/uapi/src/lib.rs @@ -134,8 +134,8 @@ const fn u64_to_u256_bytes(value: u64) -> [u8; 32] { /// A constant representing `u64::MAX` as a 32-byte array, in little-endian encoding. /// /// Deposit limits are `U256`, but balances are represented as `u64`. -/// To represent no deposit limits on an operation, this should be used. -pub const U64_MAX_AS_U256: [u8; 32] = u64_to_u256_bytes(u64::MAX); +/// To represent no deposit limits on an operation, this should be used. +pub const U256_MAX: [u8; 32] = u64_to_u256_bytes(u64::MAX); impl From for Option { fn from(code: ReturnCode) -> Self { From 93ac5badbe587aac2a0b5986d7268abd279e627c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexandre=20Bald=C3=A9?= Date: Wed, 8 Jan 2025 14:49:40 +0000 Subject: [PATCH 28/34] Update usage of `Weight::zero()` in test There, its meaning was "use all available gas", which needed to be updated to `Weight::MAX`. --- substrate/frame/revive/src/tests.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/substrate/frame/revive/src/tests.rs b/substrate/frame/revive/src/tests.rs index 1bf24d30afd1..f16aa67ea708 100644 --- a/substrate/frame/revive/src/tests.rs +++ b/substrate/frame/revive/src/tests.rs @@ -2261,7 +2261,7 @@ fn gas_estimation_for_subcalls() { // Run the test for all of those weight limits for the subcall let weights = [ - Weight::zero(), + Weight::MAX, GAS_LIMIT, GAS_LIMIT * 2, GAS_LIMIT / 5, From b228eb2d146995d9da17c8366cf133746e14863a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexandre=20Bald=C3=A9?= Date: Thu, 9 Jan 2025 19:14:56 +0000 Subject: [PATCH 29/34] Revert EIP-150 changes Keep the "`0` as zero gas limit" changes. --- .../frame/revive/fixtures/contracts/call.rs | 2 +- substrate/frame/revive/src/exec.rs | 51 ++++++++------- substrate/frame/revive/src/gas.rs | 15 ++--- substrate/frame/revive/src/storage/meter.rs | 63 ++++++++++++------- substrate/frame/revive/src/tests.rs | 10 +-- 5 files changed, 77 insertions(+), 64 deletions(-) diff --git a/substrate/frame/revive/fixtures/contracts/call.rs b/substrate/frame/revive/fixtures/contracts/call.rs index d01fc31ac872..035db56a5b41 100644 --- a/substrate/frame/revive/fixtures/contracts/call.rs +++ b/substrate/frame/revive/fixtures/contracts/call.rs @@ -40,7 +40,7 @@ pub extern "C" fn call() { 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. - &U256_MAX, // No deposit limit. + &U256_MAX, // No deposit limit. &[0u8; 32], // Value transferred to the contract. callee_input, None, diff --git a/substrate/frame/revive/src/exec.rs b/substrate/frame/revive/src/exec.rs index 359d9608e940..f99f5eb5ae40 100644 --- a/substrate/frame/revive/src/exec.rs +++ b/substrate/frame/revive/src/exec.rs @@ -982,25 +982,14 @@ where }, }; - let nested_gas; - let nested_storage; - - if origin_is_caller { - nested_gas = gas_meter.nested_take_all(); - nested_storage = storage_meter.nested_take_all(); - } else { - nested_gas = gas_meter.nested(gas_limit); - nested_storage = storage_meter.nested(deposit_limit); - } - let frame = Frame { delegate, value_transferred, contract_info: CachedContract::Cached(contract_info), account_id, entry_point, - nested_gas, - nested_storage, + nested_gas: gas_meter.nested(gas_limit), + nested_storage: storage_meter.nested(deposit_limit), allows_reentry: true, read_only, last_frame_output: Default::default(), @@ -1128,15 +1117,25 @@ where return Ok(output); } + // Storage limit is normally enforced as late as possible (when the last frame returns) + // so that the ordering of storage accesses does not matter. + // (However, if a special limit was set for a sub-call, it should be enforced right + // after the sub-call returned. See below for this case of enforcement). + if self.frames.is_empty() { + let frame = &mut self.first_frame; + frame.contract_info.load(&frame.account_id); + let contract = frame.contract_info.as_contract(); + frame.nested_storage.enforce_limit(contract)?; + } + let frame = self.top_frame_mut(); - // The storage deposit is only charged at the end of every call stack. - // To make sure that no sub call uses more than it is allowed to, - // the limit is manually enforced here. + // If a special limit was set for the sub-call, we enforce it here. + // The sub-call will be rolled back in case the limit is exhausted. let contract = frame.contract_info.as_contract(); frame .nested_storage - .enforce_limit(contract) + .enforce_subcall_limit(contract) .map_err(|e| ExecError { error: e, origin: ErrorOrigin::Callee })?; let account_id = T::AddressMapper::to_address(&frame.account_id); @@ -1959,7 +1958,7 @@ mod tests { use assert_matches::assert_matches; use frame_support::{assert_err, assert_noop, assert_ok, parameter_types}; use frame_system::{AccountInfo, EventRecord, Phase}; - use pallet_revive_uapi::ReturnFlags; + use pallet_revive_uapi::{ReturnFlags, U256_MAX}; use pretty_assertions::assert_eq; use sp_io::hashing::keccak_256; use sp_runtime::{traits::Hash, DispatchError}; @@ -3100,7 +3099,7 @@ mod tests { .ext .instantiate( Weight::MAX, - U256::from(u64::MAX), + U256::from_little_endian(&U256_MAX), dummy_ch, ::Currency::minimum_balance().into(), vec![], @@ -3804,7 +3803,7 @@ mod tests { ctx.ext .instantiate( Weight::MAX, - U256::from(u64::MAX), + U256::from_little_endian(&U256_MAX), fail_code, ctx.ext.minimum_balance() * 100, vec![], @@ -3821,7 +3820,7 @@ mod tests { .ext .instantiate( Weight::MAX, - U256::from(u64::MAX), + U256::from_little_endian(&U256_MAX), success_code, ctx.ext.minimum_balance() * 100, vec![], @@ -4598,7 +4597,7 @@ mod tests { // Successful instantiation should set the output let address = ctx .ext - .instantiate(Weight::MAX, U256::from(u64::MAX), ok_ch, value, vec![], None) + .instantiate(Weight::MAX, U256::from_little_endian(&U256_MAX), ok_ch, value, vec![], None) .unwrap(); assert_eq!( ctx.ext.last_frame_output(), @@ -4609,7 +4608,7 @@ mod tests { ctx.ext .call( Weight::MAX, - U256::from(u64::MAX), + U256::from_little_endian(&U256_MAX), &address, U256::from(1), vec![], @@ -4828,7 +4827,7 @@ mod tests { // Constructors can not access the immutable data ctx.ext - .instantiate(Weight::MAX, U256::from(u64::MAX), dummy_ch, value, vec![], None) + .instantiate(Weight::MAX, U256::from_little_endian(&U256_MAX), dummy_ch, value, vec![], None) .unwrap(); exec_success() @@ -4945,7 +4944,7 @@ mod tests { move |ctx, _| { let value = ::Currency::minimum_balance().into(); ctx.ext - .instantiate(Weight::MAX, U256::from(u64::MAX), dummy_ch, value, vec![], None) + .instantiate(Weight::MAX, U256::from_little_endian(&U256_MAX), dummy_ch, value, vec![], None) .unwrap(); exec_success() @@ -4990,7 +4989,7 @@ mod tests { move |ctx, _| { let value = ::Currency::minimum_balance().into(); ctx.ext - .instantiate(Weight::MAX, U256::from(u64::MAX), dummy_ch, value, vec![], None) + .instantiate(Weight::MAX, U256::from_little_endian(&U256_MAX), dummy_ch, value, vec![], None) .unwrap(); exec_success() diff --git a/substrate/frame/revive/src/gas.rs b/substrate/frame/revive/src/gas.rs index d0fc604b7bc6..c7085dd08eb0 100644 --- a/substrate/frame/revive/src/gas.rs +++ b/substrate/frame/revive/src/gas.rs @@ -179,11 +179,8 @@ impl GasMeter { } /// Create a new gas meter for a nested call by removing gas from the current meter. - /// - /// Per [EIP-150](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-150.md), this is - /// capped at 63/64ths of the caller's gas limit. pub fn nested(&mut self, amount: Weight) -> Self { - let amount = amount.min(self.gas_left - self.gas_left / 64); + let amount = amount.min(self.gas_left); self.gas_left -= amount; GasMeter::new(amount) } @@ -419,10 +416,8 @@ mod tests { let mut gas_meter = GasMeter::::new(test_weight); let gas_for_nested_call = gas_meter.nested(test_weight); - // With EIP-150, it is not possible for subcalls to consume all available gas. - // They are limited to 63/64ths; 50000 / 64 ≈ 781 - assert_eq!(gas_meter.gas_left(), Weight::from_parts(781, 781)); - assert_eq!(gas_for_nested_call.gas_left(), 49219.into()) + assert_eq!(gas_meter.gas_left(), Weight::from_parts(0, 0)); + assert_eq!(gas_for_nested_call.gas_left(), 50_000.into()) } #[test] @@ -431,8 +426,8 @@ mod tests { let mut gas_meter = GasMeter::::new(test_weight); let gas_for_nested_call = gas_meter.nested(test_weight + 10000.into()); - assert_eq!(gas_meter.gas_left(), Weight::from_parts(781, 781)); - assert_eq!(gas_for_nested_call.gas_left(), 49219.into()) + assert_eq!(gas_meter.gas_left(), Weight::from_parts(0, 0)); + assert_eq!(gas_for_nested_call.gas_left(), 50_000.into()) } // Make sure that the gas meter does not charge in case of overcharge diff --git a/substrate/frame/revive/src/storage/meter.rs b/substrate/frame/revive/src/storage/meter.rs index aa198cfced94..dbf78f2fc929 100644 --- a/substrate/frame/revive/src/storage/meter.rs +++ b/substrate/frame/revive/src/storage/meter.rs @@ -32,7 +32,7 @@ use frame_support::{ DefaultNoBound, RuntimeDebugNoBound, }; use sp_runtime::{ - traits::{Saturating, Zero}, + traits::{Bounded, Saturating, Zero}, DispatchError, FixedPointNumber, FixedU128, }; @@ -100,8 +100,13 @@ pub trait State: private::Sealed {} pub struct Root; /// State parameter that constitutes a meter that is in its nested state. -#[derive(Default, Debug)] -pub struct Nested; +/// Its value indicates whether the nested meter has its own limit. +#[derive(DefaultNoBound, RuntimeDebugNoBound)] +pub enum Nested { + #[default] + DerivedLimit, + OwnLimit, +} impl State for Root {} impl State for Nested {} @@ -120,8 +125,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>, + /// We store the nested state to determine if it has a special limit for sub-call. + nested: S, /// Type parameter only used in impls. - _phantom: PhantomData<(E, S)>, + _phantom: PhantomData, } /// This type is used to describe a storage change when charging from the meter. @@ -270,6 +277,7 @@ impl Default for Contribution { impl RawMeter where T: Config, + BalanceOf: Bounded, E: Ext, S: State + Default + Debug, { @@ -278,18 +286,18 @@ where /// This is called whenever a new subcall is initiated in order to track the storage /// usage for this sub call separately. This is necessary because we want to exchange balance /// with the current contract we are interacting with. - /// - /// Gas for nested calls are capped to 63/64ths of the caller's originally available limit, per - /// EIP-150. pub fn nested(&self, limit: BalanceOf) -> RawMeter { debug_assert!(matches!(self.contract_state(), ContractState::Alive)); - let available = self.available() - self.available() / (BalanceOf::::from(64u32)); + if limit == BalanceOf::::max_value() { + RawMeter { limit: self.available(), ..Default::default() } + } else { + // If a special limit is specified higher than it is available, + // we want to enforce the lesser limit to the nested meter, to fail in the sub-call. + let limit = self.available().min(limit); - // If a special limit is specified higher than it is available, - // we want to enforce the lesser limit to the nested meter, to fail in the sub-call. - let limit = available.min(limit); - RawMeter { limit, ..Default::default() } + RawMeter { limit, nested: Nested::OwnLimit, ..Default::default() } + } } /// Absorb a child that was spawned to handle a sub call. @@ -341,14 +349,6 @@ where _ => ContractState::Alive, } } - - /// Create a new storage meter using the calling meter's available limit. - /// - /// This should only be used by the primordial frame in a sequence of calls - every subsequent - /// frame should use [`nested`](Self::nested) - pub fn nested_take_all(&self) -> RawMeter { - RawMeter { limit: self.available(), ..Default::default() } - } } /// Functions that only apply to the root state. @@ -479,6 +479,13 @@ impl> RawMeter { /// [`Self::charge`] does not enforce the storage limit since we want to do this check as late /// as possible to allow later refunds to offset earlier charges. + /// + /// # Note + /// + /// We normally need to call this **once** for every call stack and not for every cross contract + /// call. However, if a dedicated limit is specified for a sub-call, this needs to be called + /// once the sub-call has returned. For this, the [`Self::enforce_subcall_limit`] wrapper is + /// used. pub fn enforce_limit( &mut self, info: Option<&mut ContractInfo>, @@ -497,6 +504,18 @@ impl> RawMeter { } Ok(()) } + + /// This is a wrapper around [`Self::enforce_limit`] to use on the exit from a sub-call to + /// enforce its special limit if needed. + pub fn enforce_subcall_limit( + &mut self, + info: Option<&mut ContractInfo>, + ) -> Result<(), DispatchError> { + match self.nested { + Nested::OwnLimit => self.enforce_limit(info), + Nested::DerivedLimit => Ok(()), + } + } } impl Ext for ReservingExt { @@ -737,7 +756,7 @@ mod tests { let meter = TestMeter::new(&Origin::from_account_id(ALICE), 1_000, 0).unwrap(); assert_eq!(meter.available(), 1_000); let nested0 = meter.nested(1_000); - assert_eq!(nested0.available(), 985); + assert_eq!(nested0.available(), 1_000); } #[test] @@ -747,7 +766,7 @@ mod tests { let meter = TestMeter::new(&Origin::from_account_id(ALICE), 1_000, 0).unwrap(); assert_eq!(meter.available(), 1_000); let nested0 = meter.nested(2_000); - assert_eq!(nested0.available(), 985); + assert_eq!(nested0.available(), 1_000); } #[test] diff --git a/substrate/frame/revive/src/tests.rs b/substrate/frame/revive/src/tests.rs index f16aa67ea708..c4407eb56ff6 100644 --- a/substrate/frame/revive/src/tests.rs +++ b/substrate/frame/revive/src/tests.rs @@ -61,7 +61,7 @@ use frame_support::{ }; use frame_system::{EventRecord, Phase}; use pallet_revive_fixtures::{bench::dummy_unique, compile_module}; -use pallet_revive_uapi::ReturnErrorCode as RuntimeReturnCode; +use pallet_revive_uapi::{ReturnErrorCode as RuntimeReturnCode, U256_MAX}; use pallet_transaction_payment::{ConstFeeMultiplier, Multiplier}; use pretty_assertions::{assert_eq, assert_ne}; use sp_core::U256; @@ -3459,7 +3459,7 @@ fn deposit_limit_in_nested_calls() { assert_err_ignore_postinfo!( builder::call(addr_caller) .storage_deposit_limit(13) - .data((100u32, &addr_callee, U256::from(u64::MAX)).encode()) + .data((100u32, &addr_callee, U256_MAX).encode()) .build(), >::StorageDepositLimitExhausted, ); @@ -3473,7 +3473,7 @@ fn deposit_limit_in_nested_calls() { assert_err_ignore_postinfo!( builder::call(addr_caller) .storage_deposit_limit(14) - .data((101u32, &addr_callee, U256::from(u64::MAX)).encode()) + .data((101u32, &addr_callee, U256::from_little_endian(&U256_MAX),).encode()) .build(), >::StorageDepositLimitExhausted, ); @@ -3495,7 +3495,7 @@ fn deposit_limit_in_nested_calls() { assert_err_ignore_postinfo!( builder::call(addr_caller) .storage_deposit_limit(0) - .data((87u32, &addr_callee, U256::from(u64::MAX)).encode()) + .data((87u32, &addr_callee, U256::from_little_endian(&U256_MAX),).encode()) .build(), >::StorageDepositLimitExhausted, ); @@ -3554,7 +3554,7 @@ fn deposit_limit_in_nested_instantiate() { let ret = builder::bare_call(addr_caller) .origin(RuntimeOrigin::signed(BOB)) .storage_deposit_limit(DepositLimit::Balance(callee_info_len + 2 + ED + 1)) - .data((0u32, &code_hash_callee, U256::from(u64::MAX)).encode()) + .data((0u32, &code_hash_callee, U256::from_little_endian(&U256_MAX),).encode()) .build_and_unwrap_result(); assert_return_code!(ret, RuntimeReturnCode::OutOfResources); // The charges made on instantiation should be rolled back. From 3e4bbe8ca1746e8f4f98b7c7660bc39f1fad9f4a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexandre=20Bald=C3=A9?= Date: Thu, 9 Jan 2025 20:46:53 +0000 Subject: [PATCH 30/34] Remove `U256_MAX` const, use `U256::MAX` --- .../frame/revive/fixtures/contracts/call.rs | 10 ++-- .../contracts/call_diverging_out_len.rs | 6 +-- .../fixtures/contracts/call_return_code.rs | 10 ++-- .../contracts/call_runtime_and_call.rs | 10 ++-- .../contracts/call_with_flags_and_value.rs | 10 ++-- .../fixtures/contracts/call_with_limit.rs | 4 +- .../fixtures/contracts/caller_contract.rs | 50 +++++++++---------- .../contracts/chain_extension_temp_storage.rs | 10 ++-- .../fixtures/contracts/create1_with_value.rs | 14 +++++- .../create_transient_storage_and_call.rs | 10 ++-- .../fixtures/contracts/delegate_call.rs | 4 +- .../contracts/delegate_call_simple.rs | 4 +- .../contracts/destroy_and_transfer.rs | 20 ++++---- .../frame/revive/fixtures/contracts/drain.rs | 4 +- .../contracts/instantiate_return_code.rs | 4 +- .../contracts/locking_delegate_dependency.rs | 12 ++++- .../frame/revive/fixtures/contracts/origin.rs | 4 +- .../fixtures/contracts/read_only_call.rs | 10 ++-- .../revive/fixtures/contracts/recurse.rs | 10 ++-- .../fixtures/contracts/return_data_api.rs | 8 +-- .../fixtures/contracts/self_destruct.rs | 10 ++-- .../contracts/transfer_return_code.rs | 4 +- substrate/frame/revive/src/exec.rs | 32 +++++------- substrate/frame/revive/src/tests.rs | 10 ++-- substrate/frame/revive/uapi/src/lib.rs | 21 -------- 25 files changed, 140 insertions(+), 151 deletions(-) diff --git a/substrate/frame/revive/fixtures/contracts/call.rs b/substrate/frame/revive/fixtures/contracts/call.rs index 035db56a5b41..7c4c0882c6b8 100644 --- a/substrate/frame/revive/fixtures/contracts/call.rs +++ b/substrate/frame/revive/fixtures/contracts/call.rs @@ -20,7 +20,7 @@ #![no_main] use common::input; -use uapi::{HostFn, HostFnImpl as api, U256_MAX}; +use uapi::{HostFn, HostFnImpl as api}; #[no_mangle] #[polkavm_derive::polkavm_export] @@ -38,10 +38,10 @@ pub extern "C" fn call() { 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. - &U256_MAX, // No deposit limit. - &[0u8; 32], // Value transferred to the contract. + 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. + &[0u8; 32], // Value transferred to the contract. callee_input, None, ) diff --git a/substrate/frame/revive/fixtures/contracts/call_diverging_out_len.rs b/substrate/frame/revive/fixtures/contracts/call_diverging_out_len.rs index 069ec0a483e1..9a8fe5f5f6cc 100644 --- a/substrate/frame/revive/fixtures/contracts/call_diverging_out_len.rs +++ b/substrate/frame/revive/fixtures/contracts/call_diverging_out_len.rs @@ -28,7 +28,7 @@ extern crate common; -use uapi::{HostFn, HostFnImpl as api, U256_MAX}; +use uapi::{HostFn, HostFnImpl as api}; const BUF_SIZE: usize = 8; static DATA: [u8; BUF_SIZE] = [1, 2, 3, 4, 5, 6, 7, 8]; @@ -44,7 +44,7 @@ fn assert_call(callee_address: &[u8; 20], expected_output: [u8; callee_address, u64::MAX, u64::MAX, - &U256_MAX, + &[u8::MAX; 32], &[0u8; 32], &[], Some(output_buf_capped), @@ -69,7 +69,7 @@ fn assert_instantiate(expected_output: [u8; BUF_SIZE]) { &code_hash, u64::MAX, u64::MAX, - &U256_MAX, + &[u8::MAX; 32], &[0; 32], &[0; 32], None, diff --git a/substrate/frame/revive/fixtures/contracts/call_return_code.rs b/substrate/frame/revive/fixtures/contracts/call_return_code.rs index 00ac4e51f5fe..19b3ae3fdb26 100644 --- a/substrate/frame/revive/fixtures/contracts/call_return_code.rs +++ b/substrate/frame/revive/fixtures/contracts/call_return_code.rs @@ -22,7 +22,7 @@ #![no_main] use common::input; -use uapi::{HostFn, HostFnImpl as api, U256_MAX}; +use uapi::{HostFn, HostFnImpl as api}; #[no_mangle] #[polkavm_derive::polkavm_export] @@ -42,10 +42,10 @@ pub extern "C" fn call() { let err_code = match 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. - &U256_MAX, // No deposit limit. - value, // Value transferred to the contract. + 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. input, None, ) { diff --git a/substrate/frame/revive/fixtures/contracts/call_runtime_and_call.rs b/substrate/frame/revive/fixtures/contracts/call_runtime_and_call.rs index 5fc3242cf3ba..78b275459f0e 100644 --- a/substrate/frame/revive/fixtures/contracts/call_runtime_and_call.rs +++ b/substrate/frame/revive/fixtures/contracts/call_runtime_and_call.rs @@ -19,7 +19,7 @@ #![no_main] use common::input; -use uapi::{HostFn, HostFnImpl as api, U256_MAX}; +use uapi::{HostFn, HostFnImpl as api}; #[no_mangle] #[polkavm_derive::polkavm_export] @@ -42,10 +42,10 @@ pub extern "C" fn call() { 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. - &U256_MAX, // No deposit limit. - &[0u8; 32], // Value transferred to the contract. + 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. + &[0u8; 32], // Value transferred to the contract. callee_input, None, ) diff --git a/substrate/frame/revive/fixtures/contracts/call_with_flags_and_value.rs b/substrate/frame/revive/fixtures/contracts/call_with_flags_and_value.rs index d90b71aa73a5..155a4b41bd95 100644 --- a/substrate/frame/revive/fixtures/contracts/call_with_flags_and_value.rs +++ b/substrate/frame/revive/fixtures/contracts/call_with_flags_and_value.rs @@ -20,7 +20,7 @@ #![no_main] use common::{input, u256_bytes}; -use uapi::{HostFn, HostFnImpl as api, U256_MAX}; +use uapi::{HostFn, HostFnImpl as api}; #[no_mangle] #[polkavm_derive::polkavm_export] @@ -40,10 +40,10 @@ pub extern "C" fn call() { api::call( uapi::CallFlags::from_bits(flags).unwrap(), 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. - &U256_MAX, // No deposit limit. - &u256_bytes(value), // Value transferred to the contract. + 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. + &u256_bytes(value), // Value transferred to the contract. forwarded_input, None, ) diff --git a/substrate/frame/revive/fixtures/contracts/call_with_limit.rs b/substrate/frame/revive/fixtures/contracts/call_with_limit.rs index 4ff0352dfe51..af5c301a353c 100644 --- a/substrate/frame/revive/fixtures/contracts/call_with_limit.rs +++ b/substrate/frame/revive/fixtures/contracts/call_with_limit.rs @@ -21,7 +21,7 @@ #![no_main] use common::input; -use uapi::{HostFn, HostFnImpl as api, U256_MAX}; +use uapi::{HostFn, HostFnImpl as api}; #[no_mangle] #[polkavm_derive::polkavm_export] @@ -43,7 +43,7 @@ pub extern "C" fn call() { callee_addr, ref_time, proof_size, - &U256_MAX, // No deposit limit. + &[u8::MAX; 32], // No deposit limit. &[0u8; 32], // value transferred to the contract. forwarded_input, None, diff --git a/substrate/frame/revive/fixtures/contracts/caller_contract.rs b/substrate/frame/revive/fixtures/contracts/caller_contract.rs index 99a821ebc0e8..d042dc2c22a2 100644 --- a/substrate/frame/revive/fixtures/contracts/caller_contract.rs +++ b/substrate/frame/revive/fixtures/contracts/caller_contract.rs @@ -19,7 +19,7 @@ #![no_main] use common::{input, u256_bytes}; -use uapi::{HostFn, HostFnImpl as api, ReturnErrorCode, U256_MAX}; +use uapi::{HostFn, HostFnImpl as api, ReturnErrorCode}; #[no_mangle] #[polkavm_derive::polkavm_export] @@ -42,9 +42,9 @@ pub extern "C" fn call() { // Fail to deploy the contract since it returns a non-zero exit status. let res = api::instantiate( code_hash, - u64::MAX, // How much ref_time weight to devote for the execution. u64::MAX = use all. - u64::MAX, // How much proof_size weight to devote for the execution. u64::MAX = use all. - &U256_MAX, // No deposit limit. + u64::MAX, // How much ref_time weight to devote for the execution. u64::MAX = use all. + u64::MAX, // How much proof_size weight to devote for the execution. u64::MAX = use all. + &[u8::MAX; 32], // No deposit limit. &value, &reverted_input, None, @@ -56,9 +56,9 @@ pub extern "C" fn call() { // Fail to deploy the contract due to insufficient ref_time weight. let res = api::instantiate( code_hash, - 1u64, // too little ref_time weight - u64::MAX, // How much proof_size weight to devote for the execution. u64::MAX = use all. - &U256_MAX, // No deposit limit. + 1u64, // too little ref_time weight + u64::MAX, // How much proof_size weight to devote for the execution. u64::MAX = use all. + &[u8::MAX; 32], // No deposit limit. &value, &input, None, @@ -70,9 +70,9 @@ pub extern "C" fn call() { // Fail to deploy the contract due to insufficient proof_size weight. let res = api::instantiate( code_hash, - u64::MAX, // How much ref_time weight to devote for the execution. u64::MAX = use all. - 1u64, // Too little proof_size weight - &U256_MAX, // No deposit limit. + u64::MAX, // How much ref_time weight to devote for the execution. u64::MAX = use all. + 1u64, // Too little proof_size weight + &[u8::MAX; 32], // No deposit limit. &value, &input, None, @@ -86,9 +86,9 @@ pub extern "C" fn call() { api::instantiate( code_hash, - u64::MAX, // How much ref_time weight to devote for the execution. u64::MAX = use all. - u64::MAX, // How much proof_size weight to devote for the execution. u64::MAX = use all. - &U256_MAX, // No deposit limit. + u64::MAX, // How much ref_time weight to devote for the execution. u64::MAX = use all. + u64::MAX, // How much proof_size weight to devote for the execution. u64::MAX = use all. + &[u8::MAX; 32], // No deposit limit. &value, &input, Some(&mut callee), @@ -101,9 +101,9 @@ pub extern "C" fn call() { let res = api::call( uapi::CallFlags::empty(), &callee, - u64::MAX, // How much ref_time weight to devote for the execution. u64::MAX = use all. - u64::MAX, // How much proof_size weight to devote for the execution. u64::MAX = use all. - &U256_MAX, // No deposit limit. + u64::MAX, // How much ref_time weight to devote for the execution. u64::MAX = use all. + u64::MAX, // How much proof_size weight to devote for the execution. u64::MAX = use all. + &[u8::MAX; 32], // No deposit limit. &value, &reverted_input, None, @@ -114,9 +114,9 @@ pub extern "C" fn call() { let res = api::call( uapi::CallFlags::empty(), &callee, - 1u64, // Too little ref_time weight. - u64::MAX, // How much proof_size weight to devote for the execution. u64::MAX = use all. - &U256_MAX, // No deposit limit. + 1u64, // Too little ref_time weight. + u64::MAX, // How much proof_size weight to devote for the execution. u64::MAX = use all. + &[u8::MAX; 32], // No deposit limit. &value, &input, None, @@ -127,9 +127,9 @@ pub extern "C" fn call() { let res = api::call( uapi::CallFlags::empty(), &callee, - u64::MAX, // How much ref_time weight to devote for the execution. u64::MAX = use all. - 1u64, // too little proof_size weight - &U256_MAX, // No deposit limit. + u64::MAX, // How much ref_time weight to devote for the execution. u64::MAX = use all. + 1u64, // too little proof_size weight + &[u8::MAX; 32], // No deposit limit. &value, &input, None, @@ -141,9 +141,9 @@ pub extern "C" fn call() { api::call( uapi::CallFlags::empty(), &callee, - u64::MAX, // How much ref_time weight to devote for the execution. u64::MAX = use all. - u64::MAX, // How much proof_size weight to devote for the execution. u64::MAX = use all. - &U256_MAX, // No deposit limit. + u64::MAX, // How much ref_time weight to devote for the execution. u64::MAX = use all. + u64::MAX, // How much proof_size weight to devote for the execution. u64::MAX = use all. + &[u8::MAX; 32], // No deposit limit. &value, &input, Some(&mut &mut output[..]), diff --git a/substrate/frame/revive/fixtures/contracts/chain_extension_temp_storage.rs b/substrate/frame/revive/fixtures/contracts/chain_extension_temp_storage.rs index 8c3e897df813..9b76b9d39ee9 100644 --- a/substrate/frame/revive/fixtures/contracts/chain_extension_temp_storage.rs +++ b/substrate/frame/revive/fixtures/contracts/chain_extension_temp_storage.rs @@ -21,7 +21,7 @@ #![no_main] use common::input; -use uapi::{HostFn, HostFnImpl as api, U256_MAX}; +use uapi::{HostFn, HostFnImpl as api}; #[no_mangle] #[polkavm_derive::polkavm_export] @@ -54,10 +54,10 @@ pub extern "C" fn call() { api::call( uapi::CallFlags::ALLOW_REENTRY, &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. - &U256_MAX, // No deposit limit. - &[0u8; 32], // Value transferred to the contract. + 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. + &[0u8; 32], // Value transferred to the contract. input, None, ) diff --git a/substrate/frame/revive/fixtures/contracts/create1_with_value.rs b/substrate/frame/revive/fixtures/contracts/create1_with_value.rs index 22de069db5e6..3554f8f620a2 100644 --- a/substrate/frame/revive/fixtures/contracts/create1_with_value.rs +++ b/substrate/frame/revive/fixtures/contracts/create1_with_value.rs @@ -19,7 +19,7 @@ #![no_main] use common::input; -use uapi::{HostFn, HostFnImpl as api, U256_MAX}; +use uapi::{HostFn, HostFnImpl as api}; #[no_mangle] #[polkavm_derive::polkavm_export] @@ -34,6 +34,16 @@ pub extern "C" fn call() { api::value_transferred(&mut value); // Deploy the contract with no salt (equivalent to create1). - let ret = api::instantiate(code_hash, u64::MAX, u64::MAX, &U256_MAX, &value, &[], None, None, None); + let ret = api::instantiate( + code_hash, + u64::MAX, + u64::MAX, + &[u8::MAX; 32], + &value, + &[], + None, + None, + None + ); assert!(ret.is_ok()); } diff --git a/substrate/frame/revive/fixtures/contracts/create_transient_storage_and_call.rs b/substrate/frame/revive/fixtures/contracts/create_transient_storage_and_call.rs index 390b6e0735e3..660db84028db 100644 --- a/substrate/frame/revive/fixtures/contracts/create_transient_storage_and_call.rs +++ b/substrate/frame/revive/fixtures/contracts/create_transient_storage_and_call.rs @@ -20,7 +20,7 @@ #![no_main] use common::input; -use uapi::{HostFn, HostFnImpl as api, StorageFlags, U256_MAX}; +use uapi::{HostFn, HostFnImpl as api, StorageFlags}; static BUFFER: [u8; 448] = [0u8; 448]; @@ -49,10 +49,10 @@ pub extern "C" fn call() { api::call( uapi::CallFlags::empty(), callee, - u64::MAX, // How much ref_time weight to devote for the execution. u64::MAX = all. - u64::MAX, // How much proof_size weight to devote for the execution. u64::MAX = all. - &U256_MAX, // No deposit limit. - &[0u8; 32], // Value transferred to the contract. + u64::MAX, // How much ref_time weight to devote for the execution. u64::MAX = all. + u64::MAX, // How much proof_size weight to devote for the execution. u64::MAX = all. + &[u8::MAX; 32], // No deposit limit. + &[0u8; 32], // Value transferred to the contract. input, None, ) diff --git a/substrate/frame/revive/fixtures/contracts/delegate_call.rs b/substrate/frame/revive/fixtures/contracts/delegate_call.rs index 686c459b9da9..0dedd5f704cb 100644 --- a/substrate/frame/revive/fixtures/contracts/delegate_call.rs +++ b/substrate/frame/revive/fixtures/contracts/delegate_call.rs @@ -19,7 +19,7 @@ #![no_main] use common::input; -use uapi::{HostFn, HostFnImpl as api, StorageFlags, U256_MAX}; +use uapi::{HostFn, HostFnImpl as api, StorageFlags}; #[no_mangle] #[polkavm_derive::polkavm_export] @@ -51,7 +51,7 @@ pub extern "C" fn call() { address, ref_time, proof_size, - &U256_MAX, + &[u8::MAX; 32], &input, None ).unwrap(); diff --git a/substrate/frame/revive/fixtures/contracts/delegate_call_simple.rs b/substrate/frame/revive/fixtures/contracts/delegate_call_simple.rs index 116d648bb60d..b7bdb792c76c 100644 --- a/substrate/frame/revive/fixtures/contracts/delegate_call_simple.rs +++ b/substrate/frame/revive/fixtures/contracts/delegate_call_simple.rs @@ -19,7 +19,7 @@ #![no_main] use common::input; -use uapi::{HostFn, HostFnImpl as api, U256_MAX}; +use uapi::{HostFn, HostFnImpl as api}; #[no_mangle] #[polkavm_derive::polkavm_export] @@ -37,7 +37,7 @@ pub extern "C" fn call() { address, u64::MAX, u64::MAX, - &U256_MAX, + &[u8::MAX; 32], &input, None ).unwrap(); diff --git a/substrate/frame/revive/fixtures/contracts/destroy_and_transfer.rs b/substrate/frame/revive/fixtures/contracts/destroy_and_transfer.rs index e921b1b9f336..c2c7da528ba7 100644 --- a/substrate/frame/revive/fixtures/contracts/destroy_and_transfer.rs +++ b/substrate/frame/revive/fixtures/contracts/destroy_and_transfer.rs @@ -19,7 +19,7 @@ #![no_main] use common::{input, u256_bytes}; -use uapi::{HostFn, HostFnImpl as api, StorageFlags, U256_MAX}; +use uapi::{HostFn, HostFnImpl as api, StorageFlags}; const ADDRESS_KEY: [u8; 32] = [0u8; 32]; const VALUE: [u8; 32] = u256_bytes(65536); @@ -35,9 +35,9 @@ pub extern "C" fn deploy() { api::instantiate( code_hash, - u64::MAX, // How much ref_time weight to devote for the execution. u64::MAX = use all. - u64::MAX, // How much proof_size weight to devote for the execution. u64::MAX = use all. - &U256_MAX, // No deposit limit. + u64::MAX, // How much ref_time weight to devote for the execution. u64::MAX = use all. + u64::MAX, // How much proof_size weight to devote for the execution. u64::MAX = use all. + &[u8::MAX; 32], // No deposit limit. &VALUE, &input, Some(&mut address), @@ -62,9 +62,9 @@ pub extern "C" fn call() { let res = api::call( uapi::CallFlags::empty(), &callee_addr, - u64::MAX, // How much ref_time weight to devote for the execution. u64::MAX = use all. - u64::MAX, // How much proof_size weight to devote for the execution. u64::MAX = use all. - &U256_MAX, // No deposit limit. + u64::MAX, // How much ref_time weight to devote for the execution. u64::MAX = use all. + u64::MAX, // How much proof_size weight to devote for the execution. u64::MAX = use all. + &[u8::MAX; 32], // No deposit limit. &VALUE, &[0u8; 1], None, @@ -75,9 +75,9 @@ pub extern "C" fn call() { api::call( uapi::CallFlags::empty(), &callee_addr, - u64::MAX, // How much ref_time weight to devote for the execution. u64::MAX = use all. - u64::MAX, // How much proof_size weight to devote for the execution. u64::MAX = use all. - &U256_MAX, // No deposit limit. + u64::MAX, // How much ref_time weight to devote for the execution. u64::MAX = use all. + u64::MAX, // How much proof_size weight to devote for the execution. u64::MAX = use all. + &[u8::MAX; 32], // No deposit limit. &VALUE, &[0u8; 0], None, diff --git a/substrate/frame/revive/fixtures/contracts/drain.rs b/substrate/frame/revive/fixtures/contracts/drain.rs index 23bd6e0a4704..53fb213143c4 100644 --- a/substrate/frame/revive/fixtures/contracts/drain.rs +++ b/substrate/frame/revive/fixtures/contracts/drain.rs @@ -19,7 +19,7 @@ #![no_main] use common::{u256_bytes, u64_output}; -use uapi::{HostFn, HostFnImpl as api, U256_MAX}; +use uapi::{HostFn, HostFnImpl as api}; #[no_mangle] #[polkavm_derive::polkavm_export] @@ -41,7 +41,7 @@ pub extern "C" fn call() { &[0u8; 20], 0, 0, - &U256_MAX, + &[u8::MAX; 32], &u256_bytes(balance), &[], None, diff --git a/substrate/frame/revive/fixtures/contracts/instantiate_return_code.rs b/substrate/frame/revive/fixtures/contracts/instantiate_return_code.rs index 6b43f9fed9cd..f7cbd75be5aa 100644 --- a/substrate/frame/revive/fixtures/contracts/instantiate_return_code.rs +++ b/substrate/frame/revive/fixtures/contracts/instantiate_return_code.rs @@ -19,7 +19,7 @@ #![no_main] use common::{input, u256_bytes}; -use uapi::{HostFn, HostFnImpl as api, U256_MAX}; +use uapi::{HostFn, HostFnImpl as api}; #[no_mangle] #[polkavm_derive::polkavm_export] @@ -35,7 +35,7 @@ pub extern "C" fn call() { code_hash, u64::MAX, // How much ref_time weight to devote for the execution. u64::MAX = use all. u64::MAX, // How much proof_size weight to devote for the execution. u64::MAX = use all. - &U256_MAX, // No deposit limit. + &[u8::MAX; 32], // No deposit limit. &u256_bytes(10_000u64), // Value to transfer. input, None, diff --git a/substrate/frame/revive/fixtures/contracts/locking_delegate_dependency.rs b/substrate/frame/revive/fixtures/contracts/locking_delegate_dependency.rs index 9d0bbe5c8b9a..6be5d5c72f9a 100644 --- a/substrate/frame/revive/fixtures/contracts/locking_delegate_dependency.rs +++ b/substrate/frame/revive/fixtures/contracts/locking_delegate_dependency.rs @@ -21,7 +21,7 @@ #![no_main] use common::input; -use uapi::{HostFn, HostFnImpl as api, U256_MAX}; +use uapi::{HostFn, HostFnImpl as api}; const ALICE_FALLBACK: [u8; 20] = [1u8; 20]; @@ -52,7 +52,15 @@ fn load_input(delegate_call: bool) { } if delegate_call { - api::delegate_call(uapi::CallFlags::empty(), address, u64::MAX, u64::MAX, &U256_MAX, &[], None).unwrap(); + api::delegate_call( + uapi::CallFlags::empty(), + address, + u64::MAX, + u64::MAX, + &[u8::MAX; 32], + &[], + None + ).unwrap(); } } diff --git a/substrate/frame/revive/fixtures/contracts/origin.rs b/substrate/frame/revive/fixtures/contracts/origin.rs index b12a45b114f8..151ca3da77cd 100644 --- a/substrate/frame/revive/fixtures/contracts/origin.rs +++ b/substrate/frame/revive/fixtures/contracts/origin.rs @@ -23,7 +23,7 @@ #![no_main] extern crate common; -use uapi::{HostFn, HostFnImpl as api, U256_MAX}; +use uapi::{HostFn, HostFnImpl as api}; #[no_mangle] #[polkavm_derive::polkavm_export] @@ -51,7 +51,7 @@ pub extern "C" fn call() { &addr, u64::MAX, u64::MAX, - &U256_MAX, + &[u8::MAX; 32], &[0; 32], &[], Some(&mut &mut buf[..]), diff --git a/substrate/frame/revive/fixtures/contracts/read_only_call.rs b/substrate/frame/revive/fixtures/contracts/read_only_call.rs index 96786cf9e370..0a87ecbb9b14 100644 --- a/substrate/frame/revive/fixtures/contracts/read_only_call.rs +++ b/substrate/frame/revive/fixtures/contracts/read_only_call.rs @@ -20,7 +20,7 @@ #![no_main] use common::input; -use uapi::{HostFn, HostFnImpl as api, U256_MAX}; +use uapi::{HostFn, HostFnImpl as api}; #[no_mangle] #[polkavm_derive::polkavm_export] @@ -39,10 +39,10 @@ pub extern "C" fn call() { api::call( uapi::CallFlags::READ_ONLY, callee_addr, - u64::MAX, // How much ref_time to devote for the execution. u64::MAX = all. - u64::MAX, // How much proof_size to devote for the execution. u64::MAX = all. - &U256_MAX, // No deposit limit. - &[0u8; 32], // Value transferred to the contract. + u64::MAX, // How much ref_time to devote for the execution. u64::MAX = all. + u64::MAX, // How much proof_size to devote for the execution. u64::MAX = all. + &[u8::MAX; 32], // No deposit limit. + &[0u8; 32], // Value transferred to the contract. callee_input, None, ) diff --git a/substrate/frame/revive/fixtures/contracts/recurse.rs b/substrate/frame/revive/fixtures/contracts/recurse.rs index 64b4358e5ffb..ead565c01459 100644 --- a/substrate/frame/revive/fixtures/contracts/recurse.rs +++ b/substrate/frame/revive/fixtures/contracts/recurse.rs @@ -21,7 +21,7 @@ #![no_main] use common::input; -use uapi::{HostFn, HostFnImpl as api, U256_MAX}; +use uapi::{HostFn, HostFnImpl as api}; #[no_mangle] #[polkavm_derive::polkavm_export] @@ -43,10 +43,10 @@ pub extern "C" fn call() { 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. - &U256_MAX, // No deposit limit. - &[0u8; 32], // Value transferred to the contract. + 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, ) diff --git a/substrate/frame/revive/fixtures/contracts/return_data_api.rs b/substrate/frame/revive/fixtures/contracts/return_data_api.rs index 0ce89bc71ca6..1407e5323ea1 100644 --- a/substrate/frame/revive/fixtures/contracts/return_data_api.rs +++ b/substrate/frame/revive/fixtures/contracts/return_data_api.rs @@ -27,7 +27,7 @@ #![no_main] use common::{input, u256_bytes}; -use uapi::{HostFn, HostFnImpl as api, U256_MAX}; +use uapi::{HostFn, HostFnImpl as api}; const INPUT_BUF_SIZE: usize = 128; static INPUT_DATA: [u8; INPUT_BUF_SIZE] = [0xFF; INPUT_BUF_SIZE]; @@ -85,7 +85,7 @@ fn assert_balance_transfer_does_reset() { &[0u8; 20], u64::MAX, u64::MAX, - &U256_MAX, + &[u8::MAX; 32], &u256_bytes(128), &[], None @@ -121,7 +121,7 @@ pub extern "C" fn call() { code_hash, u64::MAX, u64::MAX, - &U256_MAX, + &[u8::MAX; 32], &[0; 32], &construct_input(exit_flag), Some(&mut address_buf), @@ -135,7 +135,7 @@ pub extern "C" fn call() { address_buf, u64::MAX, u64::MAX, - &U256_MAX, + &[u8::MAX; 32], &[0; 32], &construct_input(exit_flag), None, diff --git a/substrate/frame/revive/fixtures/contracts/self_destruct.rs b/substrate/frame/revive/fixtures/contracts/self_destruct.rs index ea3eedf9ee0c..053e545deb19 100644 --- a/substrate/frame/revive/fixtures/contracts/self_destruct.rs +++ b/substrate/frame/revive/fixtures/contracts/self_destruct.rs @@ -19,7 +19,7 @@ #![no_main] use common::input; -use uapi::{HostFn, HostFnImpl as api, U256_MAX}; +use uapi::{HostFn, HostFnImpl as api}; const DJANGO_FALLBACK: [u8; 20] = [4u8; 20]; @@ -42,10 +42,10 @@ pub extern "C" fn call() { api::call( uapi::CallFlags::ALLOW_REENTRY, &addr, - u64::MAX, // How much ref_time to devote for the execution. u64 = all. - u64::MAX, // How much proof_size to devote for the execution. u64 = all. - &U256_MAX, // No deposit limit. - &[0u8; 32], // Value to transfer. + u64::MAX, // How much ref_time to devote for the execution. u64 = all. + u64::MAX, // How much proof_size to devote for the execution. u64 = all. + &[u8::MAX; 32], // No deposit limit. + &[0u8; 32], // Value to transfer. &[0u8; 0], None, ) diff --git a/substrate/frame/revive/fixtures/contracts/transfer_return_code.rs b/substrate/frame/revive/fixtures/contracts/transfer_return_code.rs index cbfe34f96964..053f97feda4a 100644 --- a/substrate/frame/revive/fixtures/contracts/transfer_return_code.rs +++ b/substrate/frame/revive/fixtures/contracts/transfer_return_code.rs @@ -19,7 +19,7 @@ #![no_main] use common::u256_bytes; -use uapi::{HostFn, HostFnImpl as api, U256_MAX}; +use uapi::{HostFn, HostFnImpl as api}; #[no_mangle] #[polkavm_derive::polkavm_export] @@ -33,7 +33,7 @@ pub extern "C" fn call() { &[0u8; 20], 0, 0, - &U256_MAX, + &[u8::MAX; 32], &u256_bytes(100u64), &[], None, diff --git a/substrate/frame/revive/src/exec.rs b/substrate/frame/revive/src/exec.rs index f99f5eb5ae40..a8d0da88ff40 100644 --- a/substrate/frame/revive/src/exec.rs +++ b/substrate/frame/revive/src/exec.rs @@ -1463,7 +1463,7 @@ where FrameArgs::Call { dest: dest.clone(), cached_info, delegated_call: None }, value, gas_limit, - deposit_limit.try_into().map_err(|_| Error::::BalanceConversionFailed)?, + deposit_limit.saturated_into::>(), // Enable read-only access if requested; cannot disable it if already set. read_only || self.is_read_only(), )? { @@ -1519,7 +1519,7 @@ where }, value, gas_limit, - deposit_limit.try_into().map_err(|_| Error::::BalanceConversionFailed)?, + deposit_limit.saturated_into::>(), self.is_read_only(), )?; self.run(executable.expect(FRAME_ALWAYS_EXISTS_ON_INSTANTIATE), input_data) @@ -1549,7 +1549,7 @@ where }, value.try_into().map_err(|_| Error::::BalanceConversionFailed)?, gas_limit, - deposit_limit.try_into().map_err(|_| Error::::BalanceConversionFailed)?, + deposit_limit.saturated_into::>(), self.is_read_only(), )?; let address = T::AddressMapper::to_address(&self.top_frame().account_id); @@ -1958,7 +1958,7 @@ mod tests { use assert_matches::assert_matches; use frame_support::{assert_err, assert_noop, assert_ok, parameter_types}; use frame_system::{AccountInfo, EventRecord, Phase}; - use pallet_revive_uapi::{ReturnFlags, U256_MAX}; + use pallet_revive_uapi::ReturnFlags; use pretty_assertions::assert_eq; use sp_io::hashing::keccak_256; use sp_runtime::{traits::Hash, DispatchError}; @@ -3099,7 +3099,7 @@ mod tests { .ext .instantiate( Weight::MAX, - U256::from_little_endian(&U256_MAX), + U256::MAX, dummy_ch, ::Currency::minimum_balance().into(), vec![], @@ -3803,7 +3803,7 @@ mod tests { ctx.ext .instantiate( Weight::MAX, - U256::from_little_endian(&U256_MAX), + U256::MAX, fail_code, ctx.ext.minimum_balance() * 100, vec![], @@ -3820,7 +3820,7 @@ mod tests { .ext .instantiate( Weight::MAX, - U256::from_little_endian(&U256_MAX), + U256::MAX, success_code, ctx.ext.minimum_balance() * 100, vec![], @@ -4597,7 +4597,7 @@ mod tests { // Successful instantiation should set the output let address = ctx .ext - .instantiate(Weight::MAX, U256::from_little_endian(&U256_MAX), ok_ch, value, vec![], None) + .instantiate(Weight::MAX, U256::MAX, ok_ch, value, vec![], None) .unwrap(); assert_eq!( ctx.ext.last_frame_output(), @@ -4606,15 +4606,7 @@ mod tests { // Balance transfers should reset the output ctx.ext - .call( - Weight::MAX, - U256::from_little_endian(&U256_MAX), - &address, - U256::from(1), - vec![], - true, - false, - ) + .call(Weight::MAX, U256::MAX, &address, U256::from(1), vec![], true, false) .unwrap(); assert_eq!(ctx.ext.last_frame_output(), &Default::default()); @@ -4827,7 +4819,7 @@ mod tests { // Constructors can not access the immutable data ctx.ext - .instantiate(Weight::MAX, U256::from_little_endian(&U256_MAX), dummy_ch, value, vec![], None) + .instantiate(Weight::MAX, U256::MAX, dummy_ch, value, vec![], None) .unwrap(); exec_success() @@ -4944,7 +4936,7 @@ mod tests { move |ctx, _| { let value = ::Currency::minimum_balance().into(); ctx.ext - .instantiate(Weight::MAX, U256::from_little_endian(&U256_MAX), dummy_ch, value, vec![], None) + .instantiate(Weight::MAX, U256::MAX, dummy_ch, value, vec![], None) .unwrap(); exec_success() @@ -4989,7 +4981,7 @@ mod tests { move |ctx, _| { let value = ::Currency::minimum_balance().into(); ctx.ext - .instantiate(Weight::MAX, U256::from_little_endian(&U256_MAX), dummy_ch, value, vec![], None) + .instantiate(Weight::MAX, U256::MAX, dummy_ch, value, vec![], None) .unwrap(); exec_success() diff --git a/substrate/frame/revive/src/tests.rs b/substrate/frame/revive/src/tests.rs index c4407eb56ff6..04a6c4416062 100644 --- a/substrate/frame/revive/src/tests.rs +++ b/substrate/frame/revive/src/tests.rs @@ -61,7 +61,7 @@ use frame_support::{ }; use frame_system::{EventRecord, Phase}; use pallet_revive_fixtures::{bench::dummy_unique, compile_module}; -use pallet_revive_uapi::{ReturnErrorCode as RuntimeReturnCode, U256_MAX}; +use pallet_revive_uapi::ReturnErrorCode as RuntimeReturnCode; use pallet_transaction_payment::{ConstFeeMultiplier, Multiplier}; use pretty_assertions::{assert_eq, assert_ne}; use sp_core::U256; @@ -3459,7 +3459,7 @@ fn deposit_limit_in_nested_calls() { assert_err_ignore_postinfo!( builder::call(addr_caller) .storage_deposit_limit(13) - .data((100u32, &addr_callee, U256_MAX).encode()) + .data((100u32, &addr_callee, U256::MAX).encode()) .build(), >::StorageDepositLimitExhausted, ); @@ -3473,7 +3473,7 @@ fn deposit_limit_in_nested_calls() { assert_err_ignore_postinfo!( builder::call(addr_caller) .storage_deposit_limit(14) - .data((101u32, &addr_callee, U256::from_little_endian(&U256_MAX),).encode()) + .data((101u32, &addr_callee, &U256::MAX).encode()) .build(), >::StorageDepositLimitExhausted, ); @@ -3495,7 +3495,7 @@ fn deposit_limit_in_nested_calls() { assert_err_ignore_postinfo!( builder::call(addr_caller) .storage_deposit_limit(0) - .data((87u32, &addr_callee, U256::from_little_endian(&U256_MAX),).encode()) + .data((87u32, &addr_callee, &U256::MAX.to_little_endian()).encode()) .build(), >::StorageDepositLimitExhausted, ); @@ -3554,7 +3554,7 @@ fn deposit_limit_in_nested_instantiate() { let ret = builder::bare_call(addr_caller) .origin(RuntimeOrigin::signed(BOB)) .storage_deposit_limit(DepositLimit::Balance(callee_info_len + 2 + ED + 1)) - .data((0u32, &code_hash_callee, U256::from_little_endian(&U256_MAX),).encode()) + .data((0u32, &code_hash_callee, &U256::MAX.to_little_endian()).encode()) .build_and_unwrap_result(); assert_return_code!(ret, RuntimeReturnCode::OutOfResources); // The charges made on instantiation should be rolled back. diff --git a/substrate/frame/revive/uapi/src/lib.rs b/substrate/frame/revive/uapi/src/lib.rs index 0715532c61e7..ef1798b4bf61 100644 --- a/substrate/frame/revive/uapi/src/lib.rs +++ b/substrate/frame/revive/uapi/src/lib.rs @@ -116,27 +116,6 @@ pub struct ReturnCode(u32); /// make sense for a memory location or length. const SENTINEL: u32 = u32::MAX; -/// Converts a `u64` to a 32-byte array, encoded little-endian. -/// -/// The `u64` value will be placed in the first 8 bytes, -/// and the remaining bytes are set to zero. -const fn u64_to_u256_bytes(value: u64) -> [u8; 32] { - let mut bytes = [0u8; 32]; - let value_bytes = value.to_le_bytes(); - let mut i = 0; - while i < 8 { - bytes[i] = value_bytes[i]; - i += 1; - } - bytes -} - -/// A constant representing `u64::MAX` as a 32-byte array, in little-endian encoding. -/// -/// Deposit limits are `U256`, but balances are represented as `u64`. -/// To represent no deposit limits on an operation, this should be used. -pub const U256_MAX: [u8; 32] = u64_to_u256_bytes(u64::MAX); - impl From for Option { fn from(code: ReturnCode) -> Self { (code.0 < SENTINEL).then_some(code.0) From 7c6aedbbd7de94d38ff806e3e67ea025a4e34d16 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexandre=20Bald=C3=A9?= Date: Fri, 10 Jan 2025 14:56:01 +0000 Subject: [PATCH 31/34] Remove `enforce_subcall_limit` and associated logic --- substrate/frame/revive/src/exec.rs | 18 ++------- substrate/frame/revive/src/storage/meter.rs | 41 ++------------------- substrate/frame/revive/src/tests.rs | 4 +- 3 files changed, 10 insertions(+), 53 deletions(-) diff --git a/substrate/frame/revive/src/exec.rs b/substrate/frame/revive/src/exec.rs index a8d0da88ff40..75db1bc7a4fe 100644 --- a/substrate/frame/revive/src/exec.rs +++ b/substrate/frame/revive/src/exec.rs @@ -1117,25 +1117,15 @@ where return Ok(output); } - // Storage limit is normally enforced as late as possible (when the last frame returns) - // so that the ordering of storage accesses does not matter. - // (However, if a special limit was set for a sub-call, it should be enforced right - // after the sub-call returned. See below for this case of enforcement). - if self.frames.is_empty() { - let frame = &mut self.first_frame; - frame.contract_info.load(&frame.account_id); - let contract = frame.contract_info.as_contract(); - frame.nested_storage.enforce_limit(contract)?; - } - let frame = self.top_frame_mut(); - // If a special limit was set for the sub-call, we enforce it here. - // The sub-call will be rolled back in case the limit is exhausted. + // The storage deposit is only charged at the end of every call stack. + // To make sure that no sub call uses more than it is allowed to, + // the limit is manually enforced here. let contract = frame.contract_info.as_contract(); frame .nested_storage - .enforce_subcall_limit(contract) + .enforce_limit(contract) .map_err(|e| ExecError { error: e, origin: ErrorOrigin::Callee })?; let account_id = T::AddressMapper::to_address(&frame.account_id); diff --git a/substrate/frame/revive/src/storage/meter.rs b/substrate/frame/revive/src/storage/meter.rs index dbf78f2fc929..d61a6407307f 100644 --- a/substrate/frame/revive/src/storage/meter.rs +++ b/substrate/frame/revive/src/storage/meter.rs @@ -101,12 +101,8 @@ pub struct Root; /// State parameter that constitutes a meter that is in its nested state. /// Its value indicates whether the nested meter has its own limit. -#[derive(DefaultNoBound, RuntimeDebugNoBound)] -pub enum Nested { - #[default] - DerivedLimit, - OwnLimit, -} +#[derive(Default, Debug)] +pub struct Nested; impl State for Root {} impl State for Nested {} @@ -125,10 +121,8 @@ 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>, - /// We store the nested state to determine if it has a special limit for sub-call. - nested: S, /// Type parameter only used in impls. - _phantom: PhantomData, + _phantom: PhantomData<(E, S)>, } /// This type is used to describe a storage change when charging from the meter. @@ -289,15 +283,7 @@ where pub fn nested(&self, limit: BalanceOf) -> RawMeter { debug_assert!(matches!(self.contract_state(), ContractState::Alive)); - if limit == BalanceOf::::max_value() { - RawMeter { limit: self.available(), ..Default::default() } - } else { - // If a special limit is specified higher than it is available, - // we want to enforce the lesser limit to the nested meter, to fail in the sub-call. - let limit = self.available().min(limit); - - RawMeter { limit, nested: Nested::OwnLimit, ..Default::default() } - } + RawMeter { limit: self.available().min(limit), ..Default::default() } } /// Absorb a child that was spawned to handle a sub call. @@ -479,13 +465,6 @@ impl> RawMeter { /// [`Self::charge`] does not enforce the storage limit since we want to do this check as late /// as possible to allow later refunds to offset earlier charges. - /// - /// # Note - /// - /// We normally need to call this **once** for every call stack and not for every cross contract - /// call. However, if a dedicated limit is specified for a sub-call, this needs to be called - /// once the sub-call has returned. For this, the [`Self::enforce_subcall_limit`] wrapper is - /// used. pub fn enforce_limit( &mut self, info: Option<&mut ContractInfo>, @@ -504,18 +483,6 @@ impl> RawMeter { } Ok(()) } - - /// This is a wrapper around [`Self::enforce_limit`] to use on the exit from a sub-call to - /// enforce its special limit if needed. - pub fn enforce_subcall_limit( - &mut self, - info: Option<&mut ContractInfo>, - ) -> Result<(), DispatchError> { - match self.nested { - Nested::OwnLimit => self.enforce_limit(info), - Nested::DerivedLimit => Ok(()), - } - } } impl Ext for ReservingExt { diff --git a/substrate/frame/revive/src/tests.rs b/substrate/frame/revive/src/tests.rs index 04a6c4416062..6f08adc28baf 100644 --- a/substrate/frame/revive/src/tests.rs +++ b/substrate/frame/revive/src/tests.rs @@ -2265,8 +2265,8 @@ fn gas_estimation_for_subcalls() { GAS_LIMIT, GAS_LIMIT * 2, GAS_LIMIT / 5, - Weight::from_parts(0, GAS_LIMIT.proof_size()), - Weight::from_parts(GAS_LIMIT.ref_time(), 0), + Weight::from_parts(u64::MAX, GAS_LIMIT.proof_size()), + Weight::from_parts(GAS_LIMIT.ref_time(), u64::MAX), ]; // This call is passed to the sub call in order to create a large `required_weight` From 908c37195f119341831eda6019602fb315cc5827 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexandre=20Bald=C3=A9?= Date: Fri, 10 Jan 2025 15:20:39 +0000 Subject: [PATCH 32/34] Unspecify cause of failure in `tests::skip_transfer_works` --- substrate/frame/revive/src/tests.rs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/substrate/frame/revive/src/tests.rs b/substrate/frame/revive/src/tests.rs index 6f08adc28baf..aa75612973a6 100644 --- a/substrate/frame/revive/src/tests.rs +++ b/substrate/frame/revive/src/tests.rs @@ -4852,7 +4852,7 @@ fn skip_transfer_works() { ); // fails when calling from a contract when gas is specified. - assert_err!( + assert!( Pallet::::bare_eth_transact( GenericTransaction { from: Some(BOB_ADDR), @@ -4863,8 +4863,7 @@ fn skip_transfer_works() { }, Weight::MAX, |_| 0u32 - ), - EthTransactError::Message(format!("insufficient funds for gas * price + value: address {BOB_ADDR:?} have 0 (supplied gas 1)")) + ).is_err(), ); // works when no gas is specified. From 64264010608c8d5edb32fb954ea317fb923ffd57 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexandre=20Bald=C3=A9?= Date: Fri, 10 Jan 2025 15:22:21 +0000 Subject: [PATCH 33/34] Run `cargo fmt` --- substrate/frame/revive/src/tests.rs | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/substrate/frame/revive/src/tests.rs b/substrate/frame/revive/src/tests.rs index aa75612973a6..cf02d17a4d03 100644 --- a/substrate/frame/revive/src/tests.rs +++ b/substrate/frame/revive/src/tests.rs @@ -4852,19 +4852,18 @@ fn skip_transfer_works() { ); // fails when calling from a contract when gas is specified. - assert!( - Pallet::::bare_eth_transact( - GenericTransaction { - from: Some(BOB_ADDR), - to: Some(caller_addr), - input: Some((0u32, &addr).encode().into()), - gas: Some(1u32.into()), - ..Default::default() - }, - Weight::MAX, - |_| 0u32 - ).is_err(), - ); + assert!(Pallet::::bare_eth_transact( + GenericTransaction { + from: Some(BOB_ADDR), + to: Some(caller_addr), + input: Some((0u32, &addr).encode().into()), + gas: Some(1u32.into()), + ..Default::default() + }, + Weight::MAX, + |_| 0u32 + ) + .is_err(),); // works when no gas is specified. assert_ok!(Pallet::::bare_eth_transact( From 1e48276001e1345d22b0e3bc98213feb9fdf88b6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexandre=20Bald=C3=A9?= Date: Fri, 10 Jan 2025 17:32:57 +0000 Subject: [PATCH 34/34] Remove unnecessary `Bounded` trait bound --- substrate/frame/revive/src/storage/meter.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/substrate/frame/revive/src/storage/meter.rs b/substrate/frame/revive/src/storage/meter.rs index d61a6407307f..4febcb0c4066 100644 --- a/substrate/frame/revive/src/storage/meter.rs +++ b/substrate/frame/revive/src/storage/meter.rs @@ -32,7 +32,7 @@ use frame_support::{ DefaultNoBound, RuntimeDebugNoBound, }; use sp_runtime::{ - traits::{Bounded, Saturating, Zero}, + traits::{Saturating, Zero}, DispatchError, FixedPointNumber, FixedU128, }; @@ -271,7 +271,6 @@ impl Default for Contribution { impl RawMeter where T: Config, - BalanceOf: Bounded, E: Ext, S: State + Default + Debug, {