diff --git a/pallets/gear/src/runtime_api.rs b/pallets/gear/src/runtime_api.rs
index a37fea57381..5c486a8ab4b 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,11 +127,25 @@ where
break;
};
+ //let actor = ext_manager
+ // .get_actor(actor_id)
+ // .ok_or_else(|| b"Program not found in the storage".to_vec())?;
+
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
@@ -148,8 +163,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 ae861d0d365..c20269e10d2 100644
--- a/pallets/gear/src/tests.rs
+++ b/pallets/gear/src/tests.rs
@@ -15251,3 +15251,42 @@ mod utils {
::GasMultiplier::get().gas_to_value(gas)
}
}
+
+#[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".to_vec(),
+ 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".to_vec(),
+ 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"); // panics here as `pid_dead` is terminated and rpc call wasn't able to get code.
+ })
+}