From cb0d8544dc8828c7b5e7f6a5fc20ce8c6ef9bbb4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexandre=20R=2E=20Bald=C3=A9?= <alexandre.balde@parity.io> Date: Wed, 15 Jan 2025 13:14:54 +0000 Subject: [PATCH] Remove 0 as a special case in gas/storage meters (#6890) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Closes #6846 . --------- Signed-off-by: xermicus <cyrill@parity.io> Co-authored-by: command-bot <> Co-authored-by: Alexander Theißen <alex.theissen@me.com> Co-authored-by: xermicus <cyrill@parity.io> --- .../people-westend/src/tests/governance.rs | 2 +- prdoc/pr_6890.prdoc | 19 ++++ .../frame/revive/fixtures/contracts/call.rs | 8 +- .../contracts/call_diverging_out_len.rs | 12 +-- .../fixtures/contracts/call_return_code.rs | 8 +- .../contracts/call_runtime_and_call.rs | 8 +- .../contracts/call_with_flags_and_value.rs | 8 +- .../fixtures/contracts/call_with_limit.rs | 4 +- .../fixtures/contracts/caller_contract.rs | 48 +++++----- .../contracts/chain_extension_temp_storage.rs | 8 +- .../fixtures/contracts/create1_with_value.rs | 12 ++- .../contracts/create_storage_and_call.rs | 8 +- .../create_storage_and_instantiate.rs | 6 +- .../create_transient_storage_and_call.rs | 8 +- .../fixtures/contracts/delegate_call.rs | 10 +- .../contracts/delegate_call_deposit_limit.rs | 10 +- .../contracts/delegate_call_simple.rs | 10 +- .../contracts/destroy_and_transfer.rs | 18 ++-- .../frame/revive/fixtures/contracts/drain.rs | 2 +- .../contracts/instantiate_return_code.rs | 7 +- .../contracts/locking_delegate_dependency.rs | 10 +- .../frame/revive/fixtures/contracts/origin.rs | 6 +- .../fixtures/contracts/read_only_call.rs | 8 +- .../revive/fixtures/contracts/recurse.rs | 8 +- .../fixtures/contracts/return_data_api.rs | 24 +++-- .../fixtures/contracts/self_destruct.rs | 8 +- .../contracts/transfer_return_code.rs | 2 +- substrate/frame/revive/fixtures/src/lib.rs | 2 +- .../rpc/examples/js/pvm/FlipperCaller.polkavm | Bin 4532 -> 4584 bytes .../rpc/examples/js/pvm/PiggyBank.polkavm | Bin 5062 -> 5088 bytes .../frame/revive/src/benchmarking/mod.rs | 14 +-- substrate/frame/revive/src/exec.rs | 60 +++++------- substrate/frame/revive/src/gas.rs | 74 +++++++++++---- substrate/frame/revive/src/primitives.rs | 2 +- substrate/frame/revive/src/storage/meter.rs | 89 ++++++++++-------- substrate/frame/revive/src/tests.rs | 72 +++++++------- substrate/frame/revive/src/wasm/runtime.rs | 6 +- substrate/frame/revive/uapi/src/host.rs | 6 +- .../frame/revive/uapi/src/host/riscv64.rs | 12 +-- 39 files changed, 355 insertions(+), 264 deletions(-) create mode 100644 prdoc/pr_6890.prdoc 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 ea438f80552..3b1779e40b6 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 = <Westend as Chain>::Runtime; type RuntimeCall = <Westend as Chain>::RuntimeCall; diff --git a/prdoc/pr_6890.prdoc b/prdoc/pr_6890.prdoc new file mode 100644 index 00000000000..b22a339035d --- /dev/null +++ b/prdoc/pr_6890.prdoc @@ -0,0 +1,19 @@ +# 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: Alter semantic meaning of 0 in metering limits of EVM contract calls + +doc: + - audience: [ Runtime Dev, Runtime User ] + description: | + A limit of 0, for gas meters and storage meters, no longer has the meaning of unlimited metering. + +crates: + - name: pallet-revive + bump: patch + - name: pallet-revive-fixtures + bump: patch + - name: pallet-revive-uapi + bump: patch + - name: pallet-revive-eth-rpc + bump: patch diff --git a/substrate/frame/revive/fixtures/contracts/call.rs b/substrate/frame/revive/fixtures/contracts/call.rs index ee51548879d..7c4c0882c6b 100644 --- a/substrate/frame/revive/fixtures/contracts/call.rs +++ b/substrate/frame/revive/fixtures/contracts/call.rs @@ -38,10 +38,10 @@ 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. - 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. + &[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 129adde2cec..9a8fe5f5f6c 100644 --- a/substrate/frame/revive/fixtures/contracts/call_diverging_out_len.rs +++ b/substrate/frame/revive/fixtures/contracts/call_diverging_out_len.rs @@ -42,9 +42,9 @@ fn assert_call<const N: usize>(callee_address: &[u8; 20], expected_output: [u8; api::call( uapi::CallFlags::ALLOW_REENTRY, callee_address, - 0u64, - 0u64, - None, + u64::MAX, + u64::MAX, + &[u8::MAX; 32], &[0u8; 32], &[], Some(output_buf_capped), @@ -67,9 +67,9 @@ fn assert_instantiate<const N: usize>(expected_output: [u8; BUF_SIZE]) { api::instantiate( &code_hash, - 0u64, - 0u64, - None, + u64::MAX, + u64::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 2d13b9f7095..19b3ae3fdb2 100644 --- a/substrate/frame/revive/fixtures/contracts/call_return_code.rs +++ b/substrate/frame/revive/fixtures/contracts/call_return_code.rs @@ -42,10 +42,10 @@ 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. - 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. + &[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 8c8aee96284..78b275459f0 100644 --- a/substrate/frame/revive/fixtures/contracts/call_runtime_and_call.rs +++ b/substrate/frame/revive/fixtures/contracts/call_runtime_and_call.rs @@ -42,10 +42,10 @@ 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. - 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. + &[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 330393e706e..155a4b41bd9 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,10 +40,10 @@ 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. - None, // 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 6ab892a6b7a..af5c301a353 100644 --- a/substrate/frame/revive/fixtures/contracts/call_with_limit.rs +++ b/substrate/frame/revive/fixtures/contracts/call_with_limit.rs @@ -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. + &[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 edad43fae25..d042dc2c22a 100644 --- a/substrate/frame/revive/fixtures/contracts/caller_contract.rs +++ b/substrate/frame/revive/fixtures/contracts/caller_contract.rs @@ -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, - 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. - 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. + &[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 - 0u64, // How much proof_size weight to devote for the execution. 0 = 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. + &[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, - 0u64, // How much ref_time weight to devote for the execution. 0 = 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 + &[u8::MAX; 32], // No deposit limit. &value, &input, None, @@ -86,9 +86,9 @@ 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. - 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. + &[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, - 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. - 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. + &[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. - 0u64, // How much proof_size weight to devote for the execution. 0 = 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. + &[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, - 0u64, // How much ref_time weight to devote for the execution. 0 = 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 + &[u8::MAX; 32], // No deposit limit. &value, &input, None, @@ -141,9 +141,9 @@ 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. - 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. + &[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 22d6c5b548d..9b76b9d39ee 100644 --- a/substrate/frame/revive/fixtures/contracts/chain_extension_temp_storage.rs +++ b/substrate/frame/revive/fixtures/contracts/chain_extension_temp_storage.rs @@ -54,10 +54,10 @@ 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. - 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. + &[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 c6adab82886..3554f8f620a 100644 --- a/substrate/frame/revive/fixtures/contracts/create1_with_value.rs +++ b/substrate/frame/revive/fixtures/contracts/create1_with_value.rs @@ -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, 0u64, 0u64, None, &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_storage_and_call.rs b/substrate/frame/revive/fixtures/contracts/create_storage_and_call.rs index a12c36af856..5bb11e27903 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, - 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. - 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 ecc0fc79e6f..f627bc8ba6c 100644 --- a/substrate/frame/revive/fixtures/contracts/create_storage_and_instantiate.rs +++ b/substrate/frame/revive/fixtures/contracts/create_storage_and_instantiate.rs @@ -41,9 +41,9 @@ 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. - Some(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. + 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 cf12fed2756..660db84028d 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,10 +49,10 @@ 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. - 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. + &[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 3cf74acf132..0dedd5f704c 100644 --- a/substrate/frame/revive/fixtures/contracts/delegate_call.rs +++ b/substrate/frame/revive/fixtures/contracts/delegate_call.rs @@ -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, + &[u8::MAX; 32], + &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 0f157f5a18a..0c503aa93c5 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, 0, 0, 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 a8501dad469..b7bdb792c76 100644 --- a/substrate/frame/revive/fixtures/contracts/delegate_call_simple.rs +++ b/substrate/frame/revive/fixtures/contracts/delegate_call_simple.rs @@ -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, 0, 0, None, &input, None).unwrap(); + api::delegate_call( + uapi::CallFlags::empty(), + address, + u64::MAX, + u64::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 8342f4acf95..c2c7da528ba 100644 --- a/substrate/frame/revive/fixtures/contracts/destroy_and_transfer.rs +++ b/substrate/frame/revive/fixtures/contracts/destroy_and_transfer.rs @@ -35,9 +35,9 @@ 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. - 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. + &[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, - 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. - 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. + &[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, - 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. - 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. + &[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 6e3e708a6b3..53fb213143c 100644 --- a/substrate/frame/revive/fixtures/contracts/drain.rs +++ b/substrate/frame/revive/fixtures/contracts/drain.rs @@ -41,7 +41,7 @@ pub extern "C" fn call() { &[0u8; 20], 0, 0, - None, + &[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 9764859c619..f7cbd75be5a 100644 --- a/substrate/frame/revive/fixtures/contracts/instantiate_return_code.rs +++ b/substrate/frame/revive/fixtures/contracts/instantiate_return_code.rs @@ -33,10 +33,9 @@ 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. */ - 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. + &[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 3d7702c6537..6be5d5c72f9 100644 --- a/substrate/frame/revive/fixtures/contracts/locking_delegate_dependency.rs +++ b/substrate/frame/revive/fixtures/contracts/locking_delegate_dependency.rs @@ -52,7 +52,15 @@ 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, + &[u8::MAX; 32], + &[], + None + ).unwrap(); } } diff --git a/substrate/frame/revive/fixtures/contracts/origin.rs b/substrate/frame/revive/fixtures/contracts/origin.rs index 8e9afd8e805..151ca3da77c 100644 --- a/substrate/frame/revive/fixtures/contracts/origin.rs +++ b/substrate/frame/revive/fixtures/contracts/origin.rs @@ -49,9 +49,9 @@ pub extern "C" fn call() { api::call( uapi::CallFlags::ALLOW_REENTRY, &addr, - 0u64, - 0u64, - None, + u64::MAX, + u64::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 ea74d56867f..0a87ecbb9b1 100644 --- a/substrate/frame/revive/fixtures/contracts/read_only_call.rs +++ b/substrate/frame/revive/fixtures/contracts/read_only_call.rs @@ -39,10 +39,10 @@ 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. - 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. + &[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 2e70d67d8c7..ead565c0145 100644 --- a/substrate/frame/revive/fixtures/contracts/recurse.rs +++ b/substrate/frame/revive/fixtures/contracts/recurse.rs @@ -43,10 +43,10 @@ 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. - 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. + &[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 1d483373cff..1407e5323ea 100644 --- a/substrate/frame/revive/fixtures/contracts/return_data_api.rs +++ b/substrate/frame/revive/fixtures/contracts/return_data_api.rs @@ -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], 0, 0, None, &u256_bytes(128), &[], None) - .unwrap(); + api::call( + uapi::CallFlags::empty(), + &[0u8; 20], + u64::MAX, + u64::MAX, + &[u8::MAX; 32], + &u256_bytes(128), + &[], + None + ).unwrap(); assert_return_data_size_of(0); } @@ -111,9 +119,9 @@ pub extern "C" fn call() { let mut instantiate = |exit_flag| { api::instantiate( code_hash, - 0u64, - 0u64, - None, + u64::MAX, + u64::MAX, + &[u8::MAX; 32], &[0; 32], &construct_input(exit_flag), Some(&mut address_buf), @@ -125,9 +133,9 @@ pub extern "C" fn call() { api::call( uapi::CallFlags::empty(), address_buf, - 0u64, - 0u64, - None, + u64::MAX, + u64::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 2f37706634b..053e545deb1 100644 --- a/substrate/frame/revive/fixtures/contracts/self_destruct.rs +++ b/substrate/frame/revive/fixtures/contracts/self_destruct.rs @@ -42,10 +42,10 @@ 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. - 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. + &[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 09d45d0a841..053f97feda4 100644 --- a/substrate/frame/revive/fixtures/contracts/transfer_return_code.rs +++ b/substrate/frame/revive/fixtures/contracts/transfer_return_code.rs @@ -33,7 +33,7 @@ pub extern "C" fn call() { &[0u8; 20], 0, 0, - None, + &[u8::MAX; 32], &u256_bytes(100u64), &[], None, diff --git a/substrate/frame/revive/fixtures/src/lib.rs b/substrate/frame/revive/fixtures/src/lib.rs index 38171edf115..7685253d1ea 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<u8>, sp_core::H256)> { let out_dir: std::path::PathBuf = FIXTURE_DIR.into(); diff --git a/substrate/frame/revive/rpc/examples/js/pvm/FlipperCaller.polkavm b/substrate/frame/revive/rpc/examples/js/pvm/FlipperCaller.polkavm index 585fbb392a314c15a35e7e529106738bde3be02a..38a1098fe3a767aa0af74764bf7247e59f6110b7 100644 GIT binary patch delta 1279 zcmY+CT}&KR6vy}8S>|h5m|e@38e(^sVY0h1Ep^(6SQDhH>}<fyEEMr04aVvWl*o=r zv$IVM)UN4liG<Fr3XKmWk`(ZvO-f(<3VuBBAf`4^YZ{YP`_KmsL9x<Bif6FYHkoth zo_o&y&u`8-bM-gsX|=n<<GFE~UI|TjUw&y|V04l`{7QCUFi($Ndl-+-5CKVhzNHh) z*US#~3-&VG$Gy&ta4Vd~zsSGq`_89T9;y7HGURXe|L)&i^?cQds>!P9i#ocF8;1We z1&cCkvXmJzsF9js>R6z3I3zPIG8<Nf2R-W=6DL{k-gt>J`_;T2Ml#D|l+*Vkt?i@5 ztCMe2THB{bUsz&LrtQSs>Z>1<Mejb}amv!wT&{Dw*CPIkK~zWHsCX1zCzmRcb*J!F z>^N4Waj-Ek8*CVpF;+&yM4{tY!X(1&!Z#7oxDXw^P}Z0q$vizVG>x-;7qDqe!i}q7 zm%$dm=CRCrExkz<#HCvrQwyZwO;;*`%b}E1!eK?Kr8X2va2M8HJk&-?3RATspl2E) zrAUqLag5p+(LI!@H&G+{JT~?Hlw}B}(LzO2Qj+qTMhXHY2((jB6^ch0<`(8zbZ~pP zNPcCW@V!P`hT2uT^Ql<gEeYvmgZ|R0%&J1-+G>WuG#O&wM~{&@uATnvZ;h$hAfMB{ z<Qwk5&;f7<ZUeiU{m4G>4&4TN1n}5}cNf-OJlKWDEWjgxhaxn($1&`}16vaYcm(kH zKX?r6*ky<F5}dbVV8<@|Zb}JRN+_#@429(RJr9wa8uQ6|&ghXDnd3RMH4;t7An*ZM z;M0%yted(znhR%`XV&xQa)xT^DX5StGzTE3c^%rE)q7zQdMqO~dy>f;y%cCMIlY&3 z_}VIF{?eE$7bkoPw9Q%D(r+1D(U|cytG|bQM#by;*YY{&BPgpvYa@i7TXXgLQgiRI zWRdP7S^timbAM{gPi2>t3(L$suuq?b$d_c=-*M<@8E`gXkCg9&P3?l5XWb~k!f5^v zi|@c<WEm~vC*?A<chm}J*myZ_S?<58s*qm#17?kMR$W20M5=xgf4@xns^jQGLaJlZ zo68x->&ZhAk<5ua2gUSs$L5x0Misix!wacG&pGmQ^}-MvDcC|Z8jM7LF=By0F&T{p zf=b5ecg~3MMEon;o)X`g61CImOk7cd#pGT`P@Gv&fuvwmam1~sAOstNMcWpWd>~Q~ zqOG=_D%f_tdq)f;lCz2}Dw%YrGbJjb<_Ja5wArD}54w_fgc|Pd?%#Adj+1H?l|)<# zHbl0v-JFcGEjn|Lc(mvgQeyE`QA$Jp*)x*jr0?culug+wF~T3@BL(q+_*(^`byyU~ MKxn~9Ll-^&0#ACHtN;K2 delta 1201 zcmY+CT}&KR6vy}8ncX|HA26&fC8pA0xJ-5l*6L^^*2Z-+Ei-FLW=5dI57KJu43x+Y zMt8T3p(sh0U<mAOt2UYtvk9ONl9VP&Vx-1sec(Y&{Ys34^a0~TEn<t?QoI9!w8@;z zx##@v|NiElS*)F|4H#|BKHv0cV7c-*`|^?Q?&03R(PQcEo?KvLya5iMBm$5ho(bHC zE+WW%!hO!|<yHPg{u{nFxI5^C#zVE?ec{RQVmKW6G6KpP%38~M%T8Rd!Bto{d)pNn z8F%|0#;uGoL)#O~iHiB7l?qBIoM;I5`&La9C2982_;-xkW#nuTC|nSNjQu1qn`Y*I z8GC~<o4$Dc`D+MRO>a-Hyiz1{>|>!WCTkm+%(FY#BP8PQ0e<qP|8X!!F8bA-uffe; z7u4k}jWi91#$iaR{R%it^gtYzL(<6auKokKoub<vbC2(FyQ*^Il*_dn4MCbJndmDr z8+gAj57V6^&~;8xi_d6G(U_ny1{IFYdSZO-KNA6pF0L=-dAeNkY4R)-HF+LZ4cVul zYhR^%{)TIsyaLyBc@eG+*<-YP8)hBBb$pB_vkdDx95ZCk(t4Q5+4C?6LKa$pK@PO; z5PL}p?F$_WWF4cWYS;eQOWtLW3>S^uTv0efs9##K&|iLXj{5)@MBxuYW`*?g<A<KR zX`=2s6wXsUa*(b%?ocwI$v((Y4B*-<r4u~5Dvyry=w@ko=LVe!H5o%n7lT9gJgqmt zob4m$g30PjH%#>7YQ||-kirLfusPhu3EG$;H-f3XJ*%#53}-|O9b3(fXB@+|HP=ZP z!V^zXjk!t(mbOJY)Ap>ReS8|_9Fd`3C}WG{WT?si^S>tg^TM~GdLT^R+VoF+xNM?N z35Yxx?Z1`FtPf5zgk%RTr%57`*|qSGiIz(q880g6F0=!eY3DccQ>3}$of18K9qp~s zJ!sksRP(CWP1_0jOKqVg;09U(f~=Ex?{um}hclcNEiO^YWwYLw8HSL0fNp<?^q2hr z4v?1ery;vU-Yt)VU&*ENm^^jeLaZ-GuM8+W4)XNsd~LCX>k2Z2w%_Rs7()9MQZ8KX z%X2j<PO4vjZ%9&fP*o*dDB>$Pu3IfuzM?|c>vjDj>1@#|6mWFV!8HZksuw(wTEH~f zc=#He!ci*EZ<CTLS0hzO(lFL>bX1)XCS|%wk2mYoVpP?WxS;NrB<hw|wZ7z*$(gO} z-o(;VDTyD&lSQnb8PGP5^bXdoeDN;xL7a+8qqtr^AEWwC>pZ6PTl%`X^}H|;Yl#mC Wh2pkok^_;#NP;SAo~e&x*7rX_jeaBm diff --git a/substrate/frame/revive/rpc/examples/js/pvm/PiggyBank.polkavm b/substrate/frame/revive/rpc/examples/js/pvm/PiggyBank.polkavm index 3f96fdfc21d8d8fc5bf68a34f0c9f7b055afa2a4..d0082db90e5e398832e4a32a9ec86dce83d16dd5 100644 GIT binary patch delta 1052 zcmY*WZA@EL7{2Gw_S}z_-8R4wr?xkz7m8*QJKg?h8rF;+;@s^O6m*LyGwlzeYnDOL zOo#y~Rt-HbnCv4NHkbfe6h#-~4>NTxL}MhzD1Ic?s0qd;$P$NhVR$Yg!{j{Y&3VrA zydURWtS!}gtcUhXQmNosZhy+v`FK~?$T831Cy#VJ-Rt3B8+hcoLsGZ&taL^y!@F=Z zK8XAAW%ru9lN8BOIiqmpBjpzLpn9*?p{;5Ud&9m*eUrY{^5ycEw^isn^#l4b{rIef z9>d|_YDQncnaX*bshY$2$`XFYUpibBC9$X+wDiE>YLcwLS7p1=EO=ct>SCGQl)H4| zV{pSV+2w6_XH#uGJr8boS#Ee+sfBs619iYVE*f~rlWdyt{XD<mvYYlFui5#n%W-ID zTpJGhDn#60pikhcyMP)X?|Hv(5JyQ=w)85`-$|0i39}zD^F6f2%o%5!bhdG{mN3sF zIiHT9O!|Tl%sccPTFa-#Q6{y3@~I9He?Zxkl}VLQ!u&-X7X{rf;w99ZI*-&$s!f%V zO@4Q}vB|F<X70fnGaE27>jZ-Ep;GM(;|k)sx8M)5*ViU!OCTW-gP43bib1y=MnyO+ z--kNkd-;Q#iYx2GwQhF>{+(n8U$Mz=L;|l?4WBBvqkg!e%%V}4R)gp$e5T$R+IuBQ z-o4(FwxR?@6{;%E%%aAOz@)%9+^kVF4l%9Lv-oF{JaQdglkb2b&4;F7Oe>)|==K`u zbvWTYjbymT*N)zR5#Q&#OP7<xz9wEFo8B`$M6&6`k+g(+1)_>dP)|z2*>vpW&}~=i z>aYFx;df2LX!-r<5d2hr7R|sb+fJbhsMk-SEL_xIz{^YUfWO-F%~F!Ezu--^2FK1p z&VQ@^<5HAZdgFH@AWM&b3FrJ5`Wj__C?2PV@kGsVE;m8PCTOxi!&4?>#$Zlnte&x= zF-9XSM_D+`iZsqgZB7|?uw^ydEjhn`i=Oiq*ec)^278{y8-yzo=lkL`%=n9a6K06h zu~9nAb!In5{+Cj?*DFyL;?t&5pi|8o30ru8@i?cUO$#4L+~{asHo<Vh9;QOXX>p(7 z^xrD%frv=7StiLE2PmSEa6!mK!p#f8RkDD=ZZIqm<F+H)pbW#{xm-f@eX^0VkpY>v Iuuw?)2l-oAiU0rr delta 1068 zcmY*XZ)h839KPS%OYTpa^e)h5|8Qx1b8REIvCCKmDKXsWy<w5$=Cm7gcC32&P_+SF z(oRi2I2R4o_TCEW1{;!MyN*$)!X`ypt#cnNPVkc;21Q{gy7j}lIct2=b=?N{@ZLT5 z{GR7|@7`+Lr8al!=_JQp8g*aa{|tZRaDV^EA$Q;N1N|=#x}Dh&8nK_{j&jGi(_90J zq69jKifGAIbL|nz!a?zXbWEC(-12T&^AOMPo>-&LYj{V!UA`ZEN1Ilf0!pWHNO@r< z1<#>yY$dB)K-uPLlx>+n<>omwq*nV{bRnjT!Ia`ZzLFNI^oNFBaEdnao22g>tnSjE zAAa>3-Nx_S9CzjIo?LEkfPc(Iv>rsX6obhSqXj++G5RTw{ja*y-P7J*ugvpSck=a3 zkABJ1?R?Zz;@5_8fp)mQgY)#3YZNxpvitMGOGp=VF{QM)|49pnk*O8I)XsodwquaB zD?qeqsF~UYs1a=fYGu2Z(X)`ZQ(1eCNf+4TWhmQ4wtfqP_8E|~c8@HACHzs3wS?c? zMBBiMDhwh6hsuHKP_EjSC4mjJ%(uHZ)PDKjdQ<wi=xgd^n(Ykj3_%3+im;QuD`L1v zXT&ZTqD$fz8!s-e?r2|t_ur|%WpddPt_mC-;M?dmX$$mHuRH@&bY2d^JM<TMTkC-v zY2mZ~a+#DafG%NKVtf05WsESC7>aa<2M3Bsmuk8vs0*?O?*1HHqc3{8V2+;iRN-ej z+!%scI^B2*w$h|`KYUF;@h<LKUP=qrZT4aEna;B(gnY&v$W&pFL6>9!a&{H+nb=1s zw%%%w+`j9)W1dd=_P{IjrtchlL&uv=!Xxwv<s`gEe^TDsEM7|sM{edavDMCftTQ_- zx{y-3{-STFL0F`x)rXWDf7hw_b+$lCF|N`@b)lffOQvBgME$BtNQ97&LnL7(9mkMW z)p4F;H@hRmaunhu5{^MixMLg>2ZtH%yT&RL%EO`i^f)}JJ)r3@9G;YV*_2hn!zDA} z;AWDH7chx*5P!JUsf<|<STg&{orpNzm-L5-_5NDoBn~_HZA{|pBUl=}*Jx~2M){G7 zpD+<7#;{TEf40tB%;;Xso8prMnN}jiWXy2=1>+(PHXL)Eac~ij*JW!W!!WR_j^b7) Pdfaq^l8Pstc%1tmWiL>e diff --git a/substrate/frame/revive/src/benchmarking/mod.rs b/substrate/frame/revive/src/benchmarking/mod.rs index e67c39ec089..1796348ff32 100644 --- a/substrate/frame/revive/src/benchmarking/mod.rs +++ b/substrate/frame/revive/src/benchmarking/mod.rs @@ -1648,8 +1648,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 @@ -1688,8 +1688,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 @@ -1715,7 +1715,7 @@ mod benchmarks { let value_bytes = Into::<U256>::into(value).encode(); let value_len = value_bytes.len() as u32; - let deposit: BalanceOf<T> = 0u32.into(); + let deposit: BalanceOf<T> = BalanceOf::<T>::max_value(); let deposit_bytes = Into::<U256>::into(deposit).encode(); let deposit_len = deposit_bytes.len() as u32; @@ -1750,8 +1750,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 diff --git a/substrate/frame/revive/src/exec.rs b/substrate/frame/revive/src/exec.rs index 478e96dc994..c069216d6cc 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,9 +885,9 @@ where args, value, gas_meter, - Weight::zero(), + Weight::max_value(), storage_meter, - BalanceOf::<T>::zero(), + BalanceOf::<T>::max_value(), false, true, )? @@ -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); @@ -1463,7 +1453,7 @@ where FrameArgs::Call { dest: dest.clone(), cached_info, delegated_call: None }, value, gas_limit, - deposit_limit.try_into().map_err(|_| Error::<T>::BalanceConversionFailed)?, + deposit_limit.saturated_into::<BalanceOf<T>>(), // Enable read-only access if requested; cannot disable it if already set. read_only || self.is_read_only(), )? { @@ -1519,7 +1509,7 @@ where }, value, gas_limit, - deposit_limit.try_into().map_err(|_| Error::<T>::BalanceConversionFailed)?, + deposit_limit.saturated_into::<BalanceOf<T>>(), self.is_read_only(), )?; self.run(executable.expect(FRAME_ALWAYS_EXISTS_ON_INSTANTIATE), input_data) @@ -1549,7 +1539,7 @@ where }, value.try_into().map_err(|_| Error::<T>::BalanceConversionFailed)?, gas_limit, - deposit_limit.try_into().map_err(|_| Error::<T>::BalanceConversionFailed)?, + deposit_limit.saturated_into::<BalanceOf<T>>(), self.is_read_only(), )?; let address = T::AddressMapper::to_address(&self.top_frame().account_id); @@ -3098,8 +3088,8 @@ mod tests { let (address, output) = ctx .ext .instantiate( - Weight::zero(), - U256::zero(), + Weight::MAX, + U256::MAX, dummy_ch, <Test as Config>::Currency::minimum_balance().into(), vec![], @@ -3802,8 +3792,8 @@ mod tests { let succ_fail_code = MockLoader::insert(Constructor, move |ctx, _| { ctx.ext .instantiate( - Weight::zero(), - U256::zero(), + Weight::MAX, + U256::MAX, fail_code, ctx.ext.minimum_balance() * 100, vec![], @@ -3819,8 +3809,8 @@ mod tests { let addr = ctx .ext .instantiate( - Weight::zero(), - U256::zero(), + Weight::MAX, + U256::MAX, success_code, ctx.ext.minimum_balance() * 100, vec![], @@ -4597,7 +4587,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::MAX, ok_ch, value, vec![], None) .unwrap(); assert_eq!( ctx.ext.last_frame_output(), @@ -4606,15 +4596,7 @@ mod tests { // Balance transfers should reset the output ctx.ext - .call( - Weight::zero(), - U256::zero(), - &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 +4809,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::MAX, dummy_ch, value, vec![], None) .unwrap(); exec_success() @@ -4944,7 +4926,7 @@ mod tests { move |ctx, _| { let value = <Test as Config>::Currency::minimum_balance().into(); ctx.ext - .instantiate(Weight::zero(), U256::zero(), dummy_ch, value, vec![], None) + .instantiate(Weight::MAX, U256::MAX, dummy_ch, value, vec![], None) .unwrap(); exec_success() @@ -4989,7 +4971,7 @@ mod tests { move |ctx, _| { let value = <Test as Config>::Currency::minimum_balance().into(); ctx.ext - .instantiate(Weight::zero(), U256::zero(), 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/gas.rs b/substrate/frame/revive/src/gas.rs index 5c30a0a5100..e8338db1219 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}; @@ -168,25 +168,19 @@ impl<T: Config> GasMeter<T> { } } - /// Create a new gas meter by removing gas from the current meter. + /// Create a new gas meter by removing *all* the gas from the current meter. /// - /// # Note - /// - /// Passing `0` as amount is interpreted as "all remaining gas". + /// 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) + } + + /// 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); + let amount = amount.min(self.gas_left); self.gas_left -= amount; GasMeter::new(amount) } @@ -392,6 +386,50 @@ mod tests { assert!(gas_meter.charge(SimpleToken(1)).is_err()); } + /// 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::<Test>::new(test_weight); + let gas_for_nested_call = gas_meter.nested(0.into()); + + assert_eq!(gas_meter.gas_left(), 50000.into()); + assert_eq!(gas_for_nested_call.gas_left(), 0.into()) + } + + #[test] + fn nested_some_gas_requested() { + let test_weight = 50000.into(); + let mut gas_meter = GasMeter::<Test>::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::<Test>::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(), 50_000.into()) + } + + #[test] + fn nested_excess_gas_requested() { + let test_weight = Weight::from_parts(50000, 50000); + let mut gas_meter = GasMeter::<Test>::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(), 50_000.into()) + } + // Make sure that the gas meter does not charge in case of overcharge #[test] fn overcharge_does_not_charge() { diff --git a/substrate/frame/revive/src/primitives.rs b/substrate/frame/revive/src/primitives.rs index a7127f812b4..452d2c8a306 100644 --- a/substrate/frame/revive/src/primitives.rs +++ b/substrate/frame/revive/src/primitives.rs @@ -72,7 +72,7 @@ pub struct ContractResult<R, Balance, EventRecord> { /// /// # 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. diff --git a/substrate/frame/revive/src/storage/meter.rs b/substrate/frame/revive/src/storage/meter.rs index 6eddf048be9..4febcb0c406 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<T: Config, E, S: State + Default + Debug> { /// We only have one charge per contract hence the size of this vector is /// limited by the maximum call depth. charges: Vec<Charge<T>>, - /// 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>, + _phantom: PhantomData<(E, S)>, } /// This type is used to describe a storage change when charging from the meter. @@ -281,21 +275,14 @@ 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, limit: BalanceOf<T>) -> RawMeter<T, E, Nested> { debug_assert!(matches!(self.contract_state(), ContractState::Alive)); - // 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() } - } + + RawMeter { limit: self.available().min(limit), ..Default::default() } } /// Absorb a child that was spawned to handle a sub call. @@ -477,13 +464,6 @@ impl<T: Config, E: Ext<T>> RawMeter<T, E, Nested> { /// [`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<T>>, @@ -502,18 +482,6 @@ impl<T: Config, E: Ext<T>> RawMeter<T, E, Nested> { } 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<T>>, - ) -> Result<(), DispatchError> { - match self.nested { - Nested::OwnLimit => self.enforce_limit(info), - Nested::DerivedLimit => Ok(()), - } - } } impl<T: Config> Ext<T> for ReservingExt { @@ -724,6 +692,49 @@ mod tests { ) } + /// 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(); + + let meter = TestMeter::new(&Origin::from_account_id(ALICE), 1_000, 0).unwrap(); + assert_eq!(meter.available(), 1_000); + let nested0 = meter.nested(BalanceOf::<Test>::zero()); + assert_eq!(nested0.available(), 0); + } + + #[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(); @@ -879,7 +890,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::<Test>::zero()); + let mut nested0 = meter.nested(BalanceOf::<Test>::max_value()); nested0.charge(&Diff { bytes_added: 5, bytes_removed: 1, @@ -895,7 +906,7 @@ mod tests { items_deposit: 20, immutable_data_len: 0, }); - let mut nested1 = nested0.nested(BalanceOf::<Test>::zero()); + let mut nested1 = nested0.nested(BalanceOf::<Test>::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/tests.rs b/substrate/frame/revive/src/tests.rs index 664578bf767..cf02d17a4d0 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()); }); } @@ -2261,12 +2261,12 @@ 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, - 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` @@ -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::MAX).encode()) .build(), <Error<Test>>::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::MAX).encode()) .build(), <Error<Test>>::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::MAX.to_little_endian()).encode()) .build(), <Error<Test>>::StorageDepositLimitExhausted, ); @@ -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(), - <Error<Test>>::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::MAX.to_little_endian()).encode()) + .build_and_unwrap_result(); + assert_return_code!(ret, RuntimeReturnCode::OutOfResources); // The charges made on instantiation should be rolled back. assert_eq!(<Test as Config>::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(), - <Error<Test>>::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!(<Test as Config>::Currency::free_balance(&BOB), 1_000_000); @@ -4856,20 +4852,18 @@ fn skip_transfer_works() { ); // fails when calling from a contract when gas is specified. - assert_err!( - Pallet::<Test>::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 - ), - EthTransactError::Message(format!("insufficient funds for gas * price + value: address {BOB_ADDR:?} have 0 (supplied gas 1)")) - ); + assert!(Pallet::<Test>::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::<Test>::bare_eth_transact( diff --git a/substrate/frame/revive/src/wasm/runtime.rs b/substrate/frame/revive/src/wasm/runtime.rs index 52f79f2eb55..8529c7d9e73 100644 --- a/substrate/frame/revive/src/wasm/runtime.rs +++ b/substrate/frame/revive/src/wasm/runtime.rs @@ -1004,8 +1004,7 @@ impl<'a, E: Ext, M: ?Sized + Memory<E::T>> 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::zero() } 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::<E::T>::InputForwarded)?; @@ -1091,8 +1090,7 @@ impl<'a, E: Ext, M: ?Sized + Memory<E::T>> Runtime<'a, E, M> { salt_ptr: u32, ) -> Result<ReturnErrorCode, TrapReason> { self.charge_gas(RuntimeCosts::Instantiate { input_data_len })?; - let deposit_limit: U256 = - if deposit_ptr == SENTINEL { U256::zero() } 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 d90c0f45205..ba0a63b15c3 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 c83be942a97..8c40bc9f48e 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 { -- GitLab