diff --git a/bin/node/runtime/src/lib.rs b/bin/node/runtime/src/lib.rs index 766bc9515b8ab..60d9549135b4f 100644 --- a/bin/node/runtime/src/lib.rs +++ b/bin/node/runtime/src/lib.rs @@ -1880,6 +1880,11 @@ type Migrations = ( pallet_contracts::Migration, ); +type EventRecord = frame_system::EventRecord< + ::RuntimeEvent, + ::Hash, +>; + /// MMR helper types. mod mmr { use super::Runtime; @@ -2141,7 +2146,7 @@ impl_runtime_apis! { } } - impl pallet_contracts::ContractsApi for Runtime + impl pallet_contracts::ContractsApi for Runtime { fn call( origin: AccountId, @@ -2150,7 +2155,7 @@ impl_runtime_apis! { gas_limit: Option, storage_deposit_limit: Option, input_data: Vec, - ) -> pallet_contracts_primitives::ContractExecResult { + ) -> pallet_contracts_primitives::ContractExecResult { let gas_limit = gas_limit.unwrap_or(RuntimeBlockWeights::get().max_block); Contracts::bare_call( origin, @@ -2159,7 +2164,8 @@ impl_runtime_apis! { gas_limit, storage_deposit_limit, input_data, - true, + pallet_contracts::DebugInfo::UnsafeDebug, + pallet_contracts::CollectEvents::UnsafeCollect, pallet_contracts::Determinism::Enforced, ) } @@ -2172,7 +2178,7 @@ impl_runtime_apis! { code: pallet_contracts_primitives::Code, data: Vec, salt: Vec, - ) -> pallet_contracts_primitives::ContractInstantiateResult + ) -> pallet_contracts_primitives::ContractInstantiateResult { let gas_limit = gas_limit.unwrap_or(RuntimeBlockWeights::get().max_block); Contracts::bare_instantiate( @@ -2183,7 +2189,8 @@ impl_runtime_apis! { code, data, salt, - true + pallet_contracts::DebugInfo::UnsafeDebug, + pallet_contracts::CollectEvents::UnsafeCollect, ) } diff --git a/frame/contracts/primitives/src/lib.rs b/frame/contracts/primitives/src/lib.rs index e73ceb031e184..cc21e29e67b3d 100644 --- a/frame/contracts/primitives/src/lib.rs +++ b/frame/contracts/primitives/src/lib.rs @@ -29,11 +29,18 @@ use sp_runtime::{ use sp_std::prelude::*; use sp_weights::Weight; -/// Result type of a `bare_call` or `bare_instantiate` call. +/// Result type of a `bare_call` or `bare_instantiate` call as well as `ContractsApi::call` and +/// `ContractsApi::instantiate`. /// /// It contains the execution result together with some auxiliary information. +/// +/// #Note +/// +/// It has been extended to include `events` at the end of the struct while not bumping the +/// `ContractsApi` version. Therefore when SCALE decoding a `ContractResult` its trailing data +/// should be ignored to avoid any potential compatibility issues. #[derive(Eq, PartialEq, Encode, Decode, RuntimeDebug, TypeInfo)] -pub struct ContractResult { +pub struct ContractResult { /// How much weight was consumed during execution. pub gas_consumed: Weight, /// How much weight is required as gas limit in order to execute this call. @@ -71,15 +78,18 @@ pub struct ContractResult { pub debug_message: Vec, /// The execution result of the wasm code. pub result: R, + /// The events that were emitted during execution. It is an option as event collection is + /// optional. + pub events: Option>, } -/// Result type of a `bare_call` call. -pub type ContractExecResult = - ContractResult, Balance>; +/// Result type of a `bare_call` call as well as `ContractsApi::call`. +pub type ContractExecResult = + ContractResult, Balance, EventRecord>; -/// Result type of a `bare_instantiate` call. -pub type ContractInstantiateResult = - ContractResult, DispatchError>, Balance>; +/// Result type of a `bare_instantiate` call as well as `ContractsApi::instantiate`. +pub type ContractInstantiateResult = + ContractResult, DispatchError>, Balance, EventRecord>; /// Result type of a `bare_code_upload` call. pub type CodeUploadResult = diff --git a/frame/contracts/src/benchmarking/mod.rs b/frame/contracts/src/benchmarking/mod.rs index 2c60c1501df7a..fa9417a59042d 100644 --- a/frame/contracts/src/benchmarking/mod.rs +++ b/frame/contracts/src/benchmarking/mod.rs @@ -951,7 +951,8 @@ benchmarks! { Weight::MAX, None, vec![], - true, + DebugInfo::UnsafeDebug, + CollectEvents::Skip, Determinism::Enforced, ) .result?; @@ -1000,7 +1001,8 @@ benchmarks! { Weight::MAX, None, vec![], - true, + DebugInfo::UnsafeDebug, + CollectEvents::Skip, Determinism::Enforced, ) .result?; @@ -3192,7 +3194,8 @@ benchmarks! { Weight::MAX, None, data, - false, + DebugInfo::Skip, + CollectEvents::Skip, Determinism::Enforced, ) .result?; @@ -3241,7 +3244,8 @@ benchmarks! { Weight::MAX, None, data, - false, + DebugInfo::Skip, + CollectEvents::Skip, Determinism::Enforced, ) .result?; diff --git a/frame/contracts/src/lib.rs b/frame/contracts/src/lib.rs index 97fa284577d47..e0e8e2d15b06d 100644 --- a/frame/contracts/src/lib.rs +++ b/frame/contracts/src/lib.rs @@ -117,7 +117,7 @@ use frame_support::{ weights::Weight, BoundedVec, RuntimeDebugNoBound, WeakBoundedVec, }; -use frame_system::{ensure_signed, pallet_prelude::OriginFor, Pallet as System}; +use frame_system::{ensure_signed, pallet_prelude::OriginFor, EventRecord, Pallet as System}; use pallet_contracts_primitives::{ Code, CodeUploadResult, CodeUploadReturnValue, ContractAccessError, ContractExecResult, ContractInstantiateResult, ExecReturnValue, GetStorageResult, InstantiateReturnValue, @@ -148,6 +148,8 @@ type CodeVec = BoundedVec::MaxCodeLen>; type RelaxedCodeVec = WeakBoundedVec::MaxCodeLen>; type AccountIdLookupOf = <::Lookup as StaticLookup>::Source; type DebugBufferVec = BoundedVec::MaxDebugBufferLen>; +type EventRecordOf = + EventRecord<::RuntimeEvent, ::Hash>; /// The old weight type. /// @@ -971,6 +973,35 @@ struct InstantiateInput { salt: Vec, } +/// Determines whether events should be collected during execution. +#[derive(PartialEq)] +pub enum CollectEvents { + /// Collect events. + /// + /// # Note + /// + /// Events should only be collected when called off-chain, as this would otherwise + /// collect all the Events emitted in the block so far and put them into the PoV. + /// + /// **Never** use this mode for on-chain execution. + UnsafeCollect, + /// Skip event collection. + Skip, +} + +/// Determines whether debug messages will be collected. +#[derive(PartialEq)] +pub enum DebugInfo { + /// Collect debug messages. + /// # Note + /// + /// This should only ever be set to `UnsafeDebug` when executing as an RPC because + /// it adds allocations and could be abused to drive the runtime into an OOM panic. + UnsafeDebug, + /// Skip collection of debug messages. + Skip, +} + /// Return type of private helper functions. struct InternalOutput { /// The gas meter that was used to execute the call. @@ -1187,11 +1218,11 @@ impl Pallet { /// /// # Note /// - /// `debug` should only ever be set to `true` when executing as an RPC because - /// it adds allocations and could be abused to drive the runtime into an OOM panic. - /// If set to `true` it returns additional human readable debugging information. + /// If `debug` is set to `DebugInfo::UnsafeDebug` it returns additional human readable debugging + /// information. /// - /// It returns the execution result and the amount of used weight. + /// If `collect_events` is set to `CollectEvents::UnsafeCollect` it collects all the Events + /// emitted in the block so far and the ones emitted during the execution of this contract. pub fn bare_call( origin: T::AccountId, dest: T::AccountId, @@ -1199,10 +1230,15 @@ impl Pallet { gas_limit: Weight, storage_deposit_limit: Option>, data: Vec, - debug: bool, + debug: DebugInfo, + collect_events: CollectEvents, determinism: Determinism, - ) -> ContractExecResult> { - let mut debug_message = if debug { Some(DebugBufferVec::::default()) } else { None }; + ) -> ContractExecResult, EventRecordOf> { + let mut debug_message = if matches!(debug, DebugInfo::UnsafeDebug) { + Some(DebugBufferVec::::default()) + } else { + None + }; let origin = Origin::from_account_id(origin); let common = CommonInput { origin, @@ -1213,12 +1249,19 @@ impl Pallet { debug_message: debug_message.as_mut(), }; let output = CallInput:: { dest, determinism }.run_guarded(common); + let events = if matches!(collect_events, CollectEvents::UnsafeCollect) { + Some(System::::read_events_no_consensus().map(|e| *e).collect()) + } else { + None + }; + ContractExecResult { result: output.result.map_err(|r| r.error), gas_consumed: output.gas_meter.gas_consumed(), gas_required: output.gas_meter.gas_required(), storage_deposit: output.storage_deposit, debug_message: debug_message.unwrap_or_default().to_vec(), + events, } } @@ -1231,9 +1274,11 @@ impl Pallet { /// /// # Note /// - /// `debug` should only ever be set to `true` when executing as an RPC because - /// it adds allocations and could be abused to drive the runtime into an OOM panic. - /// If set to `true` it returns additional human readable debugging information. + /// If `debug` is set to `DebugInfo::UnsafeDebug` it returns additional human readable debugging + /// information. + /// + /// If `collect_events` is set to `CollectEvents::UnsafeCollect` it collects all the Events + /// emitted in the block so far. pub fn bare_instantiate( origin: T::AccountId, value: BalanceOf, @@ -1242,9 +1287,14 @@ impl Pallet { code: Code>, data: Vec, salt: Vec, - debug: bool, - ) -> ContractInstantiateResult> { - let mut debug_message = if debug { Some(DebugBufferVec::::default()) } else { None }; + debug: DebugInfo, + collect_events: CollectEvents, + ) -> ContractInstantiateResult, EventRecordOf> { + let mut debug_message = if debug == DebugInfo::UnsafeDebug { + Some(DebugBufferVec::::default()) + } else { + None + }; let common = CommonInput { origin: Origin::from_account_id(origin), value, @@ -1254,6 +1304,12 @@ impl Pallet { debug_message: debug_message.as_mut(), }; let output = InstantiateInput:: { code, salt }.run_guarded(common); + // collect events if CollectEvents is UnsafeCollect + let events = if collect_events == CollectEvents::UnsafeCollect { + Some(System::::read_events_no_consensus().map(|e| *e).collect()) + } else { + None + }; ContractInstantiateResult { result: output .result @@ -1263,6 +1319,7 @@ impl Pallet { gas_required: output.gas_meter.gas_required(), storage_deposit: output.storage_deposit, debug_message: debug_message.unwrap_or_default().to_vec(), + events, } } @@ -1370,11 +1427,12 @@ impl Pallet { sp_api::decl_runtime_apis! { /// The API used to dry-run contract interactions. #[api_version(2)] - pub trait ContractsApi where + pub trait ContractsApi where AccountId: Codec, Balance: Codec, BlockNumber: Codec, Hash: Codec, + EventRecord: Codec, { /// Perform a call from a specified account to a given contract. /// @@ -1386,7 +1444,7 @@ sp_api::decl_runtime_apis! { gas_limit: Option, storage_deposit_limit: Option, input_data: Vec, - ) -> ContractExecResult; + ) -> ContractExecResult; /// Instantiate a new contract. /// @@ -1399,8 +1457,7 @@ sp_api::decl_runtime_apis! { code: Code, data: Vec, salt: Vec, - ) -> ContractInstantiateResult; - + ) -> ContractInstantiateResult; /// Upload new code without instantiating a contract from it. /// diff --git a/frame/contracts/src/tests.rs b/frame/contracts/src/tests.rs index a07176e9f67b9..c32999d0ade3a 100644 --- a/frame/contracts/src/tests.rs +++ b/frame/contracts/src/tests.rs @@ -27,8 +27,8 @@ use crate::{ tests::test_utils::{get_contract, get_contract_checked}, wasm::{Determinism, PrefabWasmModule, ReturnCode as RuntimeReturnCode}, weights::WeightInfo, - BalanceOf, Code, CodeStorage, Config, ContractInfo, ContractInfoOf, DefaultAddressGenerator, - DeletionQueueCounter, Error, Origin, Pallet, Schedule, + BalanceOf, Code, CodeStorage, CollectEvents, Config, ContractInfo, ContractInfoOf, DebugInfo, + DefaultAddressGenerator, DeletionQueueCounter, Error, Origin, Pallet, Schedule, }; use assert_matches::assert_matches; use codec::Encode; @@ -574,7 +574,8 @@ fn instantiate_and_call_and_deposit_event() { Code::Existing(code_hash), vec![], vec![], - false, + DebugInfo::Skip, + CollectEvents::Skip, ) .result .unwrap() @@ -680,7 +681,8 @@ fn deposit_event_max_value_limit() { Code::Upload(wasm), vec![], vec![], - false, + DebugInfo::Skip, + CollectEvents::Skip, ) .result .unwrap() @@ -726,7 +728,8 @@ fn run_out_of_gas() { Code::Upload(wasm), vec![], vec![], - false, + DebugInfo::Skip, + CollectEvents::Skip, ) .result .unwrap() @@ -768,7 +771,8 @@ fn instantiate_unique_trie_id() { Code::Existing(code_hash), vec![], vec![], - false, + DebugInfo::Skip, + CollectEvents::Skip, ) .result .unwrap() @@ -830,7 +834,8 @@ fn storage_max_value_limit() { Code::Upload(wasm), vec![], vec![], - false, + DebugInfo::Skip, + CollectEvents::Skip, ) .result .unwrap() @@ -880,7 +885,8 @@ fn deploy_and_call_other_contract() { Code::Upload(caller_wasm), vec![], vec![], - false, + DebugInfo::Skip, + CollectEvents::Skip, ) .result .unwrap() @@ -1029,7 +1035,8 @@ fn delegate_call() { Code::Upload(caller_wasm), vec![], vec![], - false, + DebugInfo::Skip, + CollectEvents::Skip, ) .result .unwrap() @@ -1068,7 +1075,8 @@ fn transfer_allow_death_cannot_kill_account() { Code::Upload(wasm), vec![], vec![], - false, + DebugInfo::Skip, + CollectEvents::Skip, ) .result .unwrap() @@ -1108,7 +1116,8 @@ fn cannot_self_destruct_through_draning() { Code::Upload(wasm), vec![], vec![], - false, + DebugInfo::Skip, + CollectEvents::Skip, ) .result .unwrap() @@ -1152,7 +1161,8 @@ fn cannot_self_destruct_through_storage_refund_after_price_change() { Code::Upload(wasm), vec![], vec![], - false, + DebugInfo::Skip, + CollectEvents::Skip, ) .result .unwrap() @@ -1210,7 +1220,8 @@ fn cannot_self_destruct_while_live() { Code::Upload(wasm), vec![], vec![], - false, + DebugInfo::Skip, + CollectEvents::Skip, ) .result .unwrap() @@ -1254,7 +1265,8 @@ fn self_destruct_works() { Code::Upload(wasm), vec![], vec![], - false, + DebugInfo::Skip, + CollectEvents::Skip, ) .result .unwrap() @@ -1361,7 +1373,8 @@ fn destroy_contract_and_transfer_funds() { Code::Upload(caller_wasm), callee_code_hash.as_ref().to_vec(), vec![], - false, + DebugInfo::Skip, + CollectEvents::Skip, ) .result .unwrap() @@ -1425,7 +1438,8 @@ fn crypto_hashes() { Code::Upload(wasm), vec![], vec![], - false, + DebugInfo::Skip, + CollectEvents::Skip, ) .result .unwrap() @@ -1458,7 +1472,8 @@ fn crypto_hashes() { GAS_LIMIT, None, params, - false, + DebugInfo::Skip, + CollectEvents::Skip, Determinism::Enforced, ) .result @@ -1485,7 +1500,8 @@ fn transfer_return_code() { Code::Upload(wasm), vec![], vec![], - false, + DebugInfo::Skip, + CollectEvents::Skip, ) .result .unwrap() @@ -1500,7 +1516,8 @@ fn transfer_return_code() { GAS_LIMIT, None, vec![], - false, + DebugInfo::Skip, + CollectEvents::Skip, Determinism::Enforced, ) .result @@ -1526,7 +1543,8 @@ fn call_return_code() { Code::Upload(caller_code), vec![0], vec![], - false, + DebugInfo::Skip, + CollectEvents::Skip, ) .result .unwrap() @@ -1541,7 +1559,8 @@ fn call_return_code() { GAS_LIMIT, None, AsRef::<[u8]>::as_ref(&DJANGO).to_vec(), - false, + DebugInfo::Skip, + CollectEvents::Skip, Determinism::Enforced, ) .result @@ -1556,7 +1575,8 @@ fn call_return_code() { Code::Upload(callee_code), vec![0], vec![], - false, + DebugInfo::Skip, + CollectEvents::Skip, ) .result .unwrap() @@ -1575,7 +1595,8 @@ fn call_return_code() { .chain(&0u32.to_le_bytes()) .cloned() .collect(), - false, + DebugInfo::Skip, + CollectEvents::Skip, Determinism::Enforced, ) .result @@ -1595,7 +1616,8 @@ fn call_return_code() { .chain(&1u32.to_le_bytes()) .cloned() .collect(), - false, + DebugInfo::Skip, + CollectEvents::Skip, Determinism::Enforced, ) .result @@ -1614,7 +1636,8 @@ fn call_return_code() { .chain(&2u32.to_le_bytes()) .cloned() .collect(), - false, + DebugInfo::Skip, + CollectEvents::Skip, Determinism::Enforced, ) .result @@ -1651,7 +1674,8 @@ fn instantiate_return_code() { Code::Upload(caller_code), vec![], vec![], - false, + DebugInfo::Skip, + CollectEvents::Skip, ) .result .unwrap() @@ -1666,7 +1690,8 @@ fn instantiate_return_code() { GAS_LIMIT, None, callee_hash.clone(), - false, + DebugInfo::Skip, + CollectEvents::Skip, Determinism::Enforced, ) .result @@ -1682,7 +1707,8 @@ fn instantiate_return_code() { GAS_LIMIT, None, vec![0; 33], - false, + DebugInfo::Skip, + CollectEvents::Skip, Determinism::Enforced, ) .result @@ -1697,7 +1723,8 @@ fn instantiate_return_code() { GAS_LIMIT, None, callee_hash.iter().chain(&1u32.to_le_bytes()).cloned().collect(), - false, + DebugInfo::Skip, + CollectEvents::Skip, Determinism::Enforced, ) .result @@ -1712,7 +1739,8 @@ fn instantiate_return_code() { GAS_LIMIT, None, callee_hash.iter().chain(&2u32.to_le_bytes()).cloned().collect(), - false, + DebugInfo::Skip, + CollectEvents::Skip, Determinism::Enforced, ) .result @@ -1757,7 +1785,8 @@ fn disabled_chain_extension_errors_on_call() { Code::Upload(code), vec![], vec![], - false, + DebugInfo::Skip, + CollectEvents::Skip, ) .result .unwrap() @@ -1784,7 +1813,8 @@ fn chain_extension_works() { Code::Upload(code), vec![], vec![], - false, + DebugInfo::Skip, + CollectEvents::Skip, ) .result .unwrap() @@ -1799,7 +1829,8 @@ fn chain_extension_works() { GAS_LIMIT, None, input.clone(), - false, + DebugInfo::Skip, + CollectEvents::Skip, Determinism::Enforced, ); assert_eq!(TestExtension::last_seen_buffer(), input); @@ -1813,7 +1844,8 @@ fn chain_extension_works() { GAS_LIMIT, None, ExtensionInput { extension_id: 0, func_id: 1, extra: &[] }.into(), - false, + DebugInfo::Skip, + CollectEvents::Skip, Determinism::Enforced, ) .result @@ -1829,7 +1861,8 @@ fn chain_extension_works() { GAS_LIMIT, None, ExtensionInput { extension_id: 0, func_id: 2, extra: &[0] }.into(), - false, + DebugInfo::Skip, + CollectEvents::Skip, Determinism::Enforced, ); assert_ok!(result.result); @@ -1841,7 +1874,8 @@ fn chain_extension_works() { GAS_LIMIT, None, ExtensionInput { extension_id: 0, func_id: 2, extra: &[42] }.into(), - false, + DebugInfo::Skip, + CollectEvents::Skip, Determinism::Enforced, ); assert_ok!(result.result); @@ -1853,7 +1887,8 @@ fn chain_extension_works() { GAS_LIMIT, None, ExtensionInput { extension_id: 0, func_id: 2, extra: &[95] }.into(), - false, + DebugInfo::Skip, + CollectEvents::Skip, Determinism::Enforced, ); assert_ok!(result.result); @@ -1867,7 +1902,8 @@ fn chain_extension_works() { GAS_LIMIT, None, ExtensionInput { extension_id: 0, func_id: 3, extra: &[] }.into(), - false, + DebugInfo::Skip, + CollectEvents::Skip, Determinism::Enforced, ) .result @@ -1885,7 +1921,8 @@ fn chain_extension_works() { GAS_LIMIT, None, ExtensionInput { extension_id: 1, func_id: 0, extra: &[] }.into(), - false, + DebugInfo::Skip, + CollectEvents::Skip, Determinism::Enforced, ) .result @@ -1923,7 +1960,8 @@ fn chain_extension_temp_storage_works() { Code::Upload(code), vec![], vec![], - false, + DebugInfo::Skip, + CollectEvents::Skip, ) .result .unwrap() @@ -1946,8 +1984,9 @@ fn chain_extension_temp_storage_works() { GAS_LIMIT, None, input.clone(), - false, - Determinism::Enforced + DebugInfo::Skip, + CollectEvents::Skip, + Determinism::Enforced, ) .result ); @@ -1969,7 +2008,8 @@ fn lazy_removal_works() { Code::Upload(code), vec![], vec![], - false, + DebugInfo::Skip, + CollectEvents::Skip, ) .result .unwrap() @@ -2022,7 +2062,8 @@ fn lazy_batch_removal_works() { Code::Upload(code.clone()), vec![], vec![i], - false, + DebugInfo::Skip, + CollectEvents::Skip, ) .result .unwrap() @@ -2087,7 +2128,8 @@ fn lazy_removal_partial_remove_works() { Code::Upload(code), vec![], vec![], - false, + DebugInfo::Skip, + CollectEvents::Skip, ) .result .unwrap() @@ -2168,7 +2210,8 @@ fn lazy_removal_does_no_run_on_low_remaining_weight() { Code::Upload(code), vec![], vec![], - false, + DebugInfo::Skip, + CollectEvents::Skip, ) .result .unwrap() @@ -2239,7 +2282,8 @@ fn lazy_removal_does_not_use_all_weight() { Code::Upload(code), vec![], vec![], - false, + DebugInfo::Skip, + CollectEvents::Skip, ) .result .unwrap() @@ -2329,7 +2373,8 @@ fn deletion_queue_ring_buffer_overflow() { Code::Upload(code.clone()), vec![], vec![i], - false, + DebugInfo::Skip, + CollectEvents::Skip, ) .result .unwrap() @@ -2386,7 +2431,8 @@ fn refcounter() { Code::Upload(wasm.clone()), vec![], vec![0], - false, + DebugInfo::Skip, + CollectEvents::Skip, ) .result .unwrap() @@ -2399,7 +2445,8 @@ fn refcounter() { Code::Upload(wasm.clone()), vec![], vec![1], - false, + DebugInfo::Skip, + CollectEvents::Skip, ) .result .unwrap() @@ -2415,7 +2462,8 @@ fn refcounter() { Code::Existing(code_hash), vec![], vec![2], - false, + DebugInfo::Skip, + CollectEvents::Skip, ) .result .unwrap() @@ -2481,7 +2529,8 @@ fn reinstrument_does_charge() { Code::Upload(wasm), zero.clone(), vec![], - false, + DebugInfo::Skip, + CollectEvents::Skip, ) .result .unwrap() @@ -2496,7 +2545,8 @@ fn reinstrument_does_charge() { GAS_LIMIT, None, zero.clone(), - false, + DebugInfo::Skip, + CollectEvents::Skip, Determinism::Enforced, ); assert!(!result0.result.unwrap().did_revert()); @@ -2508,7 +2558,8 @@ fn reinstrument_does_charge() { GAS_LIMIT, None, zero.clone(), - false, + DebugInfo::Skip, + CollectEvents::Skip, Determinism::Enforced, ); assert!(!result1.result.unwrap().did_revert()); @@ -2530,7 +2581,8 @@ fn reinstrument_does_charge() { GAS_LIMIT, None, zero.clone(), - false, + DebugInfo::Skip, + CollectEvents::Skip, Determinism::Enforced, ); assert!(!result2.result.unwrap().did_revert()); @@ -2557,7 +2609,8 @@ fn debug_message_works() { Code::Upload(wasm), vec![], vec![], - false, + DebugInfo::Skip, + CollectEvents::Skip, ) .result .unwrap() @@ -2569,7 +2622,8 @@ fn debug_message_works() { GAS_LIMIT, None, vec![], - true, + DebugInfo::UnsafeDebug, + CollectEvents::Skip, Determinism::Enforced, ); @@ -2592,7 +2646,8 @@ fn debug_message_logging_disabled() { Code::Upload(wasm), vec![], vec![], - false, + DebugInfo::Skip, + CollectEvents::Skip, ) .result .unwrap() @@ -2605,7 +2660,8 @@ fn debug_message_logging_disabled() { GAS_LIMIT, None, vec![], - false, + DebugInfo::Skip, + CollectEvents::Skip, Determinism::Enforced, ); assert_matches!(result.result, Ok(_)); @@ -2629,7 +2685,8 @@ fn debug_message_invalid_utf8() { Code::Upload(wasm), vec![], vec![], - false, + DebugInfo::Skip, + CollectEvents::Skip, ) .result .unwrap() @@ -2641,7 +2698,8 @@ fn debug_message_invalid_utf8() { GAS_LIMIT, None, vec![], - true, + DebugInfo::UnsafeDebug, + CollectEvents::Skip, Determinism::Enforced, ); assert_ok!(result.result); @@ -2665,7 +2723,8 @@ fn gas_estimation_nested_call_fixed_limit() { Code::Upload(caller_code), vec![], vec![0], - false, + DebugInfo::Skip, + CollectEvents::Skip, ) .result .unwrap() @@ -2679,7 +2738,8 @@ fn gas_estimation_nested_call_fixed_limit() { Code::Upload(callee_code), vec![], vec![1], - false, + DebugInfo::Skip, + CollectEvents::Skip, ) .result .unwrap() @@ -2700,7 +2760,8 @@ fn gas_estimation_nested_call_fixed_limit() { GAS_LIMIT, None, input.clone(), - false, + DebugInfo::Skip, + CollectEvents::Skip, Determinism::Enforced, ); assert_ok!(&result.result); @@ -2717,7 +2778,8 @@ fn gas_estimation_nested_call_fixed_limit() { result.gas_required, Some(result.storage_deposit.charge_or_zero()), input.clone(), - false, + DebugInfo::Skip, + CollectEvents::Skip, Determinism::Enforced, ) .result @@ -2731,7 +2793,8 @@ fn gas_estimation_nested_call_fixed_limit() { result.gas_required.sub_proof_size(1), Some(result.storage_deposit.charge_or_zero()), input, - false, + DebugInfo::Skip, + CollectEvents::Skip, Determinism::Enforced, ) .result; @@ -2757,7 +2820,8 @@ fn gas_estimation_call_runtime() { Code::Upload(caller_code), vec![], vec![0], - false, + DebugInfo::Skip, + CollectEvents::Skip, ) .result .unwrap() @@ -2771,7 +2835,8 @@ fn gas_estimation_call_runtime() { Code::Upload(callee_code), vec![], vec![1], - false, + DebugInfo::Skip, + CollectEvents::Skip, ) .result .unwrap() @@ -2790,7 +2855,8 @@ fn gas_estimation_call_runtime() { GAS_LIMIT, None, call.encode(), - false, + DebugInfo::Skip, + CollectEvents::Skip, Determinism::Enforced, ); // contract encodes the result of the dispatch runtime @@ -2807,7 +2873,8 @@ fn gas_estimation_call_runtime() { result.gas_required, None, call.encode(), - false, + DebugInfo::Skip, + CollectEvents::Skip, Determinism::Enforced, ) .result @@ -2832,7 +2899,8 @@ fn call_runtime_reentrancy_guarded() { Code::Upload(caller_code), vec![], vec![0], - false, + DebugInfo::Skip, + CollectEvents::Skip, ) .result .unwrap() @@ -2846,7 +2914,8 @@ fn call_runtime_reentrancy_guarded() { Code::Upload(callee_code), vec![], vec![1], - false, + DebugInfo::Skip, + CollectEvents::Skip, ) .result .unwrap() @@ -2870,7 +2939,8 @@ fn call_runtime_reentrancy_guarded() { GAS_LIMIT, None, call.encode(), - false, + DebugInfo::Skip, + CollectEvents::Skip, Determinism::Enforced, ) .result @@ -2896,7 +2966,8 @@ fn ecdsa_recover() { Code::Upload(wasm), vec![], vec![], - false, + DebugInfo::Skip, + CollectEvents::Skip, ) .result .unwrap() @@ -2932,7 +3003,8 @@ fn ecdsa_recover() { GAS_LIMIT, None, params, - false, + DebugInfo::Skip, + CollectEvents::Skip, Determinism::Enforced, ) .result @@ -2942,6 +3014,138 @@ fn ecdsa_recover() { }) } +#[test] +fn bare_instantiate_returns_events() { + let (wasm, _code_hash) = compile_module::("transfer_return_code").unwrap(); + ExtBuilder::default().existential_deposit(50).build().execute_with(|| { + let min_balance = ::Currency::minimum_balance(); + let _ = Balances::deposit_creating(&ALICE, 1000 * min_balance); + + let result = Contracts::bare_instantiate( + ALICE, + min_balance * 100, + GAS_LIMIT, + None, + Code::Upload(wasm), + vec![], + vec![], + DebugInfo::Skip, + CollectEvents::UnsafeCollect, + ); + + let events = result.events.unwrap(); + assert!(!events.is_empty()); + assert_eq!(events, System::events()); + }); +} + +#[test] +fn bare_instantiate_does_not_return_events() { + let (wasm, _code_hash) = compile_module::("transfer_return_code").unwrap(); + ExtBuilder::default().existential_deposit(50).build().execute_with(|| { + let min_balance = ::Currency::minimum_balance(); + let _ = Balances::deposit_creating(&ALICE, 1000 * min_balance); + + let result = Contracts::bare_instantiate( + ALICE, + min_balance * 100, + GAS_LIMIT, + None, + Code::Upload(wasm), + vec![], + vec![], + DebugInfo::Skip, + CollectEvents::Skip, + ); + + let events = result.events; + assert!(!System::events().is_empty()); + assert!(events.is_none()); + }); +} + +#[test] +fn bare_call_returns_events() { + let (wasm, _code_hash) = compile_module::("transfer_return_code").unwrap(); + ExtBuilder::default().existential_deposit(50).build().execute_with(|| { + let min_balance = ::Currency::minimum_balance(); + let _ = Balances::deposit_creating(&ALICE, 1000 * min_balance); + + let addr = Contracts::bare_instantiate( + ALICE, + min_balance * 100, + GAS_LIMIT, + None, + Code::Upload(wasm), + vec![], + vec![], + DebugInfo::Skip, + CollectEvents::Skip, + ) + .result + .unwrap() + .account_id; + + let result = Contracts::bare_call( + ALICE, + addr.clone(), + 0, + GAS_LIMIT, + None, + vec![], + DebugInfo::Skip, + CollectEvents::UnsafeCollect, + Determinism::Enforced, + ); + + let events = result.events.unwrap(); + assert_return_code!(&result.result.unwrap(), RuntimeReturnCode::Success); + assert!(!events.is_empty()); + assert_eq!(events, System::events()); + }); +} + +#[test] +fn bare_call_does_not_return_events() { + let (wasm, _code_hash) = compile_module::("transfer_return_code").unwrap(); + ExtBuilder::default().existential_deposit(50).build().execute_with(|| { + let min_balance = ::Currency::minimum_balance(); + let _ = Balances::deposit_creating(&ALICE, 1000 * min_balance); + + let addr = Contracts::bare_instantiate( + ALICE, + min_balance * 100, + GAS_LIMIT, + None, + Code::Upload(wasm), + vec![], + vec![], + DebugInfo::Skip, + CollectEvents::Skip, + ) + .result + .unwrap() + .account_id; + + let result = Contracts::bare_call( + ALICE, + addr.clone(), + 0, + GAS_LIMIT, + None, + vec![], + DebugInfo::Skip, + CollectEvents::Skip, + Determinism::Enforced, + ); + + let events = result.events; + assert_return_code!(&result.result.unwrap(), RuntimeReturnCode::Success); + assert!(!System::events().is_empty()); + assert!(events.is_none()); + }); +} + #[test] fn sr25519_verify() { let (wasm, _code_hash) = compile_module::("sr25519_verify").unwrap(); @@ -2958,7 +3162,8 @@ fn sr25519_verify() { Code::Upload(wasm), vec![], vec![], - false, + DebugInfo::Skip, + CollectEvents::Skip, ) .result .unwrap() @@ -2993,7 +3198,8 @@ fn sr25519_verify() { GAS_LIMIT, None, params, - false, + DebugInfo::Skip, + CollectEvents::Skip, Determinism::Enforced, ) .result @@ -3005,7 +3211,7 @@ fn sr25519_verify() { // verification should fail for other messages assert_return_code!(call_with(&b"hello worlD"), RuntimeReturnCode::Sr25519VerifyFailed); - }) + }); } #[test] @@ -3027,7 +3233,8 @@ fn failed_deposit_charge_should_roll_back_call() { Code::Upload(wasm_caller.clone()), vec![], vec![], - false, + DebugInfo::Skip, + CollectEvents::Skip, ) .result .unwrap() @@ -3040,7 +3247,8 @@ fn failed_deposit_charge_should_roll_back_call() { Code::Upload(wasm_callee.clone()), vec![], vec![], - false, + DebugInfo::Skip, + CollectEvents::Skip, ) .result .unwrap() @@ -3341,7 +3549,8 @@ fn instantiate_with_zero_balance_works() { Code::Upload(wasm), vec![], vec![], - false, + DebugInfo::Skip, + CollectEvents::Skip, ) .result .unwrap() @@ -3451,7 +3660,8 @@ fn instantiate_with_below_existential_deposit_works() { Code::Upload(wasm), vec![], vec![], - false, + DebugInfo::Skip, + CollectEvents::Skip, ) .result .unwrap() @@ -3566,7 +3776,8 @@ fn storage_deposit_works() { Code::Upload(wasm), vec![], vec![], - false, + DebugInfo::Skip, + CollectEvents::Skip, ) .result .unwrap() @@ -3704,7 +3915,8 @@ fn storage_deposit_callee_works() { Code::Upload(wasm_caller), vec![], vec![], - false, + DebugInfo::Skip, + CollectEvents::Skip, ) .result .unwrap() @@ -3717,7 +3929,8 @@ fn storage_deposit_callee_works() { Code::Upload(wasm_callee), vec![], vec![], - false, + DebugInfo::Skip, + CollectEvents::Skip, ) .result .unwrap() @@ -3758,7 +3971,8 @@ fn set_code_extrinsic() { Code::Upload(wasm), vec![], vec![], - false, + DebugInfo::Skip, + CollectEvents::Skip, ) .result .unwrap() @@ -3842,7 +4056,8 @@ fn slash_cannot_kill_account() { Code::Upload(wasm), vec![], vec![], - false, + DebugInfo::Skip, + CollectEvents::Skip, ) .result .unwrap() @@ -3931,7 +4146,8 @@ fn contract_reverted() { Code::Existing(code_hash), input.clone(), vec![], - false, + DebugInfo::Skip, + CollectEvents::Skip, ) .result .unwrap(); @@ -3948,7 +4164,8 @@ fn contract_reverted() { Code::Existing(code_hash), ReturnFlags::empty().bits().encode(), vec![], - false, + DebugInfo::Skip, + CollectEvents::Skip, ) .result .unwrap() @@ -3975,7 +4192,8 @@ fn contract_reverted() { GAS_LIMIT, None, input, - false, + DebugInfo::Skip, + CollectEvents::Skip, Determinism::Enforced, ) .result @@ -4008,7 +4226,8 @@ fn code_rejected_error_works() { Code::Upload(wasm), vec![], vec![], - true, + DebugInfo::UnsafeDebug, + CollectEvents::Skip, ); assert_err!(result.result, >::CodeRejected); assert_eq!( @@ -4035,7 +4254,8 @@ fn code_rejected_error_works() { Code::Upload(wasm), vec![], vec![], - true, + DebugInfo::UnsafeDebug, + CollectEvents::Skip, ); assert_err!(result.result, >::CodeRejected); assert_eq!( @@ -4062,7 +4282,8 @@ fn set_code_hash() { Code::Upload(wasm), vec![], vec![], - false, + DebugInfo::Skip, + CollectEvents::Skip, ) .result .unwrap() @@ -4085,7 +4306,8 @@ fn set_code_hash() { GAS_LIMIT, None, new_code_hash.as_ref().to_vec(), - true, + DebugInfo::UnsafeDebug, + CollectEvents::Skip, Determinism::Enforced, ) .result @@ -4100,7 +4322,8 @@ fn set_code_hash() { GAS_LIMIT, None, vec![], - true, + DebugInfo::UnsafeDebug, + CollectEvents::Skip, Determinism::Enforced, ) .result @@ -4163,7 +4386,8 @@ fn storage_deposit_limit_is_enforced() { Code::Upload(wasm), vec![], vec![], - false, + DebugInfo::Skip, + CollectEvents::Skip, ) .result .unwrap() @@ -4237,7 +4461,8 @@ fn deposit_limit_in_nested_calls() { Code::Upload(wasm_caller), vec![], vec![], - false, + DebugInfo::Skip, + CollectEvents::Skip, ) .result .unwrap() @@ -4250,7 +4475,8 @@ fn deposit_limit_in_nested_calls() { Code::Upload(wasm_callee), vec![], vec![], - false, + DebugInfo::Skip, + CollectEvents::Skip, ) .result .unwrap() @@ -4381,7 +4607,8 @@ fn deposit_limit_in_nested_instantiate() { Code::Upload(wasm_caller), vec![], vec![], - false, + DebugInfo::Skip, + CollectEvents::Skip, ) .result .unwrap() @@ -4395,7 +4622,8 @@ fn deposit_limit_in_nested_instantiate() { Code::Upload(wasm_callee), vec![0, 0, 0, 0], vec![], - false, + DebugInfo::Skip, + CollectEvents::Skip, ) .result .unwrap() @@ -4488,7 +4716,8 @@ fn deposit_limit_in_nested_instantiate() { GAS_LIMIT, Some(codec::Compact(callee_info_len + 2 + ED + 4).into()), (1u32, &code_hash_callee, callee_info_len + 2 + ED + 3).encode(), - false, + DebugInfo::Skip, + CollectEvents::Skip, Determinism::Enforced, ); @@ -4531,7 +4760,8 @@ fn deposit_limit_honors_liquidity_restrictions() { Code::Upload(wasm), vec![], vec![], - false, + DebugInfo::Skip, + CollectEvents::Skip, ) .result .unwrap() @@ -4575,7 +4805,8 @@ fn deposit_limit_honors_existential_deposit() { Code::Upload(wasm), vec![], vec![], - false, + DebugInfo::Skip, + CollectEvents::Skip, ) .result .unwrap() @@ -4618,7 +4849,8 @@ fn deposit_limit_honors_min_leftover() { Code::Upload(wasm), vec![], vec![], - false, + DebugInfo::Skip, + CollectEvents::Skip, ) .result .unwrap() @@ -4673,7 +4905,8 @@ fn cannot_instantiate_indeterministic_code() { Code::Upload(wasm.clone()), vec![], vec![], - false, + DebugInfo::Skip, + CollectEvents::Skip, ) .result, >::CodeRejected, @@ -4718,7 +4951,8 @@ fn cannot_instantiate_indeterministic_code() { Code::Existing(code_hash), vec![], vec![], - false, + DebugInfo::Skip, + CollectEvents::Skip, ) .result, >::Indeterministic, @@ -4733,7 +4967,8 @@ fn cannot_instantiate_indeterministic_code() { Code::Upload(caller_wasm), vec![], vec![], - false, + DebugInfo::Skip, + CollectEvents::Skip, ) .result .unwrap() @@ -4748,7 +4983,8 @@ fn cannot_instantiate_indeterministic_code() { GAS_LIMIT, None, code_hash.encode(), - false, + DebugInfo::Skip, + CollectEvents::Skip, Determinism::Enforced, ) .result, @@ -4764,7 +5000,8 @@ fn cannot_instantiate_indeterministic_code() { GAS_LIMIT, None, code_hash.encode(), - false, + DebugInfo::Skip, + CollectEvents::Skip, Determinism::Relaxed, ) .result, @@ -4797,7 +5034,8 @@ fn cannot_set_code_indeterministic_code() { Code::Upload(caller_wasm), vec![], vec![], - false, + DebugInfo::Skip, + CollectEvents::Skip, ) .result .unwrap() @@ -4812,7 +5050,8 @@ fn cannot_set_code_indeterministic_code() { GAS_LIMIT, None, code_hash.encode(), - false, + DebugInfo::Skip, + CollectEvents::Skip, Determinism::Relaxed, ) .result, @@ -4845,7 +5084,8 @@ fn delegate_call_indeterministic_code() { Code::Upload(caller_wasm), vec![], vec![], - false, + DebugInfo::Skip, + CollectEvents::Skip, ) .result .unwrap() @@ -4860,7 +5100,8 @@ fn delegate_call_indeterministic_code() { GAS_LIMIT, None, code_hash.encode(), - false, + DebugInfo::Skip, + CollectEvents::Skip, Determinism::Enforced, ) .result, @@ -4876,7 +5117,8 @@ fn delegate_call_indeterministic_code() { GAS_LIMIT, None, code_hash.encode(), - false, + DebugInfo::Skip, + CollectEvents::Skip, Determinism::Relaxed, ) .result @@ -4899,7 +5141,8 @@ fn reentrance_count_works_with_call() { Code::Upload(wasm), vec![], vec![], - false, + DebugInfo::Skip, + CollectEvents::Skip, ) .result .unwrap() @@ -4915,7 +5158,8 @@ fn reentrance_count_works_with_call() { GAS_LIMIT, None, input, - true, + DebugInfo::UnsafeDebug, + CollectEvents::Skip, Determinism::Enforced, ) .result @@ -4938,7 +5182,8 @@ fn reentrance_count_works_with_delegated_call() { Code::Upload(wasm), vec![], vec![], - false, + DebugInfo::Skip, + CollectEvents::Skip, ) .result .unwrap() @@ -4954,7 +5199,8 @@ fn reentrance_count_works_with_delegated_call() { GAS_LIMIT, None, input, - true, + DebugInfo::UnsafeDebug, + CollectEvents::Skip, Determinism::Enforced, ) .result @@ -4979,7 +5225,8 @@ fn account_reentrance_count_works() { Code::Upload(wasm), vec![], vec![], - false, + DebugInfo::Skip, + CollectEvents::Skip, ) .result .unwrap() @@ -4993,7 +5240,8 @@ fn account_reentrance_count_works() { Code::Upload(wasm_reentrance_count), vec![], vec![], - false, + DebugInfo::Skip, + CollectEvents::Skip, ) .result .unwrap() @@ -5006,7 +5254,8 @@ fn account_reentrance_count_works() { GAS_LIMIT, None, contract_addr.encode(), - true, + DebugInfo::UnsafeDebug, + CollectEvents::Skip, Determinism::Enforced, ) .result @@ -5019,7 +5268,8 @@ fn account_reentrance_count_works() { GAS_LIMIT, None, another_contract_addr.encode(), - true, + DebugInfo::UnsafeDebug, + CollectEvents::Skip, Determinism::Enforced, ) .result @@ -5091,7 +5341,8 @@ fn root_can_call() { Code::Upload(wasm), vec![], vec![], - false, + DebugInfo::Skip, + CollectEvents::Skip, ) .result .unwrap()