1use std::{
16 fmt,
17 fmt::Debug,
18 marker::PhantomData,
19};
20
21use frame_support::pallet_prelude::{
22 Decode,
23 Encode,
24};
25use ink::codegen::ContractCallBuilder;
26use ink_env::{
27 call::{
28 utils::DecodeMessageResult,
29 FromAddr,
30 },
31 Environment,
32};
33use ink_primitives::{
34 Address,
35 ConstructorResult,
36 MessageResult,
37 H256,
38};
39use pallet_revive::{
40 evm::CallTrace,
41 CodeUploadResult,
42 ExecReturnValue,
43 InstantiateReturnValue,
44 StorageDeposit,
45};
46use sp_runtime::{
47 DispatchError,
48 Weight,
49};
50
51pub type ContractInstantiateResultFor<E> =
53 ContractResult<InstantiateReturnValue, <E as Environment>::Balance>;
54
55#[derive(Debug, Clone, Eq, PartialEq, Encode, Decode)]
67pub struct ContractResult<R, Balance> {
68 pub gas_consumed: Weight,
70 pub gas_required: Weight,
81 pub storage_deposit: StorageDeposit<Balance>,
88 pub result: Result<R, DispatchError>,
90}
91
92pub type ContractExecResultFor<E> =
94 ContractResult<ExecReturnValue, <E as Environment>::Balance>;
95
96pub struct BareInstantiationResult<EventLog> {
98 pub addr: Address,
100 pub events: EventLog,
102 pub trace: Option<CallTrace>,
104 pub code_hash: H256,
106}
107
108impl<EventLog> BareInstantiationResult<EventLog> {
109 pub fn call(&self) -> Address {
112 self.addr
113 }
114}
115
116impl<EventLog> Debug for BareInstantiationResult<EventLog>
119where
120 EventLog: Debug,
121{
122 fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
123 f.debug_struct("BareInstantiationResult")
125 .field("addr", &self.addr)
126 .field("events", &self.events)
127 .field("trace", &self.trace)
128 .finish()
129 }
130}
131
132pub struct InstantiationResult<E: Environment, EventLog, Abi> {
134 pub addr: Address,
136 pub dry_run: InstantiateDryRunResult<E, Abi>,
139 pub events: EventLog,
141 pub trace: Option<CallTrace>,
143 pub code_hash: H256,
145}
146
147impl<E: Environment, EventLog, Abi> InstantiationResult<E, EventLog, Abi> {
148 pub fn call_builder<Contract>(&self) -> <Contract as ContractCallBuilder>::Type<Abi>
154 where
155 Contract: ContractCallBuilder,
156 <Contract as ContractCallBuilder>::Type<Abi>: FromAddr,
157 {
158 <<Contract as ContractCallBuilder>::Type<Abi> as FromAddr>::from_addr(self.addr)
159 }
160
161 pub fn call_builder_abi<Contract, CallAbi>(
168 &self,
169 ) -> <Contract as ContractCallBuilder>::Type<CallAbi>
170 where
171 Contract: ContractCallBuilder,
172 <Contract as ContractCallBuilder>::Type<CallAbi>: FromAddr,
173 {
174 <<Contract as ContractCallBuilder>::Type<CallAbi> as FromAddr>::from_addr(
175 self.addr,
176 )
177 }
178}
179
180impl<E: Environment, EventLog, Abi> Debug for InstantiationResult<E, EventLog, Abi>
183where
184 E::AccountId: Debug,
185 E::Balance: Debug,
186 E::EventRecord: Debug,
187 EventLog: Debug,
188{
189 fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
190 f.debug_struct("InstantiationResult")
192 .field("addr", &self.addr)
193 .field("dry_run", &self.dry_run)
194 .field("events", &self.events)
195 .finish()
196 }
197}
198
199pub struct UploadResult<E: Environment, EventLog> {
201 pub code_hash: H256,
203 pub dry_run: CodeUploadResult<E::Balance>,
205 pub events: EventLog,
207}
208
209impl<E: Environment, EventLog> Debug for UploadResult<E, EventLog>
212where
213 E::Balance: Debug,
214 H256: Debug,
215 EventLog: Debug,
216{
217 fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
218 f.debug_struct("UploadResult")
219 .field("code_hash", &self.code_hash)
220 .field("dry_run", &self.dry_run)
221 .field("events", &self.events)
222 .finish()
223 }
224}
225
226pub struct CallResult<E: Environment, V, EventLog, Abi> {
228 pub dry_run: CallDryRunResult<E, V, Abi>,
230 pub events: EventLog,
232 pub trace: Option<CallTrace>,
234}
235
236impl<E: Environment, V: DecodeMessageResult<Abi>, EventLog, Abi>
237 CallResult<E, V, EventLog, Abi>
238{
239 pub fn message_result(&self) -> MessageResult<V> {
246 self.dry_run.message_result()
247 }
248
249 pub fn return_value(self) -> V {
254 self.dry_run.return_value()
255 }
256}
257
258impl<E: Environment, V, EventLog, Abi> CallResult<E, V, EventLog, Abi> {
259 pub fn return_data(&self) -> &[u8] {
263 &self.dry_run.exec_return_value().data
264 }
265}
266
267impl<E: Environment, V, EventLog, Abi> Debug for CallResult<E, V, EventLog, Abi>
269where
270 E: Debug,
271 E::Balance: Debug,
272 E::EventRecord: Debug,
273 V: Debug,
274 EventLog: Debug,
275{
276 fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
277 f.debug_struct("CallResult")
278 .field("dry_run", &self.dry_run)
279 .field("events", &self.events)
280 .field("trace", &self.trace)
281 .finish()
282 }
283}
284
285pub struct CallDryRunResult<E: Environment, V, Abi> {
287 pub exec_result: ContractExecResultFor<E>,
289 pub trace: Option<CallTrace>,
291 pub _marker: PhantomData<(V, Abi)>,
293}
294
295impl<E: Environment, V, Abi> Debug for CallDryRunResult<E, V, Abi>
298where
299 E::Balance: Debug,
300 E::EventRecord: Debug,
301{
302 fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
303 f.debug_struct("CallDryRunResult")
304 .field("exec_result", &self.exec_result)
305 .finish()
306 }
307}
308
309impl<E: Environment, V, Abi> CallDryRunResult<E, V, Abi> {
310 pub fn is_err(&self) -> bool {
312 self.exec_result.result.is_err() || self.did_revert()
313 }
314
315 pub fn exec_return_value(&self) -> &ExecReturnValue {
319 self.exec_result
320 .result
321 .as_ref()
322 .unwrap_or_else(|call_err| panic!("Call dry-run failed: {call_err:?}"))
323 }
324
325 pub fn did_revert(&self) -> bool {
327 let res = self.exec_result.result.clone().expect("no result found");
328 res.did_revert()
329 }
330
331 pub fn return_data(&self) -> &[u8] {
335 &self.exec_return_value().data
336 }
337}
338
339impl<E: Environment, V: DecodeMessageResult<Abi>, Abi> CallDryRunResult<E, V, Abi> {
340 pub fn message_result(&self) -> MessageResult<V> {
346 let data = &self.exec_return_value().data;
347 DecodeMessageResult::decode_output(data.as_ref(), self.did_revert()).unwrap_or_else(|env_err| {
348 panic!(
349 "Decoding dry run result to ink! message return type failed: {env_err:?} {:?}",
350 self.exec_return_value()
351 )
352 })
353 }
354
355 pub fn return_value(&self) -> V {
360 self.message_result()
361 .unwrap_or_else(|lang_err| {
362 panic!(
363 "Encountered a `LangError` while decoding dry run result to ink! message: {lang_err:?}"
364 )
365 })
366 }
367}
368
369pub struct InstantiateDryRunResult<E: Environment, Abi> {
371 pub contract_result: ContractInstantiateResultFor<E>,
373 pub _marker: PhantomData<Abi>,
375}
376
377impl<E: Environment, Abi> From<ContractInstantiateResultFor<E>>
378 for InstantiateDryRunResult<E, Abi>
379{
380 fn from(contract_result: ContractInstantiateResultFor<E>) -> Self {
381 Self {
382 contract_result,
383 _marker: PhantomData,
384 }
385 }
386}
387
388impl<E: Environment, Abi> InstantiateDryRunResult<E, Abi> {
389 pub fn is_err(&self) -> bool {
391 self.contract_result.result.is_err()
392 }
393
394 pub fn instantiate_return_value(&self) -> &InstantiateReturnValue {
398 self.contract_result
399 .result
400 .as_ref()
401 .unwrap_or_else(|call_err| panic!("Instantiate dry-run failed: {call_err:?}"))
402 }
403
404 pub fn constructor_result<V: DecodeMessageResult<Abi>>(
410 &self,
411 ) -> ConstructorResult<V> {
412 let data = &self.instantiate_return_value().result.data;
413 DecodeMessageResult::decode_output(data.as_ref(), self.did_revert()).unwrap_or_else(|env_err| {
414 panic!("Decoding dry run result to constructor return type failed: {env_err:?}")
415 })
416 }
417
418 pub fn return_data(&self) -> &[u8] {
422 &self.instantiate_return_value().result.data
423 }
424
425 pub fn did_revert(&self) -> bool {
427 let res = self.instantiate_return_value().clone().result;
428 res.did_revert()
429 }
430}
431
432impl<E, Abi> Debug for InstantiateDryRunResult<E, Abi>
433where
434 E: Environment,
435 E::AccountId: Debug,
436 E::Balance: Debug,
437 E::EventRecord: Debug,
438{
439 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
440 f.debug_struct("InstantiateDryRunResult")
441 .field("contract_result", &self.contract_result)
442 .finish()
443 }
444}