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(crate) struct CallResult {
12    contract_address: Address,
13    caller: Address,
14    gas_used: u64,
15    result: OdraResult<Bytes>,
16    events: BTreeMap<Address, Vec<Bytes>>
17}
18
19impl CallResult {
20    /// Creates a new `CallResult` instance with the specified parameters.
21    pub fn new(
22        contract_address: Address,
23        caller: Address,
24        gas_used: u64,
25        result: OdraResult<Bytes>,
26        events: BTreeMap<Address, Vec<Bytes>>
27    ) -> Self {
28        Self {
29            contract_address,
30            caller,
31            gas_used,
32            result,
33            events
34        }
35    }
36
37    /// Returns the result of the contract call as a [Bytes] object.
38    ///
39    /// # Panics
40    ///
41    /// Panics if the result is an error.
42    pub fn bytes(&self) -> Bytes {
43        match &self.result {
44            Ok(result) => result.clone(),
45            Err(error) => {
46                panic!("Last call result is an error: {:?}", error);
47            }
48        }
49    }
50
51    /// Returns the result of the contract call as a [OdraResult] object.
52    pub fn result(&self) -> OdraResult<Bytes> {
53        self.result.clone()
54    }
55
56    /// Returns the error of the contract call as an `OdraError` object.
57    pub fn error(&self) -> OdraError {
58        match &self.result {
59            Ok(_) => {
60                panic!("Last call result is not an error");
61            }
62            Err(error) => error.clone()
63        }
64    }
65
66    /// Returns the address of the caller.
67    pub fn caller(&self) -> Address {
68        self.caller
69    }
70
71    /// Returns the amount of gas used in the contract call.
72    pub fn gas_used(&self) -> u64 {
73        self.gas_used
74    }
75
76    /// Returns the address of the contract.
77    pub fn contract_address(&self) -> Address {
78        self.contract_address
79    }
80
81    /// Returns the names of the events emitted by the contract at the given address.
82    pub fn event_names(&self, contract_address: &Address) -> Vec<String> {
83        self.events
84            .get(contract_address)
85            .unwrap_or(&vec![])
86            .iter()
87            .map(|event_bytes| extract_event_name(event_bytes).unwrap())
88            .collect()
89    }
90
91    /// Returns the events emitted by the contract at the given address.
92    pub fn contract_events(&self, contract_address: &Address) -> Vec<Bytes> {
93        self.events.get(contract_address).unwrap_or(&vec![]).clone()
94    }
95
96    /// Checks if the specified event has been emitted by the contract at the given address.
97    pub fn emitted(&self, contract_address: &Address, event_name: &str) -> bool {
98        self.event_names(contract_address)
99            .contains(&event_name.to_string())
100    }
101
102    /// Checks if the specified event instance has been emitted by the contract at the given address.
103    pub fn emitted_event<T: ToBytes + EventInstance>(
104        &self,
105        contract_address: &Address,
106        event: &T
107    ) -> bool {
108        self.contract_events(contract_address)
109            .contains(&Bytes::from(event.to_bytes().unwrap()))
110    }
111
112    /// Returns a wrapper [ContractCallResult] object containing the current `CallResult` and the given contract address.
113    pub fn contract_last_call(self, contract_address: Address) -> ContractCallResult {
114        ContractCallResult {
115            call_result: self,
116            contract_address
117        }
118    }
119}
120
121/// Represents the result of a contract call.
122///
123/// It may represent not the original call but the an external call.
124/// However the result and gas used come from the original call.
125#[derive(Debug, Clone)]
126pub struct ContractCallResult {
127    call_result: CallResult,
128    contract_address: Address
129}
130
131impl ContractCallResult {
132    /// Returns the address of the contract.
133    ///
134    /// # Returns
135    ///
136    /// The address of the contract.
137    pub fn contract_address(&self) -> Address {
138        self.contract_address
139    }
140
141    /// Returns the address of the callee contract.
142    ///
143    /// # Returns
144    ///
145    /// The address of the callee contract.
146    pub fn callee_contract_address(&self) -> Address {
147        self.call_result.contract_address()
148    }
149
150    /// Returns the result of the original contract call as a [Bytes] object.
151    ///
152    /// # Panics
153    ///
154    /// Panics if the result is an error.
155    pub fn callee_contract_bytes(&self) -> Bytes {
156        self.call_result.bytes()
157    }
158
159    /// Returns the result of the original contract call as a [OdraResult] object.
160    pub fn callee_contract_result(&self) -> OdraResult<Bytes> {
161        self.call_result.result()
162    }
163
164    /// Returns the error of the original contract call as an `OdraError` object.
165    pub fn callee_contract_error(&self) -> OdraError {
166        self.call_result.error()
167    }
168
169    /// Returns the address of the original contract caller.
170    pub fn callee_contract_caller(&self) -> Address {
171        self.call_result.caller()
172    }
173
174    /// Returns the amount of gas used in the original contract call.
175    pub fn callee_contract_gas_used(&self) -> u64 {
176        self.call_result.gas_used()
177    }
178
179    /// Returns the names of the events emitted by the contract call.
180    ///
181    /// # Returns
182    ///
183    /// A vector containing the names of the events emitted by the contract call.
184    pub fn event_names(&self) -> Vec<String> {
185        self.call_result.event_names(&self.contract_address)
186    }
187
188    /// Returns the events emitted by the contract call.
189    ///
190    /// # Returns
191    ///
192    /// A vector containing the events emitted by the contract call.
193    pub fn events(&self) -> Vec<Bytes> {
194        self.call_result.contract_events(&self.contract_address)
195    }
196
197    /// Checks if an event with the specified name was emitted by the contract call.
198    ///
199    /// # Arguments
200    ///
201    /// * `event_name` - The name of the event to check.
202    ///
203    /// # Returns
204    ///
205    /// `true` if the event was emitted, otherwise `false`.
206    pub fn emitted(&self, event_name: &str) -> bool {
207        self.call_result.emitted(&self.contract_address, event_name)
208    }
209
210    /// Checks if the specified event instance was emitted by the contract call.
211    ///
212    /// # Arguments
213    ///
214    /// * `event` - The event instance to check.
215    ///
216    /// # Returns
217    ///
218    /// `true` if the event was emitted, otherwise `false`.
219    pub fn emitted_event<T: ToBytes + EventInstance>(&self, event: &T) -> bool {
220        self.call_result
221            .emitted_event(&self.contract_address, event)
222    }
223}