pallet_revive/test_utils/
builder.rs1use super::{deposit_limit, GAS_LIMIT};
19use crate::{
20 address::AddressMapper, AccountIdOf, BalanceOf, BumpNonce, Code, Config, ContractResult,
21 DepositLimit, ExecReturnValue, InstantiateReturnValue, OriginFor, Pallet, Weight, U256,
22};
23use alloc::{vec, vec::Vec};
24use frame_support::pallet_prelude::DispatchResultWithPostInfo;
25use paste::paste;
26use sp_core::H160;
27
28macro_rules! builder {
30 (
32 $method:ident($($field:ident: $type:ty,)*) -> $result:ty;
33 $($extra:item)*
34 ) => {
35 paste!{
36 builder!([< $method:camel Builder >], $method($($field: $type,)* ) -> $result; $($extra)*);
37 }
38 };
39 (
41 $name:ident,
42 $method:ident($($field:ident: $type:ty,)*) -> $result:ty;
43 $($extra:item)*
44 ) => {
45 #[doc = concat!("A builder to construct a ", stringify!($method), " call")]
46 pub struct $name<T: Config> {
47 $($field: $type,)*
48 }
49
50 #[allow(dead_code)]
51 impl<T: Config> $name<T>
52 where
53 BalanceOf<T>: Into<sp_core::U256> + TryFrom<sp_core::U256>,
54 crate::MomentOf<T>: Into<sp_core::U256>,
55 T::Hash: frame_support::traits::IsType<sp_core::H256>,
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
77pub struct Contract<T: Config> {
78 pub account_id: AccountIdOf<T>,
79 pub addr: H160,
80}
81
82builder!(
83 instantiate_with_code(
84 origin: OriginFor<T>,
85 value: BalanceOf<T>,
86 gas_limit: Weight,
87 storage_deposit_limit: BalanceOf<T>,
88 code: Vec<u8>,
89 data: Vec<u8>,
90 salt: Option<[u8; 32]>,
91 ) -> DispatchResultWithPostInfo;
92
93 pub fn instantiate_with_code(origin: OriginFor<T>, code: Vec<u8>) -> Self {
95 Self {
96 origin,
97 value: 0u32.into(),
98 gas_limit: GAS_LIMIT,
99 storage_deposit_limit: deposit_limit::<T>(),
100 code,
101 data: vec![],
102 salt: Some([0; 32]),
103 }
104 }
105);
106
107builder!(
108 instantiate(
109 origin: OriginFor<T>,
110 value: BalanceOf<T>,
111 gas_limit: Weight,
112 storage_deposit_limit: BalanceOf<T>,
113 code_hash: sp_core::H256,
114 data: Vec<u8>,
115 salt: Option<[u8; 32]>,
116 ) -> DispatchResultWithPostInfo;
117
118 pub fn instantiate(origin: OriginFor<T>, code_hash: sp_core::H256) -> Self {
120 Self {
121 origin,
122 value: 0u32.into(),
123 gas_limit: GAS_LIMIT,
124 storage_deposit_limit: deposit_limit::<T>(),
125 code_hash,
126 data: vec![],
127 salt: Some([0; 32]),
128 }
129 }
130);
131
132builder!(
133 bare_instantiate(
134 origin: OriginFor<T>,
135 evm_value: U256,
136 gas_limit: Weight,
137 storage_deposit_limit: DepositLimit<BalanceOf<T>>,
138 code: Code,
139 data: Vec<u8>,
140 salt: Option<[u8; 32]>,
141 bump_nonce: BumpNonce,
142 ) -> ContractResult<InstantiateReturnValue, BalanceOf<T>>;
143
144 pub fn concat_evm_data(mut self, more_data: &[u8]) -> Self {
145 let Code::Upload(code) = &mut self.code else {
146 panic!("concat_evm_data should only be used with Code::Upload");
147 };
148 code.extend_from_slice(more_data);
149 self
150 }
151
152 pub fn native_value(mut self, value: BalanceOf<T>) -> Self {
154 self.evm_value = Pallet::<T>::convert_native_to_evm(value);
155 self
156 }
157
158 pub fn build_and_unwrap_result(self) -> InstantiateReturnValue {
160 self.build().result.unwrap()
161 }
162
163 pub fn build_and_unwrap_contract(self) -> Contract<T> {
165 let result = self.build().result.unwrap();
166 assert!(!result.result.did_revert(), "instantiation did revert");
167
168 let addr = result.addr;
169 let account_id = T::AddressMapper::to_account_id(&addr);
170 Contract{ account_id, addr }
171 }
172
173 pub fn bare_instantiate(origin: OriginFor<T>, code: Code) -> Self {
175 Self {
176 origin,
177 evm_value: Default::default(),
178 gas_limit: GAS_LIMIT,
179 storage_deposit_limit: DepositLimit::Balance(deposit_limit::<T>()),
180 code,
181 data: vec![],
182 salt: Some([0; 32]),
183 bump_nonce: BumpNonce::Yes,
184 }
185 }
186);
187
188builder!(
189 call(
190 origin: OriginFor<T>,
191 dest: H160,
192 value: BalanceOf<T>,
193 gas_limit: Weight,
194 storage_deposit_limit: BalanceOf<T>,
195 data: Vec<u8>,
196 ) -> DispatchResultWithPostInfo;
197
198 pub fn call(origin: OriginFor<T>, dest: H160) -> Self {
200 CallBuilder {
201 origin,
202 dest,
203 value: 0u32.into(),
204 gas_limit: GAS_LIMIT,
205 storage_deposit_limit: deposit_limit::<T>(),
206 data: vec![],
207 }
208 }
209);
210
211builder!(
212 bare_call(
213 origin: OriginFor<T>,
214 dest: H160,
215 evm_value: U256,
216 gas_limit: Weight,
217 storage_deposit_limit: DepositLimit<BalanceOf<T>>,
218 data: Vec<u8>,
219 ) -> ContractResult<ExecReturnValue, BalanceOf<T>>;
220
221 pub fn native_value(mut self, value: BalanceOf<T>) -> Self {
223 self.evm_value = Pallet::<T>::convert_native_to_evm(value);
224 self
225 }
226
227 pub fn build_and_unwrap_result(self) -> ExecReturnValue {
229 self.build().result.unwrap()
230 }
231
232 pub fn bare_call(origin: OriginFor<T>, dest: H160) -> Self {
234 Self {
235 origin,
236 dest,
237 evm_value: Default::default(),
238 gas_limit: GAS_LIMIT,
239 storage_deposit_limit: DepositLimit::Balance(deposit_limit::<T>()),
240 data: vec![],
241 }
242 }
243);
244
245builder!(
246 eth_call(
247 origin: OriginFor<T>,
248 dest: H160,
249 value: U256,
250 gas_limit: Weight,
251 storage_deposit_limit: BalanceOf<T>,
252 data: Vec<u8>,
253 ) -> DispatchResultWithPostInfo;
254
255 pub fn eth_call(origin: OriginFor<T>, dest: H160) -> Self {
257 Self {
258 origin,
259 dest,
260 value: 0u32.into(),
261 gas_limit: GAS_LIMIT,
262 storage_deposit_limit: deposit_limit::<T>(),
263 data: vec![],
264 }
265 }
266);