Skip to content

Commit 35d7e02

Browse files
Emit events when a contracts calls into the runtime (#1561)
Co-authored-by: Adam Dossa <adam.dossa@gmail.com>
1 parent 5d4bb99 commit 35d7e02

File tree

2 files changed

+54
-43
lines changed

2 files changed

+54
-43
lines changed

pallets/contracts/src/chain_extension.rs

Lines changed: 48 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,21 @@
1-
use codec::{Decode, Encode};
2-
use frame_support::{
3-
dispatch::{DispatchError, Dispatchable, GetDispatchInfo},
4-
ensure,
5-
log::trace,
6-
storage::unhashed,
7-
traits::{Get, GetCallMetadata},
8-
};
1+
#[cfg(feature = "std")]
2+
use sp_runtime::{Deserialize, Serialize};
3+
4+
use codec::{Decode, DecodeLimit, Encode};
5+
use frame_support::dispatch::{DispatchError, Dispatchable, GetDispatchInfo};
6+
use frame_support::ensure;
7+
use frame_support::log::trace;
8+
use frame_support::storage::unhashed;
9+
use frame_support::traits::{Get, GetCallMetadata};
910
use frame_system::RawOrigin;
11+
use scale_info::TypeInfo;
12+
use sp_core::crypto::UncheckedFrom;
13+
1014
use pallet_contracts::chain_extension as ce;
1115
use pallet_contracts::Config as BConfig;
1216
use pallet_permissions::with_call_metadata;
1317
use polymesh_common_utilities::Context;
1418
use polymesh_primitives::IdentityId;
15-
use scale_info::TypeInfo;
16-
use sp_core::crypto::UncheckedFrom;
17-
#[cfg(feature = "std")]
18-
use sp_runtime::{Deserialize, Serialize};
1919

2020
use super::*;
2121

@@ -479,35 +479,39 @@ where
479479
env.charge_weight(<T as Config>::WeightInfo::call_runtime(in_len))?;
480480

481481
// Decide what to call in the runtime.
482-
use codec::DecodeLimit;
483-
let call = match old_call {
484-
None => {
485-
let input = env.read(in_len)?;
486-
// Decode the pallet_id & extrinsic_id.
487-
let ext_id =
488-
ExtrinsicId::try_from(input.as_slice()).ok_or(Error::<T>::InvalidRuntimeCall)?;
489-
// Check if the extrinsic is allowed to be called.
490-
Module::<T>::ensure_call_runtime(ext_id)?;
491-
<<T as BConfig>::RuntimeCall>::decode_all_with_depth_limit(
492-
MAX_DECODE_DEPTH,
493-
&mut input.as_slice(),
494-
)
495-
.map_err(|_| Error::<T>::InvalidRuntimeCall)?
496-
}
497-
Some(ext_id) => {
498-
// Check if the extrinsic is allowed to be called.
499-
Module::<T>::ensure_call_runtime(ext_id)?;
500-
// Convert old ChainExtension runtime calls into `Call` format.
501-
let extrinsic: [u8; 2] = ext_id.into();
502-
let params = env.read(in_len)?;
503-
let mut input = ChainInput::new(&extrinsic, params.as_slice());
504-
let call = <<T as BConfig>::RuntimeCall>::decode_with_depth_limit(
505-
MAX_DECODE_DEPTH,
506-
&mut input,
507-
)
508-
.map_err(|_| Error::<T>::InvalidRuntimeCall)?;
509-
ensure!(input.is_empty(), Error::<T>::DataLeftAfterDecoding);
510-
call
482+
let (call, extrinsic_id) = {
483+
match old_call {
484+
None => {
485+
let input = env.read(in_len)?;
486+
// Decode the pallet_id & extrinsic_id.
487+
let ext_id = ExtrinsicId::try_from(input.as_slice())
488+
.ok_or(Error::<T>::InvalidRuntimeCall)?;
489+
// Check if the extrinsic is allowed to be called.
490+
Module::<T>::ensure_call_runtime(ext_id)?;
491+
(
492+
<<T as BConfig>::RuntimeCall>::decode_all_with_depth_limit(
493+
MAX_DECODE_DEPTH,
494+
&mut input.as_slice(),
495+
)
496+
.map_err(|_| Error::<T>::InvalidRuntimeCall)?,
497+
ext_id,
498+
)
499+
}
500+
Some(ext_id) => {
501+
// Check if the extrinsic is allowed to be called.
502+
Module::<T>::ensure_call_runtime(ext_id)?;
503+
// Convert old ChainExtension runtime calls into `Call` format.
504+
let extrinsic: [u8; 2] = ext_id.into();
505+
let params = env.read(in_len)?;
506+
let mut input = ChainInput::new(&extrinsic, params.as_slice());
507+
let call = <<T as BConfig>::RuntimeCall>::decode_with_depth_limit(
508+
MAX_DECODE_DEPTH,
509+
&mut input,
510+
)
511+
.map_err(|_| Error::<T>::InvalidRuntimeCall)?;
512+
ensure!(input.is_empty(), Error::<T>::DataLeftAfterDecoding);
513+
(call, ext_id)
514+
}
511515
}
512516
};
513517

@@ -517,6 +521,9 @@ where
517521

518522
// Execute call requested by contract, with current DID set to the contract owner.
519523
let addr = env.ext().address().clone();
524+
// Emit event for calling into the runtime
525+
Module::<T>::deposit_event(Event::<T>::SCRuntimeCall(addr.clone(), extrinsic_id));
526+
// Dispatch call
520527
let result = with_did_and_payer::<T, _, _>(contract_did::<T>(&addr)?, addr.clone(), || {
521528
with_call_metadata(call.get_call_metadata(), || {
522529
// Dispatch the call, avoiding use of `ext.call_runtime()`,

pallets/contracts/src/lib.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -322,10 +322,14 @@ decl_event! {
322322
pub enum Event<T>
323323
where
324324
Hash = CodeHash<T>,
325+
AccountId = <T as frame_system::Config>::AccountId,
325326
{
326-
/// Emitted when a contract starts supporting a new API upgrade
327+
/// Emitted when a contract starts supporting a new API upgrade.
327328
/// Contains the [`Api`], [`ChainVersion`], and the bytes for the code hash.
328-
ApiHashUpdated(Api, ChainVersion, Hash)
329+
ApiHashUpdated(Api, ChainVersion, Hash),
330+
/// Emitted when a contract calls into the runtime.
331+
/// Contains the account id set by the contract owner and the [`ExtrinsicId`].
332+
SCRuntimeCall(AccountId, ExtrinsicId)
329333
}
330334
}
331335

0 commit comments

Comments
 (0)