referrerpolicy=no-referrer-when-downgrade

pallet_contracts/test_utils/
builder.rs

1// This file is part of Substrate.
2
3// Copyright (C) Parity Technologies (UK) Ltd.
4// SPDX-License-Identifier: Apache-2.0
5
6// Licensed under the Apache License, Version 2.0 (the "License");
7// you may not use this file except in compliance with the License.
8// You may obtain a copy of the License at
9//
10// 	http://www.apache.org/licenses/LICENSE-2.0
11//
12// Unless required by applicable law or agreed to in writing, software
13// distributed under the License is distributed on an "AS IS" BASIS,
14// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15// See the License for the specific language governing permissions and
16// limitations under the License.
17
18use super::GAS_LIMIT;
19use crate::{
20	AccountIdLookupOf, AccountIdOf, BalanceOf, Code, CodeHash, CollectEvents, Config,
21	ContractExecResult, ContractInstantiateResult, DebugInfo, Determinism, EventRecordOf,
22	ExecReturnValue, InstantiateReturnValue, OriginFor, Pallet, Weight,
23};
24use codec::{Encode, HasCompact};
25use core::fmt::Debug;
26use frame_support::pallet_prelude::DispatchResultWithPostInfo;
27use paste::paste;
28use scale_info::TypeInfo;
29
30/// Helper macro to generate a builder for contract API calls.
31macro_rules! builder {
32	// Entry point to generate a builder for the given method.
33	(
34		$method:ident($($field:ident: $type:ty,)*) -> $result:ty;
35        $($extra:item)*
36	) => {
37		paste!{
38			builder!([< $method:camel Builder >], $method($($field: $type,)* ) -> $result; $($extra)*);
39		}
40	};
41	// Generate the builder struct and its methods.
42	(
43		$name:ident,
44		$method:ident($($field:ident: $type:ty,)*) -> $result:ty;
45        $($extra:item)*
46	) => {
47		#[doc = concat!("A builder to construct a ", stringify!($method), " call")]
48		pub struct $name<T: Config> {
49			$($field: $type,)*
50		}
51
52		#[allow(dead_code)]
53		impl<T: Config> $name<T>
54		where
55			<BalanceOf<T> as HasCompact>::Type: Clone + Eq + PartialEq + Debug + TypeInfo + Encode,
56		{
57			$(
58				#[doc = concat!("Set the ", stringify!($field))]
59				pub fn $field(mut self, value: $type) -> Self {
60					self.$field = value;
61					self
62				}
63			)*
64
65			#[doc = concat!("Build the ", stringify!($method), " call")]
66			pub fn build(self) -> $result {
67				Pallet::<T>::$method(
68					$(self.$field,)*
69				)
70			}
71
72            $($extra)*
73		}
74	}
75}
76
77builder!(
78	instantiate_with_code(
79		origin: OriginFor<T>,
80		value: BalanceOf<T>,
81		gas_limit: Weight,
82		storage_deposit_limit: Option<<BalanceOf<T> as codec::HasCompact>::Type>,
83		code: Vec<u8>,
84		data: Vec<u8>,
85		salt: Vec<u8>,
86	) -> DispatchResultWithPostInfo;
87
88	/// Create an [`InstantiateWithCodeBuilder`] with default values.
89	pub fn instantiate_with_code(origin: OriginFor<T>, code: Vec<u8>) -> Self {
90		Self {
91			origin: origin,
92			value: 0u32.into(),
93			gas_limit: GAS_LIMIT,
94			storage_deposit_limit: None,
95			code,
96			data: vec![],
97			salt: vec![],
98		}
99	}
100);
101
102builder!(
103	instantiate(
104		origin: OriginFor<T>,
105		value: BalanceOf<T>,
106		gas_limit: Weight,
107		storage_deposit_limit: Option<<BalanceOf<T> as codec::HasCompact>::Type>,
108		code_hash: CodeHash<T>,
109		data: Vec<u8>,
110		salt: Vec<u8>,
111	) -> DispatchResultWithPostInfo;
112
113	/// Create an [`InstantiateBuilder`] with default values.
114	pub fn instantiate(origin: OriginFor<T>, code_hash: CodeHash<T>) -> Self {
115		Self {
116			origin,
117			value: 0u32.into(),
118			gas_limit: GAS_LIMIT,
119			storage_deposit_limit: None,
120			code_hash,
121			data: vec![],
122			salt: vec![],
123		}
124	}
125);
126
127builder!(
128	bare_instantiate(
129		origin: AccountIdOf<T>,
130		value: BalanceOf<T>,
131		gas_limit: Weight,
132		storage_deposit_limit: Option<BalanceOf<T>>,
133		code: Code<CodeHash<T>>,
134		data: Vec<u8>,
135		salt: Vec<u8>,
136		debug: DebugInfo,
137		collect_events: CollectEvents,
138	) -> ContractInstantiateResult<AccountIdOf<T>, BalanceOf<T>, EventRecordOf<T>>;
139
140	/// Build the instantiate call and unwrap the result.
141	pub fn build_and_unwrap_result(self) -> InstantiateReturnValue<AccountIdOf<T>> {
142		self.build().result.unwrap()
143	}
144
145	/// Build the instantiate call and unwrap the account id.
146	pub fn build_and_unwrap_account_id(self) -> AccountIdOf<T> {
147		self.build().result.unwrap().account_id
148	}
149
150	pub fn bare_instantiate(origin: AccountIdOf<T>, code: Code<CodeHash<T>>) -> Self {
151		Self {
152			origin,
153			value: 0u32.into(),
154			gas_limit: GAS_LIMIT,
155			storage_deposit_limit: None,
156			code,
157			data: vec![],
158			salt: vec![],
159			debug: DebugInfo::Skip,
160			collect_events: CollectEvents::Skip,
161		}
162	}
163);
164
165builder!(
166	call(
167		origin: OriginFor<T>,
168		dest: AccountIdLookupOf<T>,
169		value: BalanceOf<T>,
170		gas_limit: Weight,
171		storage_deposit_limit: Option<<BalanceOf<T> as codec::HasCompact>::Type>,
172		data: Vec<u8>,
173	) -> DispatchResultWithPostInfo;
174
175	/// Create a [`CallBuilder`] with default values.
176	pub fn call(origin: OriginFor<T>, dest: AccountIdLookupOf<T>) -> Self {
177		CallBuilder {
178			origin,
179			dest,
180			value: 0u32.into(),
181			gas_limit: GAS_LIMIT,
182			storage_deposit_limit: None,
183			data: vec![],
184		}
185	}
186);
187
188builder!(
189	bare_call(
190		origin: AccountIdOf<T>,
191		dest: AccountIdOf<T>,
192		value: BalanceOf<T>,
193		gas_limit: Weight,
194		storage_deposit_limit: Option<BalanceOf<T>>,
195		data: Vec<u8>,
196		debug: DebugInfo,
197		collect_events: CollectEvents,
198		determinism: Determinism,
199	) -> ContractExecResult<BalanceOf<T>, EventRecordOf<T>>;
200
201	/// Build the call and unwrap the result.
202	pub fn build_and_unwrap_result(self) -> ExecReturnValue {
203		self.build().result.unwrap()
204	}
205
206	/// Create a [`BareCallBuilder`] with default values.
207	pub fn bare_call(origin: AccountIdOf<T>, dest: AccountIdOf<T>) -> Self {
208		Self {
209			origin,
210			dest,
211			value: 0u32.into(),
212			gas_limit: GAS_LIMIT,
213			storage_deposit_limit: None,
214			data: vec![],
215			debug: DebugInfo::Skip,
216			collect_events: CollectEvents::Skip,
217			determinism: Determinism::Enforced,
218		}
219	}
220);