pallet_revive/test_utils/
builder.rs1use super::{deposit_limit, ETH_GAS_LIMIT, WEIGHT_LIMIT};
19use crate::{
20 address::AddressMapper, evm::TransactionSigned, metering::TransactionLimits, AccountIdOf,
21 BalanceOf, Code, Config, ContractResult, ExecConfig, ExecReturnValue, InstantiateReturnValue,
22 OriginFor, Pallet, Weight, U256,
23};
24use alloc::{vec, vec::Vec};
25use frame_support::pallet_prelude::DispatchResultWithPostInfo;
26use paste::paste;
27use sp_core::H160;
28
29macro_rules! builder {
31 (
33 $method:ident($($field:ident: $type:ty,)*) -> $result:ty;
34 $($extra:item)*
35 ) => {
36 paste!{
37 builder!([< $method:camel Builder >], $method($($field: $type,)* ) -> $result; $($extra)*);
38 }
39 };
40 (
42 $name:ident,
43 $method:ident($($field:ident: $type:ty,)*) -> $result:ty;
44 $($extra:item)*
45 ) => {
46 #[doc = concat!("A builder to construct a ", stringify!($method), " call")]
47 pub struct $name<T: Config> {
48 $($field: $type,)*
49 }
50
51 #[allow(dead_code)]
52 impl<T: Config> $name<T> {
53 $(
54 #[doc = concat!("Set the ", stringify!($field))]
55 pub fn $field(mut self, value: $type) -> Self {
56 self.$field = value;
57 self
58 }
59 )*
60
61 #[doc = concat!("Build the ", stringify!($method), " call")]
62 pub fn build(self) -> $result {
63 Pallet::<T>::$method(
64 $(self.$field,)*
65 )
66 }
67
68 $($extra)*
69 }
70 }
71}
72
73pub struct Contract<T: Config> {
74 pub account_id: AccountIdOf<T>,
75 pub addr: H160,
76}
77
78builder!(
79 instantiate_with_code(
80 origin: OriginFor<T>,
81 value: BalanceOf<T>,
82 weight_limit: Weight,
83 storage_deposit_limit: BalanceOf<T>,
84 code: Vec<u8>,
85 data: Vec<u8>,
86 salt: Option<[u8; 32]>,
87 ) -> DispatchResultWithPostInfo;
88
89 pub fn instantiate_with_code(origin: OriginFor<T>, code: Vec<u8>) -> Self {
91 Self {
92 origin,
93 value: 0u32.into(),
94 weight_limit: WEIGHT_LIMIT,
95 storage_deposit_limit: deposit_limit::<T>(),
96 code,
97 data: vec![],
98 salt: Some([0; 32]),
99 }
100 }
101);
102
103builder!(
104 instantiate(
105 origin: OriginFor<T>,
106 value: BalanceOf<T>,
107 weight_limit: Weight,
108 storage_deposit_limit: BalanceOf<T>,
109 code_hash: sp_core::H256,
110 data: Vec<u8>,
111 salt: Option<[u8; 32]>,
112 ) -> DispatchResultWithPostInfo;
113
114 pub fn instantiate(origin: OriginFor<T>, code_hash: sp_core::H256) -> Self {
116 Self {
117 origin,
118 value: 0u32.into(),
119 weight_limit: WEIGHT_LIMIT,
120 storage_deposit_limit: deposit_limit::<T>(),
121 code_hash,
122 data: vec![],
123 salt: Some([0; 32]),
124 }
125 }
126);
127
128builder!(
129 bare_instantiate(
130 origin: OriginFor<T>,
131 evm_value: U256,
132 transaction_limits: TransactionLimits<T>,
133 code: Code,
134 data: Vec<u8>,
135 salt: Option<[u8; 32]>,
136 exec_config: ExecConfig<T>,
137 ) -> ContractResult<InstantiateReturnValue, BalanceOf<T>>;
138
139 pub fn constructor_data(mut self, data: Vec<u8>) -> Self {
140 match self.code {
141 Code::Upload(ref mut code) if !code.starts_with(&polkavm_common::program::BLOB_MAGIC) => {
142 code.extend_from_slice(&data);
143 self
144 },
145 _ => {
146 self.data(data)
147 }
148 }
149 }
150
151 pub fn native_value(mut self, value: BalanceOf<T>) -> Self {
153 self.evm_value = Pallet::<T>::convert_native_to_evm(value);
154 self
155 }
156
157 pub fn build_and_unwrap_result(self) -> InstantiateReturnValue {
159 self.build().result.unwrap()
160 }
161
162 pub fn build_and_unwrap_contract(self) -> Contract<T> {
164 let result = self.build().result.unwrap();
165 assert!(!result.result.did_revert(), "instantiation did revert");
166
167 let addr = result.addr;
168 let account_id = T::AddressMapper::to_account_id(&addr);
169 Contract{ account_id, addr }
170 }
171
172 pub fn bare_instantiate(origin: OriginFor<T>, code: Code) -> Self {
174 Self {
175 origin,
176 evm_value: Default::default(),
177 transaction_limits: TransactionLimits::WeightAndDeposit {
178 weight_limit: WEIGHT_LIMIT,
179 deposit_limit: deposit_limit::<T>()
180 },
181 code,
182 data: vec![],
183 salt: Some([0; 32]),
184 exec_config: ExecConfig::new_substrate_tx(),
185 }
186 }
187);
188
189builder!(
190 call(
191 origin: OriginFor<T>,
192 dest: H160,
193 value: BalanceOf<T>,
194 weight_limit: Weight,
195 storage_deposit_limit: BalanceOf<T>,
196 data: Vec<u8>,
197 ) -> DispatchResultWithPostInfo;
198
199 pub fn call(origin: OriginFor<T>, dest: H160) -> Self {
201 CallBuilder {
202 origin,
203 dest,
204 value: 0u32.into(),
205 weight_limit: WEIGHT_LIMIT,
206 storage_deposit_limit: deposit_limit::<T>(),
207 data: vec![],
208 }
209 }
210);
211
212builder!(
213 bare_call(
214 origin: OriginFor<T>,
215 dest: H160,
216 evm_value: U256,
217 transaction_limits: TransactionLimits<T>,
218 data: Vec<u8>,
219 exec_config: ExecConfig<T>,
220 ) -> ContractResult<ExecReturnValue, BalanceOf<T>>;
221
222 pub fn native_value(mut self, value: BalanceOf<T>) -> Self {
224 self.evm_value = Pallet::<T>::convert_native_to_evm(value);
225 self
226 }
227
228 pub fn build_and_unwrap_result(self) -> ExecReturnValue {
230 self.build().result.unwrap()
231 }
232
233 pub fn bare_call(origin: OriginFor<T>, dest: H160) -> Self {
235 Self {
236 origin,
237 dest,
238 evm_value: Default::default(),
239 transaction_limits: TransactionLimits::WeightAndDeposit {
240 weight_limit: WEIGHT_LIMIT,
241 deposit_limit: deposit_limit::<T>()
242 },
243 data: vec![],
244 exec_config: ExecConfig::new_substrate_tx(),
245 }
246 }
247);
248
249builder!(
250 eth_call(
251 origin: OriginFor<T>,
252 dest: H160,
253 value: U256,
254 weight_limit: Weight,
255 eth_gas_limit: U256,
256 data: Vec<u8>,
257 transaction_encoded: Vec<u8>,
258 effective_gas_price: U256,
259 encoded_len: u32,
260 ) -> DispatchResultWithPostInfo;
261
262 pub fn eth_call(origin: OriginFor<T>, dest: H160) -> Self {
264 Self {
265 origin,
266 dest,
267 value: 0u32.into(),
268 weight_limit: WEIGHT_LIMIT,
269 eth_gas_limit: ETH_GAS_LIMIT.into(),
270 data: vec![],
271 transaction_encoded: TransactionSigned::TransactionLegacySigned(Default::default()).signed_payload(),
272 effective_gas_price: 0u32.into(),
273 encoded_len: 0,
274 }
275 }
276);
277
278builder!(
279 eth_instantiate_with_code(
280 origin: OriginFor<T>,
281 value: U256,
282 gas_limit: Weight,
283 eth_gas_limit: U256,
284 code: Vec<u8>,
285 data: Vec<u8>,
286 transaction_encoded: Vec<u8>,
287 effective_gas_price: U256,
288 encoded_len: u32,
289 ) -> DispatchResultWithPostInfo;
290
291 pub fn eth_instantiate_with_code(origin: OriginFor<T>, code: Vec<u8>) -> Self {
293 Self {
294 origin,
295 value: 0u32.into(),
296 gas_limit: WEIGHT_LIMIT,
297 eth_gas_limit: ETH_GAS_LIMIT.into(),
298 code,
299 data: vec![],
300 transaction_encoded: TransactionSigned::Transaction4844Signed(Default::default()).signed_payload(),
301 effective_gas_price: 0u32.into(),
302 encoded_len: 0,
303 }
304 }
305);