hiero_sdk/contract/
contract_function_parameters.rs

1use std::cmp::max;
2use std::str::FromStr;
3
4use num_bigint::{
5    BigInt,
6    BigUint,
7    Sign,
8};
9
10use self::private::Sealed;
11use crate::contract::contract_function_selector::ContractFunctionSelector;
12use crate::ethereum::SolidityAddress;
13
14/// Builder for encoding parameters for a Solidity contract constructor/function call.
15#[derive(Debug, Clone, Default)]
16pub struct ContractFunctionParameters {
17    args: Vec<Argument>,
18}
19
20#[derive(Debug, Clone)]
21struct Argument {
22    type_name: &'static str,
23    value_bytes: Vec<u8>,
24    is_dynamic: bool,
25}
26
27mod private {
28    pub trait Sealed {}
29    impl Sealed for String {}
30    impl Sealed for str {}
31    impl Sealed for [u8; 32] {}
32}
33
34pub trait AsBytes32: Sealed {
35    fn as_bytes32(&self) -> &[u8];
36}
37
38impl<T: Sealed + AsRef<[u8]> + ?Sized> AsBytes32 for T {
39    fn as_bytes32(&self) -> &[u8] {
40        self.as_ref()
41    }
42}
43
44trait IntEncode {
45    fn get_is_negative_and_be_bytes(&self) -> (bool, Vec<u8>);
46}
47
48impl IntEncode for u8 {
49    fn get_is_negative_and_be_bytes(&self) -> (bool, Vec<u8>) {
50        (false, self.to_be_bytes().to_vec())
51    }
52}
53
54impl IntEncode for i8 {
55    fn get_is_negative_and_be_bytes(&self) -> (bool, Vec<u8>) {
56        (self.is_negative(), self.to_be_bytes().to_vec())
57    }
58}
59
60impl IntEncode for u16 {
61    fn get_is_negative_and_be_bytes(&self) -> (bool, Vec<u8>) {
62        (false, self.to_be_bytes().to_vec())
63    }
64}
65
66impl IntEncode for i16 {
67    fn get_is_negative_and_be_bytes(&self) -> (bool, Vec<u8>) {
68        (self.is_negative(), self.to_be_bytes().to_vec())
69    }
70}
71
72impl IntEncode for u32 {
73    fn get_is_negative_and_be_bytes(&self) -> (bool, Vec<u8>) {
74        (false, self.to_be_bytes().to_vec())
75    }
76}
77
78impl IntEncode for i32 {
79    fn get_is_negative_and_be_bytes(&self) -> (bool, Vec<u8>) {
80        (self.is_negative(), self.to_be_bytes().to_vec())
81    }
82}
83
84impl IntEncode for u64 {
85    fn get_is_negative_and_be_bytes(&self) -> (bool, Vec<u8>) {
86        (false, self.to_be_bytes().to_vec())
87    }
88}
89
90impl IntEncode for i64 {
91    fn get_is_negative_and_be_bytes(&self) -> (bool, Vec<u8>) {
92        (self.is_negative(), self.to_be_bytes().to_vec())
93    }
94}
95
96impl IntEncode for u128 {
97    fn get_is_negative_and_be_bytes(&self) -> (bool, Vec<u8>) {
98        (false, self.to_be_bytes().to_vec())
99    }
100}
101
102impl IntEncode for i128 {
103    fn get_is_negative_and_be_bytes(&self) -> (bool, Vec<u8>) {
104        (self.is_negative(), self.to_be_bytes().to_vec())
105    }
106}
107
108impl IntEncode for BigUint {
109    fn get_is_negative_and_be_bytes(&self) -> (bool, Vec<u8>) {
110        (false, self.to_bytes_be())
111    }
112}
113
114impl IntEncode for BigInt {
115    fn get_is_negative_and_be_bytes(&self) -> (bool, Vec<u8>) {
116        (self.sign() == Sign::Minus, self.to_signed_bytes_be())
117    }
118}
119
120// todo: remove this
121#[allow(clippy::needless_pass_by_value)]
122impl ContractFunctionParameters {
123    /// Create a new, empty `ContractFunctionParameters`
124    #[must_use]
125    pub fn new() -> Self {
126        Self::default()
127    }
128
129    /// Returns the encoding of the currently added parameters as bytes.
130    ///
131    /// You can continue adding arguments after calling this function.
132    // passing an `&Option<A>` or an `Option<&A>` would just be pointlessly more restrictive,
133    // since downstream code can just...
134    // Call this with `Option<&A>` anyway if they want to keep ownership of it.
135    pub fn to_bytes(&self, func_name: Option<&str>) -> Vec<u8> {
136        let mut current_dynamic_offset = self.args.len() * 32;
137        let mut arg_bytes = Vec::new();
138        let mut dynamic_arg_bytes = Vec::new();
139        let mut function_selector = func_name.map(ContractFunctionSelector::new);
140        for arg in &self.args {
141            if let Some(selector) = &mut function_selector {
142                selector.add_param_type(arg.type_name);
143            }
144            if arg.is_dynamic {
145                arg_bytes.extend_from_slice(
146                    left_pad_32_bytes(current_dynamic_offset.to_be_bytes().as_slice(), false)
147                        .as_slice(),
148                );
149                dynamic_arg_bytes.extend_from_slice(arg.value_bytes.as_slice());
150                current_dynamic_offset += arg.value_bytes.len();
151            } else {
152                arg_bytes.extend_from_slice(arg.value_bytes.as_slice());
153            }
154        }
155
156        arg_bytes.append(&mut dynamic_arg_bytes);
157
158        if let Some(selector) = &mut function_selector {
159            let mut out_bytes = Vec::from(selector.finish());
160            out_bytes.append(&mut arg_bytes);
161            out_bytes
162        } else {
163            arg_bytes
164        }
165    }
166
167    /// Add a `string` argument to the `ContractFunctionParameters`
168    pub fn add_string<T: AsRef<str>>(&mut self, val: T) -> &mut Self {
169        self.args.push(Argument {
170            type_name: "string",
171            value_bytes: encode_dynamic_bytes(val.as_ref().as_bytes()),
172            is_dynamic: true,
173        });
174        self
175    }
176
177    /// Add a `string[]` argument to the `ContractFunctionParameters`
178    pub fn add_string_array<T: AsRef<str>>(&mut self, val: &[T]) -> &mut Self {
179        self.args.push(Argument {
180            type_name: "string[]",
181            value_bytes: encode_array_of_dynamic_byte_arrays(
182                val.iter().map(|s| s.as_ref().as_bytes()),
183                val.len(),
184            ),
185            is_dynamic: true,
186        });
187        self
188    }
189
190    /// Add a `bytes` argument to the `ContractFunctionParameters`
191    pub fn add_bytes(&mut self, val: &[u8]) -> &mut Self {
192        self.args.push(Argument {
193            type_name: "bytes",
194            value_bytes: encode_dynamic_bytes(val),
195            is_dynamic: true,
196        });
197        self
198    }
199
200    /// Add a `bytes[]` argument to the `ContractFunctionParameters`
201    pub fn add_bytes_array(&mut self, val: &[&[u8]]) -> &mut Self {
202        self.args.push(Argument {
203            type_name: "bytes[]",
204            value_bytes: encode_array_of_dynamic_byte_arrays(val, val.len()),
205            is_dynamic: true,
206        });
207        self
208    }
209
210    /// Add a `bytes32` argument to the `ContractFunctionParameters`
211    pub fn add_bytes32<T: AsBytes32 + ?Sized>(&mut self, val: &T) -> &mut Self {
212        self.args.push(Argument {
213            type_name: "bytes32",
214            value_bytes: encode_array_of_32_byte(val),
215            is_dynamic: false,
216        });
217        self
218    }
219
220    /// Add a `bytes32[]` argument to the `ContractFunctionParameters`
221    pub fn add_bytes32_array(&mut self, val: &[[u8; 32]]) -> &mut Self {
222        self.args.push(Argument {
223            type_name: "bytes32",
224            value_bytes: encode_array_of_32_byte_elements(val.iter().copied(), val.len()),
225            is_dynamic: true,
226        });
227        self
228    }
229
230    /// Add a `bool` argument to the `ContractFunctionParameters`
231    pub fn add_bool(&mut self, val: bool) -> &mut Self {
232        self.args.push(Argument {
233            type_name: "bool",
234            value_bytes: left_pad_32_bytes(
235                // a bool in rust is guaranteed to be of value 0 or 1
236                u32::from(val).to_be_bytes().as_slice(),
237                false,
238            )
239            .to_vec(),
240            is_dynamic: false,
241        });
242        self
243    }
244
245    fn add_int<T>(&mut self, val: &T, type_name: &'static str, byte_count: isize) -> &mut Self
246    where
247        T: IntEncode,
248    {
249        self.args.push(Argument {
250            type_name,
251            value_bytes: truncate_and_left_pad_32_bytes(val, byte_count).to_vec(),
252            is_dynamic: false,
253        });
254        self
255    }
256
257    fn add_int_array<T>(
258        &mut self,
259        values: &[T],
260        type_name: &'static str,
261        byte_count: isize,
262    ) -> &mut Self
263    where
264        T: IntEncode,
265    {
266        self.args.push(Argument {
267            type_name,
268            value_bytes: encode_array_of_32_byte_elements(
269                values.iter().map(|val| truncate_and_left_pad_32_bytes(val, byte_count)),
270                values.len(),
271            ),
272            is_dynamic: true,
273        });
274        self
275    }
276
277    /// Add an `int8` argument to the `ContractFunctionParameters`
278    pub fn add_int8(&mut self, val: i8) -> &mut Self {
279        self.add_int(&val, "int8", 1)
280    }
281
282    /// Add an `int16` argument to the `ContractFunctionParameters`
283    pub fn add_int16(&mut self, val: i16) -> &mut Self {
284        self.add_int(&val, "int16", 2)
285    }
286
287    /// Add an `int24` argument to the `ContractFunctionParameters`
288    pub fn add_int24(&mut self, val: i32) -> &mut Self {
289        self.add_int(&val, "int24", 3)
290    }
291
292    /// Add an `int32` argument to the `ContractFunctionParameters`
293    pub fn add_int32(&mut self, val: i32) -> &mut Self {
294        self.add_int(&val, "int32", 4)
295    }
296
297    /// Add an `int40` argument to the `ContractFunctionParameters`
298    pub fn add_int40(&mut self, val: i64) -> &mut Self {
299        self.add_int(&val, "int40", 5)
300    }
301
302    /// Add an `int48` argument to the `ContractFunctionParameters`
303    pub fn add_int48(&mut self, val: i64) -> &mut Self {
304        self.add_int(&val, "int48", 6)
305    }
306
307    /// Add an `int56` argument to the `ContractFunctionParameters`
308    pub fn add_int56(&mut self, val: i64) -> &mut Self {
309        self.add_int(&val, "int56", 7)
310    }
311
312    /// Add an `int64` argument to the `ContractFunctionParameters`
313    pub fn add_int64(&mut self, val: i64) -> &mut Self {
314        self.add_int(&val, "int64", 8)
315    }
316
317    /// Add an `int72` argument to the `ContractFunctionParameters`
318    pub fn add_int72(&mut self, val: i128) -> &mut Self {
319        self.add_int(&val, "int72", 9)
320    }
321
322    /// Add an `int80` argument to the `ContractFunctionParameters`
323    pub fn add_int80(&mut self, val: i128) -> &mut Self {
324        self.add_int(&val, "int80", 10)
325    }
326
327    /// Add an `int88` argument to the `ContractFunctionParameters`
328    pub fn add_int88(&mut self, val: i128) -> &mut Self {
329        self.add_int(&val, "int88", 11)
330    }
331
332    /// Add an `int96` argument to the `ContractFunctionParameters`
333    pub fn add_int96(&mut self, val: i128) -> &mut Self {
334        self.add_int(&val, "int96", 12)
335    }
336
337    /// Add an `int104` argument to the `ContractFunctionParameters`
338    pub fn add_int104(&mut self, val: i128) -> &mut Self {
339        self.add_int(&val, "int104", 13)
340    }
341
342    /// Add an `int112` argument to the `ContractFunctionParameters`
343    pub fn add_int112(&mut self, val: i128) -> &mut Self {
344        self.add_int(&val, "int112", 14)
345    }
346
347    /// Add an `int120` argument to the `ContractFunctionParameters`
348    pub fn add_int120(&mut self, val: i128) -> &mut Self {
349        self.add_int(&val, "int120", 15)
350    }
351
352    /// Add an `int128` argument to the `ContractFunctionParameters`
353    pub fn add_int128(&mut self, val: i128) -> &mut Self {
354        self.add_int(&val, "int128", 16)
355    }
356
357    /// Add an `int136` argument to the `ContractFunctionParameters`
358    pub fn add_int136(&mut self, val: BigInt) -> &mut Self {
359        self.add_int(&val, "int136", 17)
360    }
361
362    /// Add an `int144` argument to the `ContractFunctionParameters`
363    pub fn add_int144(&mut self, val: BigInt) -> &mut Self {
364        self.add_int(&val, "int144", 18)
365    }
366
367    /// Add an `int152` argument to the `ContractFunctionParameters`
368    pub fn add_int152(&mut self, val: BigInt) -> &mut Self {
369        self.add_int(&val, "int152", 19)
370    }
371
372    /// Add an `int160` argument to the `ContractFunctionParameters`
373    pub fn add_int160(&mut self, val: BigInt) -> &mut Self {
374        self.add_int(&val, "int160", 20)
375    }
376
377    /// Add an `int168` argument to the `ContractFunctionParameters`
378    pub fn add_int168(&mut self, val: BigInt) -> &mut Self {
379        self.add_int(&val, "int168", 21)
380    }
381
382    /// Add an `int176` argument to the `ContractFunctionParameters`
383    pub fn add_int176(&mut self, val: BigInt) -> &mut Self {
384        self.add_int(&val, "int176", 22)
385    }
386
387    /// Add an `int184` argument to the `ContractFunctionParameters`
388    pub fn add_int184(&mut self, val: BigInt) -> &mut Self {
389        self.add_int(&val, "int184", 23)
390    }
391
392    /// Add an `int192` argument to the `ContractFunctionParameters`
393    pub fn add_int192(&mut self, val: BigInt) -> &mut Self {
394        self.add_int(&val, "int192", 24)
395    }
396
397    /// Add an `int200` argument to the `ContractFunctionParameters`
398    pub fn add_int200(&mut self, val: BigInt) -> &mut Self {
399        self.add_int(&val, "int200", 25)
400    }
401
402    /// Add an `int208` argument to the `ContractFunctionParameters`
403    pub fn add_int208(&mut self, val: BigInt) -> &mut Self {
404        self.add_int(&val, "int208", 26)
405    }
406
407    /// Add an `int216` argument to the `ContractFunctionParameters`
408    pub fn add_int216(&mut self, val: BigInt) -> &mut Self {
409        self.add_int(&val, "int216", 27)
410    }
411
412    /// Add an `int224` argument to the `ContractFunctionParameters`
413    pub fn add_int224(&mut self, val: BigInt) -> &mut Self {
414        self.add_int(&val, "int224", 28)
415    }
416
417    /// Add an `int232` argument to the `ContractFunctionParameters`
418    pub fn add_int232(&mut self, val: BigInt) -> &mut Self {
419        self.add_int(&val, "int232", 29)
420    }
421
422    /// Add an `int240` argument to the `ContractFunctionParameters`
423    pub fn add_int240(&mut self, val: BigInt) -> &mut Self {
424        self.add_int(&val, "int240", 30)
425    }
426
427    /// Add an `int248` argument to the `ContractFunctionParameters`
428    pub fn add_int248(&mut self, val: BigInt) -> &mut Self {
429        self.add_int(&val, "int248", 31)
430    }
431
432    /// Add an `int256` argument to the `ContractFunctionParameters`
433    pub fn add_int256(&mut self, val: BigInt) -> &mut Self {
434        self.add_int(&val, "int256", 32)
435    }
436
437    /// Add an `int8[]` argument to the `ContractFunctionParameters`
438    pub fn add_int8_array(&mut self, values: &[i8]) -> &mut Self {
439        self.add_int_array(values, "int8[]", 1)
440    }
441
442    /// Add an `int16[]` argument to the `ContractFunctionParameters`
443    pub fn add_int16_array(&mut self, values: &[i16]) -> &mut Self {
444        self.add_int_array(values, "int16[]", 2)
445    }
446
447    /// Add an `int24[]` argument to the `ContractFunctionParameters`
448    pub fn add_int24_array(&mut self, values: &[i32]) -> &mut Self {
449        self.add_int_array(values, "int24[]", 3)
450    }
451
452    /// Add an `int32[]` argument to the `ContractFunctionParameters`
453    pub fn add_int32_array(&mut self, values: &[i32]) -> &mut Self {
454        self.add_int_array(values, "int32[]", 4)
455    }
456
457    /// Add an `int40[]` argument to the `ContractFunctionParameters`
458    pub fn add_int40_array(&mut self, values: &[i64]) -> &mut Self {
459        self.add_int_array(values, "int40[]", 5)
460    }
461
462    /// Add an `int48[]` argument to the `ContractFunctionParameters`
463    pub fn add_int48_array(&mut self, values: &[i64]) -> &mut Self {
464        self.add_int_array(values, "int48[]", 6)
465    }
466
467    /// Add an `int56[]` argument to the `ContractFunctionParameters`
468    pub fn add_int56_array(&mut self, values: &[i64]) -> &mut Self {
469        self.add_int_array(values, "int56[]", 7)
470    }
471
472    /// Add an `int64[]` argument to the `ContractFunctionParameters`
473    pub fn add_int64_array(&mut self, values: &[i64]) -> &mut Self {
474        self.add_int_array(values, "int64[]", 8)
475    }
476
477    /// Add an `int72[]` argument to the `ContractFunctionParameters`
478    pub fn add_int72_array(&mut self, values: &[i128]) -> &mut Self {
479        self.add_int_array(values, "int72[]", 9)
480    }
481
482    /// Add an `int80[]` argument to the `ContractFunctionParameters`
483    pub fn add_int80_array(&mut self, values: &[i128]) -> &mut Self {
484        self.add_int_array(values, "int80[]", 10)
485    }
486
487    /// Add an `int88[]` argument to the `ContractFunctionParameters`
488    pub fn add_int88_array(&mut self, values: &[i128]) -> &mut Self {
489        self.add_int_array(values, "int88[]", 11)
490    }
491
492    /// Add an `int96[]` argument to the `ContractFunctionParameters`
493    pub fn add_int96_array(&mut self, values: &[i128]) -> &mut Self {
494        self.add_int_array(values, "int96[]", 12)
495    }
496
497    /// Add an `int104[]` argument to the `ContractFunctionParameters`
498    pub fn add_int104_array(&mut self, values: &[i128]) -> &mut Self {
499        self.add_int_array(values, "int104[]", 13)
500    }
501
502    /// Add an `int112[]` argument to the `ContractFunctionParameters`
503    pub fn add_int112_array(&mut self, values: &[i128]) -> &mut Self {
504        self.add_int_array(values, "int112[]", 14)
505    }
506
507    /// Add an `int120[]` argument to the `ContractFunctionParameters`
508    pub fn add_int120_array(&mut self, values: &[i128]) -> &mut Self {
509        self.add_int_array(values, "int120[]", 15)
510    }
511
512    /// Add an `int128[]` argument to the `ContractFunctionParameters`
513    pub fn add_int128_array(&mut self, values: &[i128]) -> &mut Self {
514        self.add_int_array(values, "int128[]", 16)
515    }
516
517    /// Add an `int136[]` argument to the `ContractFunctionParameters`
518    pub fn add_int136_array(&mut self, values: &[BigInt]) -> &mut Self {
519        self.add_int_array(values, "int136[]", 17)
520    }
521
522    /// Add an `int144[]` argument to the `ContractFunctionParameters`
523    pub fn add_int144_array(&mut self, values: &[BigInt]) -> &mut Self {
524        self.add_int_array(values, "int144[]", 18)
525    }
526
527    /// Add an `int152[]` argument to the `ContractFunctionParameters`
528    pub fn add_int152_array(&mut self, values: &[BigInt]) -> &mut Self {
529        self.add_int_array(values, "int152[]", 19)
530    }
531
532    /// Add an `int160[]` argument to the `ContractFunctionParameters`
533    pub fn add_int160_array(&mut self, values: &[BigInt]) -> &mut Self {
534        self.add_int_array(values, "int160[]", 20)
535    }
536
537    /// Add an `int168[]` argument to the `ContractFunctionParameters`
538    pub fn add_int168_array(&mut self, values: &[BigInt]) -> &mut Self {
539        self.add_int_array(values, "int168[]", 21)
540    }
541
542    /// Add an `int176[]` argument to the `ContractFunctionParameters`
543    pub fn add_int176_array(&mut self, values: &[BigInt]) -> &mut Self {
544        self.add_int_array(values, "int176[]", 22)
545    }
546
547    /// Add an `int184[]` argument to the `ContractFunctionParameters`
548    pub fn add_int184_array(&mut self, values: &[BigInt]) -> &mut Self {
549        self.add_int_array(values, "int184[]", 23)
550    }
551
552    /// Add an `int192[]` argument to the `ContractFunctionParameters`
553    pub fn add_int192_array(&mut self, values: &[BigInt]) -> &mut Self {
554        self.add_int_array(values, "int192[]", 24)
555    }
556
557    /// Add an `int200[]` argument to the `ContractFunctionParameters`
558    pub fn add_int200_array(&mut self, values: &[BigInt]) -> &mut Self {
559        self.add_int_array(values, "int200[]", 25)
560    }
561
562    /// Add an `int208[]` argument to the `ContractFunctionParameters`
563    pub fn add_int208_array(&mut self, values: &[BigInt]) -> &mut Self {
564        self.add_int_array(values, "int208[]", 26)
565    }
566
567    /// Add an `int216[]` argument to the `ContractFunctionParameters`
568    pub fn add_int216_array(&mut self, values: &[BigInt]) -> &mut Self {
569        self.add_int_array(values, "int216[]", 27)
570    }
571
572    /// Add an `int224[]` argument to the `ContractFunctionParameters`
573    pub fn add_int224_array(&mut self, values: &[BigInt]) -> &mut Self {
574        self.add_int_array(values, "int224[]", 28)
575    }
576
577    /// Add an `int232[]` argument to the `ContractFunctionParameters`
578    pub fn add_int232_array(&mut self, values: &[BigInt]) -> &mut Self {
579        self.add_int_array(values, "int232[]", 29)
580    }
581
582    /// Add an `int240[]` argument to the `ContractFunctionParameters`
583    pub fn add_int240_array(&mut self, values: &[BigInt]) -> &mut Self {
584        self.add_int_array(values, "int240[]", 30)
585    }
586
587    /// Add an `int248[]` argument to the `ContractFunctionParameters`
588    pub fn add_int248_array(&mut self, values: &[BigInt]) -> &mut Self {
589        self.add_int_array(values, "int248[]", 31)
590    }
591
592    /// Add an `int256[]` argument to the `ContractFunctionParameters`
593    pub fn add_int256_array(&mut self, values: &[BigInt]) -> &mut Self {
594        self.add_int_array(values, "int256[]", 32)
595    }
596
597    /// Add a `uint8` argument to the `ContractFunctionParameters`
598    pub fn add_uint8(&mut self, val: u8) -> &mut Self {
599        self.add_int(&val, "uint8", 1)
600    }
601
602    /// Add a `uint16` argument to the `ContractFunctionParameters`
603    pub fn add_uint16(&mut self, val: u16) -> &mut Self {
604        self.add_int(&val, "uint16", 2)
605    }
606
607    /// Add a `uint24` argument to the `ContractFunctionParameters`
608    pub fn add_uint24(&mut self, val: u32) -> &mut Self {
609        self.add_int(&val, "uint24", 3)
610    }
611
612    /// Add a `uint32` argument to the `ContractFunctionParameters`
613    pub fn add_uint32(&mut self, val: u32) -> &mut Self {
614        self.add_int(&val, "uint32", 4)
615    }
616
617    /// Add a `uint40` argument to the `ContractFunctionParameters`
618    pub fn add_uint40(&mut self, val: u64) -> &mut Self {
619        self.add_int(&val, "uint40", 5)
620    }
621
622    /// Add a `uint48` argument to the `ContractFunctionParameters`
623    pub fn add_uint48(&mut self, val: u64) -> &mut Self {
624        self.add_int(&val, "uint48", 6)
625    }
626
627    /// Add a `uint56` argument to the `ContractFunctionParameters`
628    pub fn add_uint56(&mut self, val: u64) -> &mut Self {
629        self.add_int(&val, "uint56", 7)
630    }
631
632    /// Add a `uint64` argument to the `ContractFunctionParameters`
633    pub fn add_uint64(&mut self, val: u64) -> &mut Self {
634        self.add_int(&val, "uint64", 8)
635    }
636
637    /// Add a `uint72` argument to the `ContractFunctionParameters`
638    pub fn add_uint72(&mut self, val: u128) -> &mut Self {
639        self.add_int(&val, "uint72", 9)
640    }
641
642    /// Add a `uint80` argument to the `ContractFunctionParameters`
643    pub fn add_uint80(&mut self, val: u128) -> &mut Self {
644        self.add_int(&val, "uint80", 10)
645    }
646
647    /// Add a `uint88` argument to the `ContractFunctionParameters`
648    pub fn add_uint88(&mut self, val: u128) -> &mut Self {
649        self.add_int(&val, "uint88", 11)
650    }
651
652    /// Add a `uint96` argument to the `ContractFunctionParameters`
653    pub fn add_uint96(&mut self, val: u128) -> &mut Self {
654        self.add_int(&val, "uint96", 12)
655    }
656
657    /// Add a `uint104` argument to the `ContractFunctionParameters`
658    pub fn add_uint104(&mut self, val: u128) -> &mut Self {
659        self.add_int(&val, "uint104", 13)
660    }
661
662    /// Add a `uint112` argument to the `ContractFunctionParameters`
663    pub fn add_uint112(&mut self, val: u128) -> &mut Self {
664        self.add_int(&val, "uint112", 14)
665    }
666
667    /// Add a `uint120` argument to the `ContractFunctionParameters`
668    pub fn add_uint120(&mut self, val: u128) -> &mut Self {
669        self.add_int(&val, "uint120", 15)
670    }
671
672    /// Add a `uint128` argument to the `ContractFunctionParameters`
673    pub fn add_uint128(&mut self, val: u128) -> &mut Self {
674        self.add_int(&val, "uint128", 16)
675    }
676
677    /// Add a `uint136` argument to the `ContractFunctionParameters`
678    pub fn add_uint136(&mut self, val: BigUint) -> &mut Self {
679        self.add_int(&val, "uint136", 17)
680    }
681
682    /// Add a `uint144` argument to the `ContractFunctionParameters`
683    pub fn add_uint144(&mut self, val: BigUint) -> &mut Self {
684        self.add_int(&val, "uint144", 18)
685    }
686
687    /// Add a `uint152` argument to the `ContractFunctionParameters`
688    pub fn add_uint152(&mut self, val: BigUint) -> &mut Self {
689        self.add_int(&val, "uint152", 19)
690    }
691
692    /// Add a `uint160` argument to the `ContractFunctionParameters`
693    pub fn add_uint160(&mut self, val: BigUint) -> &mut Self {
694        self.add_int(&val, "uint160", 20)
695    }
696
697    /// Add a `uint168` argument to the `ContractFunctionParameters`
698    pub fn add_uint168(&mut self, val: BigUint) -> &mut Self {
699        self.add_int(&val, "uint168", 21)
700    }
701
702    /// Add a `uint176` argument to the `ContractFunctionParameters`
703    pub fn add_uint176(&mut self, val: BigUint) -> &mut Self {
704        self.add_int(&val, "uint176", 22)
705    }
706
707    /// Add a `uint184` argument to the `ContractFunctionParameters`
708    pub fn add_uint184(&mut self, val: BigUint) -> &mut Self {
709        self.add_int(&val, "uint184", 23)
710    }
711
712    /// Add a `uint192` argument to the `ContractFunctionParameters`
713    pub fn add_uint192(&mut self, val: BigUint) -> &mut Self {
714        self.add_int(&val, "uint192", 24)
715    }
716
717    /// Add a `uint200` argument to the `ContractFunctionParameters`
718    pub fn add_uint200(&mut self, val: BigUint) -> &mut Self {
719        self.add_int(&val, "uint200", 25)
720    }
721
722    /// Add a `uint208` argument to the `ContractFunctionParameters`
723    pub fn add_uint208(&mut self, val: BigUint) -> &mut Self {
724        self.add_int(&val, "uint208", 26)
725    }
726
727    /// Add a `uint216` argument to the `ContractFunctionParameters`
728    pub fn add_uint216(&mut self, val: BigUint) -> &mut Self {
729        self.add_int(&val, "uint216", 27)
730    }
731
732    /// Add a `uint224` argument to the `ContractFunctionParameters`
733    pub fn add_uint224(&mut self, val: BigUint) -> &mut Self {
734        self.add_int(&val, "uint224", 28)
735    }
736
737    /// Add a `uint232` argument to the `ContractFunctionParameters`
738    pub fn add_uint232(&mut self, val: BigUint) -> &mut Self {
739        self.add_int(&val, "uint232", 29)
740    }
741
742    /// Add a `uint240` argument to the `ContractFunctionParameters`
743    pub fn add_uint240(&mut self, val: BigUint) -> &mut Self {
744        self.add_int(&val, "uint240", 30)
745    }
746
747    /// Add a `uint248` argument to the `ContractFunctionParameters`
748    pub fn add_uint248(&mut self, val: BigUint) -> &mut Self {
749        self.add_int(&val, "uint248", 31)
750    }
751
752    /// Add a `uint256` argument to the `ContractFunctionParameters`
753    pub fn add_uint256(&mut self, val: BigUint) -> &mut Self {
754        self.add_int(&val, "uint256", 32)
755    }
756
757    /// Add a `uint8[]` argument to the `ContractFunctionParameters`
758    pub fn add_uint8_array(&mut self, values: &[u8]) -> &mut Self {
759        self.add_int_array(values, "uint8[]", 1)
760    }
761
762    /// Add a `uint16[]` argument to the `ContractFunctionParameters`
763    pub fn add_uint16_array(&mut self, values: &[u16]) -> &mut Self {
764        self.add_int_array(values, "uint16[]", 2)
765    }
766
767    /// Add a `uint24[]` argument to the `ContractFunctionParameters`
768    pub fn add_uint24_array(&mut self, values: &[u32]) -> &mut Self {
769        self.add_int_array(values, "uint24[]", 3)
770    }
771
772    /// Add a `uint32[]` argument to the `ContractFunctionParameters`
773    pub fn add_uint32_array(&mut self, values: &[u32]) -> &mut Self {
774        self.add_int_array(values, "uint32[]", 4)
775    }
776
777    /// Add a `uint40[]` argument to the `ContractFunctionParameters`
778    pub fn add_uint40_array(&mut self, values: &[u64]) -> &mut Self {
779        self.add_int_array(values, "uint40[]", 5)
780    }
781
782    /// Add a `uint48[]` argument to the `ContractFunctionParameters`
783    pub fn add_uint48_array(&mut self, values: &[u64]) -> &mut Self {
784        self.add_int_array(values, "uint48[]", 6)
785    }
786
787    /// Add a `uint56[]` argument to the `ContractFunctionParameters`
788    pub fn add_uint56_array(&mut self, values: &[u64]) -> &mut Self {
789        self.add_int_array(values, "uint56[]", 7)
790    }
791
792    /// Add a `uint64[]` argument to the `ContractFunctionParameters`
793    pub fn add_uint64_array(&mut self, values: &[u64]) -> &mut Self {
794        self.add_int_array(values, "uint64[]", 8)
795    }
796
797    /// Add a `uint72[]` argument to the `ContractFunctionParameters`
798    pub fn add_uint72_array(&mut self, values: &[u128]) -> &mut Self {
799        self.add_int_array(values, "uint72[]", 9)
800    }
801
802    /// Add a `uint80[]` argument to the `ContractFunctionParameters`
803    pub fn add_uint80_array(&mut self, values: &[u128]) -> &mut Self {
804        self.add_int_array(values, "uint80[]", 10)
805    }
806
807    /// Add a `uint88[]` argument to the `ContractFunctionParameters`
808    pub fn add_uint88_array(&mut self, values: &[u128]) -> &mut Self {
809        self.add_int_array(values, "uint88[]", 11)
810    }
811
812    /// Add a `uint96[]` argument to the `ContractFunctionParameters`
813    pub fn add_uint96_array(&mut self, values: &[u128]) -> &mut Self {
814        self.add_int_array(values, "uint96[]", 12)
815    }
816
817    /// Add a `uint104[]` argument to the `ContractFunctionParameters`
818    pub fn add_uint104_array(&mut self, values: &[u128]) -> &mut Self {
819        self.add_int_array(values, "uint104[]", 13)
820    }
821
822    /// Add a `uint112[]` argument to the `ContractFunctionParameters`
823    pub fn add_uint112_array(&mut self, values: &[u128]) -> &mut Self {
824        self.add_int_array(values, "uint112[]", 14)
825    }
826
827    /// Add a `uint120[]` argument to the `ContractFunctionParameters`
828    pub fn add_uint120_array(&mut self, values: &[u128]) -> &mut Self {
829        self.add_int_array(values, "uint120[]", 15)
830    }
831
832    /// Add a `uint128[]` argument to the `ContractFunctionParameters`
833    pub fn add_uint128_array(&mut self, values: &[u128]) -> &mut Self {
834        self.add_int_array(values, "uint128[]", 16)
835    }
836
837    /// Add a `uint136[]` argument to the `ContractFunctionParameters`
838    pub fn add_uint136_array(&mut self, values: &[BigUint]) -> &mut Self {
839        self.add_int_array(values, "uint136[]", 17)
840    }
841
842    /// Add a `uint144[]` argument to the `ContractFunctionParameters`
843    pub fn add_uint144_array(&mut self, values: &[BigUint]) -> &mut Self {
844        self.add_int_array(values, "uint144[]", 18)
845    }
846
847    /// Add a `uint152[]` argument to the `ContractFunctionParameters`
848    pub fn add_uint152_array(&mut self, values: &[BigUint]) -> &mut Self {
849        self.add_int_array(values, "uint152[]", 19)
850    }
851
852    /// Add a `uint160[]` argument to the `ContractFunctionParameters`
853    pub fn add_uint160_array(&mut self, values: &[BigUint]) -> &mut Self {
854        self.add_int_array(values, "uint160[]", 20)
855    }
856
857    /// Add a `uint168[]` argument to the `ContractFunctionParameters`
858    pub fn add_uint168_array(&mut self, values: &[BigUint]) -> &mut Self {
859        self.add_int_array(values, "uint168[]", 21)
860    }
861
862    /// Add a `uint176[]` argument to the `ContractFunctionParameters`
863    pub fn add_uint176_array(&mut self, values: &[BigUint]) -> &mut Self {
864        self.add_int_array(values, "uint176[]", 22)
865    }
866
867    /// Add a `uint184[]` argument to the `ContractFunctionParameters`
868    pub fn add_uint184_array(&mut self, values: &[BigUint]) -> &mut Self {
869        self.add_int_array(values, "uint184[]", 23)
870    }
871
872    /// Add a `uint192[]` argument to the `ContractFunctionParameters`
873    pub fn add_uint192_array(&mut self, values: &[BigUint]) -> &mut Self {
874        self.add_int_array(values, "uint192[]", 24)
875    }
876
877    /// Add a `uint200[]` argument to the `ContractFunctionParameters`
878    pub fn add_uint200_array(&mut self, values: &[BigUint]) -> &mut Self {
879        self.add_int_array(values, "uint200[]", 25)
880    }
881
882    /// Add a `uint208[]` argument to the `ContractFunctionParameters`
883    pub fn add_uint208_array(&mut self, values: &[BigUint]) -> &mut Self {
884        self.add_int_array(values, "uint208[]", 26)
885    }
886
887    /// Add a `uint216[]` argument to the `ContractFunctionParameters`
888    pub fn add_uint216_array(&mut self, values: &[BigUint]) -> &mut Self {
889        self.add_int_array(values, "uint216[]", 27)
890    }
891
892    /// Add a `uint224[]` argument to the `ContractFunctionParameters`
893    pub fn add_uint224_array(&mut self, values: &[BigUint]) -> &mut Self {
894        self.add_int_array(values, "uint224[]", 28)
895    }
896
897    /// Add a `uint232[]` argument to the `ContractFunctionParameters`
898    pub fn add_uint232_array(&mut self, values: &[BigUint]) -> &mut Self {
899        self.add_int_array(values, "uint232[]", 29)
900    }
901
902    /// Add a `uint240[]` argument to the `ContractFunctionParameters`
903    pub fn add_uint240_array(&mut self, values: &[BigUint]) -> &mut Self {
904        self.add_int_array(values, "uint240[]", 30)
905    }
906
907    /// Add a `uint248[]` argument to the `ContractFunctionParameters`
908    pub fn add_uint248_array(&mut self, values: &[BigUint]) -> &mut Self {
909        self.add_int_array(values, "uint248[]", 31)
910    }
911
912    /// Add a `uint256[]` argument to the `ContractFunctionParameters`
913    pub fn add_uint256_array(&mut self, values: &[BigUint]) -> &mut Self {
914        self.add_int_array(values, "uint256[]", 32)
915    }
916
917    /// Add an `address` argument to the `ContractFunctionParameters`
918    pub fn add_address(&mut self, address: &str) -> &mut Self {
919        self.args.push(Argument {
920            type_name: "address",
921            value_bytes: encode_address(address).to_vec(),
922            is_dynamic: false,
923        });
924        self
925    }
926
927    /// Add an `address[]` argument to the `ContractFunctionParameters`
928    pub fn add_address_array(&mut self, addresses: &[&str]) -> &mut Self {
929        self.args.push(Argument {
930            type_name: "address[]",
931            value_bytes: encode_array_of_32_byte_elements(
932                addresses.iter().map(|addr| encode_address(addr)),
933                addresses.len(),
934            ),
935            is_dynamic: true,
936        });
937        self
938    }
939
940    /// Add a `function` argument to the `ContractFunctionParameters`
941    ///
942    /// # Panics
943    /// If the `address` isn't a valid evm address.
944    pub fn add_function(
945        &mut self,
946        address: &str,
947        mut selector: ContractFunctionSelector,
948    ) -> &mut Self {
949        let mut value_bytes = SolidityAddress::from_str(address).unwrap().to_bytes().to_vec();
950        value_bytes.extend(selector.finish());
951        right_pad_32_bytes(&mut value_bytes);
952
953        self.args.push(Argument {
954            type_name: "function",
955            value_bytes: value_bytes,
956            is_dynamic: false,
957        });
958        self
959    }
960}
961
962fn left_pad_32_bytes(bytes: &[u8], is_negative: bool) -> [u8; 32] {
963    let pad_byte = if is_negative { 0xFF } else { 0x00 };
964
965    let mut result = [pad_byte; 32];
966    result[(32 - bytes.len())..].copy_from_slice(bytes);
967    result
968}
969
970fn truncate_and_left_pad_32_bytes<T>(val: &T, byte_count: isize) -> [u8; 32]
971where
972    T: IntEncode,
973{
974    let (is_negative, full_value_bytes) = val.get_is_negative_and_be_bytes();
975    let truncated_value_bytes =
976        &full_value_bytes[max((full_value_bytes.len() as isize) - byte_count, 0) as usize..];
977    left_pad_32_bytes(truncated_value_bytes, is_negative)
978}
979
980/// Pads out `buf` so that it's len % 32 == 0
981fn right_pad_32_bytes(buf: &mut Vec<u8>) {
982    let rem = buf.len() % 32;
983    if rem != 0 {
984        let padding = [0_u8; 32];
985        buf.extend_from_slice(&padding[..(32 - rem)])
986    }
987}
988
989fn encode_address(address: &str) -> [u8; 32] {
990    left_pad_32_bytes(SolidityAddress::from_str(address).unwrap().0 .0.as_slice(), false)
991}
992
993fn encode_dynamic_bytes(bytes: &[u8]) -> Vec<u8> {
994    let mut out_bytes = left_pad_32_bytes(bytes.len().to_be_bytes().as_slice(), false).to_vec();
995    out_bytes.extend(bytes);
996    right_pad_32_bytes(&mut out_bytes);
997    out_bytes
998}
999
1000fn encode_array_of_dynamic_byte_arrays<I>(elements: I, elements_len: usize) -> Vec<u8>
1001where
1002    I: IntoIterator,
1003    I::Item: AsRef<[u8]>,
1004{
1005    let head_len = (elements_len + 1) * 32;
1006    let mut out_bytes = Vec::with_capacity(head_len);
1007    out_bytes.extend_from_slice(
1008        left_pad_32_bytes(elements_len.to_be_bytes().as_slice(), false).as_slice(),
1009    );
1010    let mut current_offset = elements_len * 32;
1011    let mut body_bytes: Vec<u8> = Vec::new();
1012    for element in elements {
1013        let element = element.as_ref();
1014        out_bytes.extend_from_slice(
1015            left_pad_32_bytes(current_offset.to_be_bytes().as_slice(), false).as_slice(),
1016        );
1017        current_offset += element.len();
1018        body_bytes.extend(element);
1019    }
1020    out_bytes.extend(body_bytes);
1021    out_bytes
1022}
1023
1024fn encode_array_of_32_byte_elements<I>(elements: I, elements_len: usize) -> Vec<u8>
1025where
1026    I: IntoIterator<Item = [u8; 32]>,
1027{
1028    let mut out_bytes = left_pad_32_bytes(elements_len.to_be_bytes().as_slice(), false).to_vec();
1029    out_bytes.reserve(out_bytes.len() + (elements_len * 32));
1030    out_bytes.extend(elements.into_iter().flatten());
1031    out_bytes
1032}
1033
1034fn encode_array_of_32_byte<T: AsBytes32 + ?Sized>(elements: &T) -> Vec<u8> {
1035    let slice = elements.as_bytes32();
1036    if slice.len() > 32 {
1037        panic!("32 bytes exceeded in contract function call")
1038    }
1039
1040    let mut new_bytes = slice.to_vec();
1041    right_pad_32_bytes(&mut new_bytes);
1042    new_bytes
1043}
1044
1045#[cfg(test)]
1046mod tests {
1047    use num_bigint::{
1048        BigInt,
1049        BigUint,
1050    };
1051
1052    use crate::contract::contract_function_parameters::ContractFunctionParameters;
1053    use crate::contract::contract_function_selector::ContractFunctionSelector;
1054
1055    #[test]
1056    fn misc_params() {
1057        let param_bytes = ContractFunctionParameters::new()
1058            .add_uint8(0x1)
1059            .add_int8(-0x2)
1060            .add_uint32(0x3)
1061            .add_int32(-0x4)
1062            .add_uint64(0x4)
1063            .add_int64(-0x5)
1064            .add_uint256(BigUint::from(0x6_u32))
1065            .add_int256(BigInt::from(-0x7))
1066            .add_uint8_array([0x1, 0x2, 0x3, 0x4].as_slice())
1067            .add_int8_array([-0x5, 0x6, 0x7, -0x8].as_slice())
1068            .add_uint32_array([0x9, 0xA, 0xB, 0xC].as_slice())
1069            .add_int32_array([-0xD, 0xE, 0xF, -0x10].as_slice())
1070            .add_uint64_array([0x11, 0x12, 0x13, 0x14].as_slice())
1071            .add_int64_array([-0x15, 0x16, 0x17, -0x18].as_slice())
1072            .add_uint256_array([BigUint::from(0x19_u32)].as_slice())
1073            .add_int256_array([BigInt::from(-0x1A)].as_slice())
1074            .to_bytes(Some("foo"));
1075
1076        assert_eq!(
1077            hex::encode(param_bytes),
1078            "11bcd903\
1079                0000000000000000000000000000000000000000000000000000000000000001\
1080                fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe\
1081                0000000000000000000000000000000000000000000000000000000000000003\
1082                fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc\
1083                0000000000000000000000000000000000000000000000000000000000000004\
1084                fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb\
1085                0000000000000000000000000000000000000000000000000000000000000006\
1086                fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9\
1087                0000000000000000000000000000000000000000000000000000000000000200\
1088                00000000000000000000000000000000000000000000000000000000000002a0\
1089                0000000000000000000000000000000000000000000000000000000000000340\
1090                00000000000000000000000000000000000000000000000000000000000003e0\
1091                0000000000000000000000000000000000000000000000000000000000000480\
1092                0000000000000000000000000000000000000000000000000000000000000520\
1093                00000000000000000000000000000000000000000000000000000000000005c0\
1094                0000000000000000000000000000000000000000000000000000000000000600\
1095                0000000000000000000000000000000000000000000000000000000000000004\
1096                0000000000000000000000000000000000000000000000000000000000000001\
1097                0000000000000000000000000000000000000000000000000000000000000002\
1098                0000000000000000000000000000000000000000000000000000000000000003\
1099                0000000000000000000000000000000000000000000000000000000000000004\
1100                0000000000000000000000000000000000000000000000000000000000000004\
1101                fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb\
1102                0000000000000000000000000000000000000000000000000000000000000006\
1103                0000000000000000000000000000000000000000000000000000000000000007\
1104                fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8\
1105                0000000000000000000000000000000000000000000000000000000000000004\
1106                0000000000000000000000000000000000000000000000000000000000000009\
1107                000000000000000000000000000000000000000000000000000000000000000a\
1108                000000000000000000000000000000000000000000000000000000000000000b\
1109                000000000000000000000000000000000000000000000000000000000000000c\
1110                0000000000000000000000000000000000000000000000000000000000000004\
1111                fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff3\
1112                000000000000000000000000000000000000000000000000000000000000000e\
1113                000000000000000000000000000000000000000000000000000000000000000f\
1114                fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0\
1115                0000000000000000000000000000000000000000000000000000000000000004\
1116                0000000000000000000000000000000000000000000000000000000000000011\
1117                0000000000000000000000000000000000000000000000000000000000000012\
1118                0000000000000000000000000000000000000000000000000000000000000013\
1119                0000000000000000000000000000000000000000000000000000000000000014\
1120                0000000000000000000000000000000000000000000000000000000000000004\
1121                ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeb\
1122                0000000000000000000000000000000000000000000000000000000000000016\
1123                0000000000000000000000000000000000000000000000000000000000000017\
1124                ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe8\
1125                0000000000000000000000000000000000000000000000000000000000000001\
1126                0000000000000000000000000000000000000000000000000000000000000019\
1127                0000000000000000000000000000000000000000000000000000000000000001\
1128                ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe6"
1129        )
1130    }
1131
1132    #[test]
1133    fn address_params() {
1134        let param_bytes = ContractFunctionParameters::new()
1135            .add_address("1122334455667788990011223344556677889900")
1136            .add_address("0x1122334455667788990011223344556677889900")
1137            .add_address_array(
1138                [
1139                    "1122334455667788990011223344556677889900",
1140                    "1122334455667788990011223344556677889900",
1141                ]
1142                .as_slice(),
1143            )
1144            .to_bytes(Some("foo"));
1145
1146        assert_eq!(
1147            hex::encode(param_bytes),
1148            "7d48c86d\
1149                0000000000000000000000001122334455667788990011223344556677889900\
1150                0000000000000000000000001122334455667788990011223344556677889900\
1151                0000000000000000000000000000000000000000000000000000000000000060\
1152                0000000000000000000000000000000000000000000000000000000000000002\
1153                0000000000000000000000001122334455667788990011223344556677889900\
1154                0000000000000000000000001122334455667788990011223344556677889900"
1155        )
1156    }
1157
1158    #[test]
1159    fn function_params() {
1160        let param_bytes = ContractFunctionParameters::new()
1161            .add_function(
1162                "1122334455667788990011223344556677889900",
1163                ContractFunctionSelector::from([1, 2, 3, 4]),
1164            )
1165            .add_function(
1166                "0x1122334455667788990011223344556677889900",
1167                ContractFunctionSelector::new("randomFunction").add_bool().clone(),
1168            )
1169            .to_bytes(Some("foo"));
1170
1171        assert_eq!(
1172            hex::encode(param_bytes),
1173            "c99c40cd\
1174                1122334455667788990011223344556677889900010203040000000000000000\
1175                112233445566778899001122334455667788990063441d820000000000000000"
1176        );
1177    }
1178
1179    // regression test for https://github.com/hashgraph/hedera-sdk-rust/issues/715
1180    #[test]
1181    fn long_string() {
1182        let s = "abcd".repeat(63);
1183
1184        let bytes = ContractFunctionParameters::new().add_string(s).to_bytes(None);
1185
1186        // sigh, the things we do to not have to manually format.
1187        let mut buf = String::with_capacity(bytes.len() * 2 + ((bytes.len() * 2) / 64));
1188        for line in bytes.chunks(32).map(hex::encode) {
1189            if !buf.is_empty() {
1190                buf.push('\n');
1191            }
1192
1193            buf.push_str(&line);
1194        }
1195
1196        expect_test::expect![[r#"
1197            0000000000000000000000000000000000000000000000000000000000000020
1198            00000000000000000000000000000000000000000000000000000000000000fc
1199            6162636461626364616263646162636461626364616263646162636461626364
1200            6162636461626364616263646162636461626364616263646162636461626364
1201            6162636461626364616263646162636461626364616263646162636461626364
1202            6162636461626364616263646162636461626364616263646162636461626364
1203            6162636461626364616263646162636461626364616263646162636461626364
1204            6162636461626364616263646162636461626364616263646162636461626364
1205            6162636461626364616263646162636461626364616263646162636461626364
1206            6162636461626364616263646162636461626364616263646162636400000000"#]]
1207        .assert_eq(&buf);
1208    }
1209
1210    #[test]
1211    fn string_to_bytes32() {
1212        let s = "alice".to_string();
1213
1214        let bytes = ContractFunctionParameters::new().add_bytes32(&s).to_bytes(None);
1215
1216        // sigh, the things we do to not have to manually format.
1217        let mut buf = String::with_capacity(bytes.len() * 2 + ((bytes.len() * 2) / 64));
1218        for line in bytes.chunks(32).map(hex::encode) {
1219            if !buf.is_empty() {
1220                buf.push('\n');
1221            }
1222
1223            buf.push_str(&line);
1224        }
1225
1226        expect_test::expect!["616c696365000000000000000000000000000000000000000000000000000000"]
1227            .assert_eq(&buf);
1228    }
1229
1230    #[test]
1231    fn str_to_bytes32() {
1232        let s = "alice";
1233
1234        let bytes = ContractFunctionParameters::new().add_bytes32(s).to_bytes(None);
1235
1236        let mut buf = String::with_capacity(bytes.len() * 2 + ((bytes.len() * 2) / 64));
1237        for line in bytes.chunks(32).map(hex::encode) {
1238            if !buf.is_empty() {
1239                buf.push('\n');
1240            }
1241
1242            buf.push_str(&line);
1243        }
1244
1245        expect_test::expect!["616c696365000000000000000000000000000000000000000000000000000000"]
1246            .assert_eq(&buf);
1247    }
1248
1249    #[test]
1250    fn bytes_to_bytes32() {
1251        let mut array = [0u8; 32];
1252
1253        let str_sample = "aliceandbob".as_bytes();
1254
1255        for (i, &byte) in str_sample.iter().enumerate() {
1256            array[i] = byte;
1257        }
1258
1259        let bytes = ContractFunctionParameters::new().add_bytes32(&array).to_bytes(None);
1260
1261        let mut buf = String::with_capacity(bytes.len() * 2 + ((bytes.len() * 2) / 64));
1262        for line in bytes.chunks(32).map(hex::encode) {
1263            if !buf.is_empty() {
1264                buf.push('\n');
1265            }
1266
1267            buf.push_str(&line);
1268        }
1269
1270        expect_test::expect!["616c696365616e64626f62000000000000000000000000000000000000000000"]
1271            .assert_eq(&buf);
1272    }
1273
1274    #[test]
1275    #[should_panic]
1276    fn bytes32_panic() {
1277        let str_sample = "alice bought some burgers from bob";
1278
1279        // should panic if input is more than 32 bytes in add_bytes32
1280        ContractFunctionParameters::new().add_bytes32(str_sample).to_bytes(None);
1281    }
1282}