odra_core/
call_result.rs

1use crate::casper_types::bytesrepr::{Bytes, ToBytes};
2use crate::prelude::*;
3use crate::utils::extract_event_name;
4use casper_event_standard::EventInstance;
5
6/// Represents the result of a contract call. Includes external contracts calls.
7///
8/// The result contains the address of the called contract, the address of the caller, the amount of gas
9/// used, the result of the call, and the events emitted by the contract.
10#[derive(Debug, Clone)]
11pub struct CallResult {
12    contract_address: Address,
13    caller: Address,
14    gas_used: u64,
15    result: OdraResult<Bytes>,
16    events: BTreeMap<Address, Vec<Bytes>>,
17    native_events: BTreeMap<Address, Vec<Bytes>>
18}
19
20impl CallResult {
21    /// Creates a new `CallResult` instance with the specified parameters.
22    pub fn new(
23        contract_address: Address,
24        caller: Address,
25        gas_used: u64,
26        result: OdraResult<Bytes>,
27        events: BTreeMap<Address, Vec<Bytes>>,
28        native_events: BTreeMap<Address, Vec<Bytes>>
29    ) -> Self {
30        Self {
31            contract_address,
32            caller,
33            gas_used,
34            result,
35            events,
36            native_events
37        }
38    }
39
40    /// Returns the result of the contract call as a [Bytes] object.
41    ///
42    /// # Panics
43    ///
44    /// Panics if the result is an error.
45    pub fn bytes(&self) -> Bytes {
46        match &self.result {
47            Ok(result) => result.clone(),
48            Err(error) => {
49                panic!("Last call result is an error: {:?}", error);
50            }
51        }
52    }
53
54    /// Returns the result of the contract call as a [OdraResult] object.
55    pub fn result(&self) -> OdraResult<Bytes> {
56        self.result.clone()
57    }
58
59    /// Returns the error of the contract call as an `OdraError` object.
60    pub fn error(&self) -> OdraError {
61        match &self.result {
62            Ok(_) => {
63                panic!("Last call result is not an error");
64            }
65            Err(error) => error.clone()
66        }
67    }
68
69    /// Returns the address of the caller.
70    pub fn caller(&self) -> Address {
71        self.caller
72    }
73
74    /// Returns the amount of gas used in the contract call.
75    pub fn gas_used(&self) -> u64 {
76        self.gas_used
77    }
78
79    /// Returns the address of the contract.
80    pub fn contract_address(&self) -> Address {
81        self.contract_address
82    }
83
84    /// Returns the names of the events emitted in the call.
85    pub fn event_names(&self, contract_address: &Address) -> Vec<String> {
86        self.events
87            .get(contract_address)
88            .unwrap_or(&vec![])
89            .iter()
90            .map(|event_bytes| extract_event_name(event_bytes).unwrap())
91            .collect()
92    }
93
94    pub fn native_event_names(&self, contract_address: &Address) -> Vec<String> {
95        self.native_events
96            .get(contract_address)
97            .unwrap_or(&vec![])
98            .iter()
99            .map(|event_bytes| extract_event_name(event_bytes).unwrap())
100            .collect()
101    }
102
103    /// Returns the events emitted by the contract in this call.
104    pub fn contract_events(&self, contract_address: &Address) -> Vec<Bytes> {
105        self.events.get(contract_address).unwrap_or(&vec![]).clone()
106    }
107
108    /// Returns the native events emitted by the contract in this call.
109    pub fn contract_native_events(&self, contract_address: &Address) -> Vec<Bytes> {
110        self.events.get(contract_address).unwrap_or(&vec![]).clone()
111    }
112
113    /// Checks if the specified event has been emitted by the contract during the call.
114    pub fn emitted(&self, contract_address: &Address, event_name: &str) -> bool {
115        self.event_names(contract_address)
116            .contains(&event_name.to_string())
117    }
118
119    /// Checks if the specified native event has been emitted by the contract during the call.
120    pub fn emitted_native(&self, contract_address: &Address, event_name: &str) -> bool {
121        self.native_event_names(contract_address)
122            .contains(&event_name.to_string())
123    }
124
125    /// Checks if the specified event instance has been emitted by the contract during the call.
126    pub fn emitted_event<T: ToBytes + EventInstance>(
127        &self,
128        contract_address: &Address,
129        event: T
130    ) -> bool {
131        self.contract_events(contract_address)
132            .contains(&Bytes::from(event.to_bytes().unwrap()))
133    }
134
135    /// Checks if the specified native event instance has been emitted by the contract during the call.
136    pub fn emitted_native_event<T: ToBytes + EventInstance>(
137        &self,
138        contract_address: &Address,
139        event: T
140    ) -> bool {
141        self.contract_native_events(contract_address)
142            .contains(&Bytes::from(event.to_bytes().unwrap()))
143    }
144
145    /// Returns a wrapper [ContractCallResult] object containing the current `CallResult` and the given contract address.
146    pub fn contract_last_call(self, contract_address: Address) -> ContractCallResult {
147        ContractCallResult {
148            call_result: self,
149            contract_address
150        }
151    }
152}
153
154/// Represents the result of a contract call.
155///
156/// It may represent not the original call but the an external call.
157/// However the result and gas used come from the original call.
158#[derive(Debug, Clone)]
159pub struct ContractCallResult {
160    call_result: CallResult,
161    contract_address: Address
162}
163
164impl ContractCallResult {
165    /// Returns the address of the contract.
166    ///
167    /// # Returns
168    ///
169    /// The address of the contract.
170    pub fn contract_address(&self) -> Address {
171        self.contract_address
172    }
173
174    /// Returns the address of the callee contract.
175    ///
176    /// # Returns
177    ///
178    /// The address of the callee contract.
179    pub fn callee_contract_address(&self) -> Address {
180        self.call_result.contract_address()
181    }
182
183    /// Returns the result of the original contract call as a [Bytes] object.
184    ///
185    /// # Panics
186    ///
187    /// Panics if the result is an error.
188    pub fn callee_contract_bytes(&self) -> Bytes {
189        self.call_result.bytes()
190    }
191
192    /// Returns the result of the original contract call as a [OdraResult] object.
193    pub fn callee_contract_result(&self) -> OdraResult<Bytes> {
194        self.call_result.result()
195    }
196
197    /// Returns the error of the original contract call as an `OdraError` object.
198    pub fn callee_contract_error(&self) -> OdraError {
199        self.call_result.error()
200    }
201
202    /// Returns the address of the original contract caller.
203    pub fn callee_contract_caller(&self) -> Address {
204        self.call_result.caller()
205    }
206
207    /// Returns the amount of gas used in the original contract call.
208    pub fn callee_contract_gas_used(&self) -> u64 {
209        self.call_result.gas_used()
210    }
211
212    /// Returns the names of the events emitted by the contract call.
213    ///
214    /// # Returns
215    ///
216    /// A vector containing the names of the events emitted by the contract call.
217    pub fn event_names(&self) -> Vec<String> {
218        self.call_result.event_names(&self.contract_address)
219    }
220
221    /// Returns the names of the native events emitted by the contract call.
222    ///
223    /// # Returns
224    ///
225    /// A vector containing the names of the events emitted by the contract call.
226    pub fn native_event_names(&self) -> Vec<String> {
227        self.call_result.native_event_names(&self.contract_address)
228    }
229
230    /// Returns the events emitted by the contract call.
231    ///
232    /// # Returns
233    ///
234    /// A vector containing the events emitted by the contract call.
235    pub fn events(&self) -> Vec<Bytes> {
236        self.call_result.contract_events(&self.contract_address)
237    }
238
239    /// Returns the native events emitted by the contract call.
240    ///
241    /// # Returns
242    ///
243    /// A vector containing the events emitted by the contract call.
244    pub fn native_events(&self) -> Vec<Bytes> {
245        self.call_result
246            .contract_native_events(&self.contract_address)
247    }
248
249    /// Checks if an event with the specified name was emitted by the contract call.
250    ///
251    /// # Arguments
252    ///
253    /// * `event_name` - The name of the event to check.
254    ///
255    /// # Returns
256    ///
257    /// `true` if the event was emitted, otherwise `false`.
258    pub fn emitted(&self, event_name: &str) -> bool {
259        self.call_result.emitted(&self.contract_address, event_name)
260    }
261
262    /// Checks if a native event with the specified name was emitted by the contract call.
263    ///
264    /// # Arguments
265    ///
266    /// * `event_name` - The name of the event to check.
267    ///
268    /// # Returns
269    ///
270    /// `true` if the event was emitted, otherwise `false`.
271    pub fn emitted_native(&self, event_name: &str) -> bool {
272        self.call_result
273            .emitted_native(&self.contract_address, event_name)
274    }
275    /// Checks if the specified event instance was emitted by the contract call.
276    ///
277    /// # Arguments
278    ///
279    /// * `event` - The event instance to check.
280    ///
281    /// # Returns
282    ///
283    /// `true` if the event was emitted, otherwise `false`.
284    pub fn emitted_event<T: ToBytes + EventInstance>(&self, event: T) -> bool {
285        self.call_result
286            .emitted_event(&self.contract_address, event)
287    }
288
289    /// Checks if the specified native event instance was emitted by the contract call.
290    ///
291    /// # Arguments
292    ///
293    /// * `event` - The event instance to check.
294    ///
295    /// # Returns
296    ///
297    /// `true` if the event was emitted, otherwise `false`.
298    pub fn emitted_native_event<T: ToBytes + EventInstance>(&self, event: T) -> bool {
299        self.call_result
300            .emitted_native_event(&self.contract_address, event)
301    }
302
303    /// Returns the raw call result. Includes data from sub-calls to external contracts.
304    pub fn raw_call_result(&self) -> CallResult {
305        self.call_result.clone()
306    }
307}