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 Environment,
28 call::{
29 FromAddr,
30 utils::DecodeMessageResult,
31 },
32};
33use ink_primitives::{
34 Address,
35 ConstructorResult,
36 H256,
37 MessageResult,
38};
39use ink_revive_types::{
40 CodeUploadResult,
41 ExecReturnValue,
42 InstantiateReturnValue,
43 StorageDeposit,
44 evm::CallTrace,
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<E: Environment, EventLog> {
98 pub addr: Address,
100 pub account_id: E::AccountId,
102 pub events: EventLog,
104 pub trace: Option<CallTrace>,
106 pub code_hash: H256,
108}
109
110impl<E: Environment, EventLog> Debug for BareInstantiationResult<E, EventLog>
113where
114 EventLog: Debug,
115{
116 fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
117 f.debug_struct("BareInstantiationResult")
118 .field("addr", &self.addr)
119 .field("account_id", &self.account_id.encode())
120 .field("events", &self.events)
121 .field("trace", &self.trace)
122 .field("code_hash", &self.code_hash)
123 .finish()
124 }
125}
126
127pub struct InstantiationResult<E: Environment, EventLog, Abi> {
129 pub addr: Address,
131 pub account_id: E::AccountId,
133 pub dry_run: InstantiateDryRunResult<E, Abi>,
136 pub events: EventLog,
138 pub trace: Option<CallTrace>,
140 pub code_hash: H256,
142}
143
144impl<E: Environment, EventLog, Abi> InstantiationResult<E, EventLog, Abi> {
145 pub fn call_builder<Contract>(&self) -> <Contract as ContractCallBuilder>::Type<Abi>
151 where
152 Contract: ContractCallBuilder,
153 <Contract as ContractCallBuilder>::Type<Abi>: FromAddr,
154 {
155 <<Contract as ContractCallBuilder>::Type<Abi> as FromAddr>::from_addr(self.addr)
156 }
157
158 pub fn call_builder_abi<Contract, CallAbi>(
165 &self,
166 ) -> <Contract as ContractCallBuilder>::Type<CallAbi>
167 where
168 Contract: ContractCallBuilder,
169 <Contract as ContractCallBuilder>::Type<CallAbi>: FromAddr,
170 {
171 <<Contract as ContractCallBuilder>::Type<CallAbi> as FromAddr>::from_addr(
172 self.addr,
173 )
174 }
175}
176
177impl<E: Environment, EventLog, Abi> Debug for InstantiationResult<E, EventLog, Abi>
180where
181 E::AccountId: Debug,
182 E::Balance: Debug,
183 E::EventRecord: Debug,
184 EventLog: Debug,
185{
186 fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
187 f.debug_struct("InstantiationResult")
189 .field("addr", &self.addr)
190 .field("dry_run", &self.dry_run)
191 .field("events", &self.events)
192 .finish()
193 }
194}
195
196pub struct UploadResult<E: Environment, EventLog> {
198 pub code_hash: H256,
200 pub dry_run: CodeUploadResult<E::Balance>,
202 pub events: EventLog,
204}
205
206impl<E: Environment, EventLog> Debug for UploadResult<E, EventLog>
209where
210 E::Balance: Debug,
211 H256: Debug,
212 EventLog: Debug,
213{
214 fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
215 f.debug_struct("UploadResult")
216 .field("code_hash", &self.code_hash)
217 .field("dry_run", &self.dry_run)
218 .field("events", &self.events)
219 .finish()
220 }
221}
222
223pub struct CallResult<E: Environment, V, EventLog, Abi> {
225 pub dry_run: CallDryRunResult<E, V, Abi>,
227 pub events: EventLog,
229 pub trace: Option<CallTrace>,
231}
232
233impl<E: Environment, V: DecodeMessageResult<Abi>, EventLog, Abi>
234 CallResult<E, V, EventLog, Abi>
235{
236 pub fn message_result(&self) -> MessageResult<V> {
243 self.dry_run.message_result()
244 }
245
246 pub fn return_value(self) -> V {
251 self.dry_run.return_value()
252 }
253}
254
255impl<E: Environment, V, EventLog, Abi> CallResult<E, V, EventLog, Abi> {
256 pub fn return_data(&self) -> &[u8] {
260 &self.dry_run.exec_return_value().data
261 }
262}
263
264impl<E: Environment, V, EventLog, Abi> Debug for CallResult<E, V, EventLog, Abi>
266where
267 E: Debug,
268 E::Balance: Debug,
269 E::EventRecord: Debug,
270 V: Debug,
271 EventLog: Debug,
272{
273 fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
274 f.debug_struct("CallResult")
275 .field("dry_run", &self.dry_run)
276 .field("events", &self.events)
277 .field("trace", &self.trace)
278 .finish()
279 }
280}
281
282pub struct CallDryRunResult<E: Environment, V, Abi> {
284 pub exec_result: ContractExecResultFor<E>,
286 pub trace: Option<CallTrace>,
288 pub _marker: PhantomData<(V, Abi)>,
290}
291
292impl<E: Environment, V, Abi> Debug for CallDryRunResult<E, V, Abi>
295where
296 E::Balance: Debug,
297 E::EventRecord: Debug,
298{
299 fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
300 f.debug_struct("CallDryRunResult")
301 .field("exec_result", &self.exec_result)
302 .finish()
303 }
304}
305
306impl<E: Environment, V, Abi> CallDryRunResult<E, V, Abi> {
307 pub fn is_err(&self) -> bool {
309 self.exec_result.result.is_err() || self.did_revert()
310 }
311
312 pub fn exec_return_value(&self) -> &ExecReturnValue {
316 self.exec_result
317 .result
318 .as_ref()
319 .unwrap_or_else(|call_err| panic!("Call dry-run failed: {call_err:?}"))
320 }
321
322 pub fn did_revert(&self) -> bool {
324 let res = self.exec_result.result.clone().expect("no result found");
325 res.did_revert()
326 }
327
328 pub fn return_data(&self) -> &[u8] {
332 &self.exec_return_value().data
333 }
334}
335
336impl<E: Environment, V: DecodeMessageResult<Abi>, Abi> CallDryRunResult<E, V, Abi> {
337 pub fn message_result(&self) -> MessageResult<V> {
343 let data = &self.exec_return_value().data;
344 DecodeMessageResult::decode_output(data.as_ref(), self.did_revert()).unwrap_or_else(|env_err| {
345 panic!(
346 "Decoding dry run result to ink! message return type failed: {env_err:?} {:?}\n\n\
347 Attempt to stringify returned data: {:?}",
348 self.exec_return_value(),
349 String::from_utf8_lossy(&self.exec_return_value().data[..])
350 )
351 })
352 }
353
354 pub fn return_value(&self) -> V {
359 self.message_result()
360 .unwrap_or_else(|lang_err| {
361 panic!(
362 "Encountered a `LangError` while decoding dry run result to ink! message: {lang_err:?}"
363 )
364 })
365 }
366}
367
368#[derive(Clone)]
370pub 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() || self.did_revert()
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}