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}