pallet_contracts/debug.rs
1// This file is part of Substrate.
2
3// Copyright (C) Parity Technologies (UK) Ltd.
4// SPDX-License-Identifier: Apache-2.0
5
6// Licensed under the Apache License, Version 2.0 (the "License");
7// you may not use this file except in compliance with the License.
8// You may obtain a copy of the License at
9//
10// http://www.apache.org/licenses/LICENSE-2.0
11//
12// Unless required by applicable law or agreed to in writing, software
13// distributed under the License is distributed on an "AS IS" BASIS,
14// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15// See the License for the specific language governing permissions and
16// limitations under the License.
17
18pub use crate::{
19 exec::{ExecResult, ExportedFunction},
20 primitives::ExecReturnValue,
21};
22use crate::{Config, LOG_TARGET};
23
24/// Umbrella trait for all interfaces that serves for debugging.
25pub trait Debugger<T: Config>: Tracing<T> + CallInterceptor<T> {}
26
27impl<T: Config, V> Debugger<T> for V where V: Tracing<T> + CallInterceptor<T> {}
28
29/// Defines methods to capture contract calls, enabling external observers to
30/// measure, trace, and react to contract interactions.
31pub trait Tracing<T: Config> {
32 /// The type of [`CallSpan`] that is created by this trait.
33 type CallSpan: CallSpan;
34
35 /// Creates a new call span to encompass the upcoming contract execution.
36 ///
37 /// This method should be invoked just before the execution of a contract and
38 /// marks the beginning of a traceable span of execution.
39 ///
40 /// # Arguments
41 ///
42 /// * `contract_address` - The address of the contract that is about to be executed.
43 /// * `entry_point` - Describes whether the call is the constructor or a regular call.
44 /// * `input_data` - The raw input data of the call.
45 fn new_call_span(
46 contract_address: &T::AccountId,
47 entry_point: ExportedFunction,
48 input_data: &[u8],
49 ) -> Self::CallSpan;
50}
51
52/// Defines a span of execution for a contract call.
53pub trait CallSpan {
54 /// Called just after the execution of a contract.
55 ///
56 /// # Arguments
57 ///
58 /// * `output` - The raw output of the call.
59 fn after_call(self, output: &ExecReturnValue);
60}
61
62impl<T: Config> Tracing<T> for () {
63 type CallSpan = ();
64
65 fn new_call_span(
66 contract_address: &T::AccountId,
67 entry_point: ExportedFunction,
68 input_data: &[u8],
69 ) {
70 log::trace!(target: LOG_TARGET, "call {entry_point:?} account: {contract_address:?}, input_data: {input_data:?}")
71 }
72}
73
74impl CallSpan for () {
75 fn after_call(self, output: &ExecReturnValue) {
76 log::trace!(target: LOG_TARGET, "call result {output:?}")
77 }
78}
79
80/// Provides an interface for intercepting contract calls.
81pub trait CallInterceptor<T: Config> {
82 /// Allows to intercept contract calls and decide whether they should be executed or not.
83 /// If the call is intercepted, the mocked result of the call is returned.
84 ///
85 /// # Arguments
86 ///
87 /// * `contract_address` - The address of the contract that is about to be executed.
88 /// * `entry_point` - Describes whether the call is the constructor or a regular call.
89 /// * `input_data` - The raw input data of the call.
90 ///
91 /// # Expected behavior
92 ///
93 /// This method should return:
94 /// * `Some(ExecResult)` - if the call should be intercepted and the mocked result of the call
95 /// is returned.
96 /// * `None` - otherwise, i.e. the call should be executed normally.
97 fn intercept_call(
98 contract_address: &T::AccountId,
99 entry_point: &ExportedFunction,
100 input_data: &[u8],
101 ) -> Option<ExecResult>;
102}
103
104impl<T: Config> CallInterceptor<T> for () {
105 fn intercept_call(
106 _contract_address: &T::AccountId,
107 _entry_point: &ExportedFunction,
108 _input_data: &[u8],
109 ) -> Option<ExecResult> {
110 None
111 }
112}