diff --git a/pallets/gear/src/runtime_api.rs b/pallets/gear/src/runtime_api.rs index d3dc1d94a9a..f2f09ac4bc6 100644 --- a/pallets/gear/src/runtime_api.rs +++ b/pallets/gear/src/runtime_api.rs @@ -17,9 +17,10 @@ // along with this program. If not, see . use super::*; -use crate::queue::QueueStep; +use crate::queue::{ActorResult, QueueStep}; use common::ActiveProgram; use core::convert::TryFrom; +use core_processor::common::PrechargedDispatch; use gear_core::{code::TryNewCodeConfig, pages::WasmPage}; use gear_wasm_instrument::syscalls::SysCallName; @@ -126,10 +127,20 @@ where }; let actor_id = queued_dispatch.destination(); + let dispatch_id = queued_dispatch.id(); + let dispatch_reply = queued_dispatch.reply_details().is_some(); + + let balance = CurrencyOf::::free_balance(&::from_origin( + actor_id.into_origin(), + )); - let actor = ext_manager - .get_actor(actor_id) - .ok_or_else(|| b"Program not found in the storage".to_vec())?; + let get_actor_data = |precharged_dispatch: PrechargedDispatch| { + // At this point gas counters should be changed accordingly so fetch the program data. + match Self::get_active_actor_data(actor_id, dispatch_id, dispatch_reply) { + ActorResult::Data(data) => Ok((precharged_dispatch, data)), + ActorResult::Continue => Err(precharged_dispatch), + } + }; let dispatch_id = queued_dispatch.id(); let success_reply = queued_dispatch @@ -146,8 +157,8 @@ where ext_manager: &mut ext_manager, gas_limit, dispatch: queued_dispatch, - balance: actor.balance, - get_actor_data: |dispatch| Ok((dispatch, actor.executable_data)), + balance: balance.unique_saturated_into(), + get_actor_data, }; let journal = step.execute().unwrap_or_else(|e| unreachable!("{e:?}")); diff --git a/pallets/gear/src/tests.rs b/pallets/gear/src/tests.rs index fef0874afa1..1a234ddff62 100644 --- a/pallets/gear/src/tests.rs +++ b/pallets/gear/src/tests.rs @@ -14317,6 +14317,45 @@ fn gear_block_number_math_adds_up() { }) } +#[test] +fn test_gas_info_of_terminated_program() { + use demo_constructor::{Calls, Scheme}; + + init_logger(); + new_test_ext().execute_with(|| { + // Dies in init + let init_dead = Calls::builder().panic("Die in init"); + let handle_dead = Calls::builder().panic("Called after being terminated!"); + let (_, pid_dead) = utils::submit_constructor_with_args( + USER_1, + b"salt1", + Scheme::predefined(init_dead, handle_dead, Calls::default()), + 0, + ); + + // Sends in handle message do dead program + let handle_proxy = Calls::builder().send(pid_dead.into_bytes(), []); + let (_, proxy_pid) = utils::submit_constructor_with_args( + USER_1, + b"salt2", + Scheme::predefined(Calls::default(), handle_proxy, Calls::default()), + 0, + ); + + run_to_next_block(None); + + let _gas_info = Gear::calculate_gas_info( + USER_1.into_origin(), + HandleKind::Handle(proxy_pid), + EMPTY_PAYLOAD.to_vec(), + 0, + true, + true, + ) + .expect("failed getting gas info"); + }) +} + mod utils { #![allow(unused)]