t3rn_types/
abi.rs

1use codec::{Decode, Encode};
2use scale_info::{
3    prelude::{boxed::Box, fmt::Debug, vec, vec::Vec},
4    TypeInfo,
5};
6
7#[cfg(feature = "runtime")]
8use scale_info::prelude::any::Any;
9
10#[cfg(feature = "runtime")]
11use primitive_types::U256;
12
13#[cfg(feature = "runtime")]
14use crate::Bytes;
15
16#[cfg(feature = "std")]
17use serde::{Deserialize, Serialize};
18
19#[cfg(feature = "runtime")]
20use sp_runtime::RuntimeString;
21
22/// ToDo: Introduce Compact Encoding for u8 + u16 + u32
23#[derive(PartialEq, Clone, Encode, Decode, Eq, Hash, Debug, TypeInfo)]
24#[cfg_attr(feature = "std", derive(serde::Serialize, serde::Deserialize))]
25pub enum Type {
26    Address(u16),
27    DynamicAddress,
28    Bool,
29    Int(u16),
30    Uint(u16),
31    /// where u8 is bytes length
32    Bytes(u8),
33    DynamicBytes,
34    String,
35    Enum(u8),
36    Struct(u8),
37    Mapping(Box<Type>, Box<Type>),
38    Contract,
39    Ref(Box<Type>),
40    Option(Box<Type>),
41    OptionalInsurance,
42    OptionalReward,
43    StorageRef(Box<Type>),
44    /// There is no way to declare value in Solidity (should there be?)
45    Value,
46    /// DynamicBytes and String are lowered to a vector.
47    Slice,
48    Hasher(HasherAlgo, u16),
49    Crypto(CryptoAlgo),
50}
51
52#[derive(PartialEq, Clone, Encode, Decode, Eq, Hash, Debug, TypeInfo)]
53#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
54pub enum HasherAlgo {
55    Blake2,
56    Keccak256,
57}
58
59#[derive(PartialEq, Clone, Encode, Decode, Eq, Hash, Debug, TypeInfo)]
60#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
61pub enum CryptoAlgo {
62    Ed25519,
63    Sr25519,
64    Ecdsa,
65}
66
67#[derive(PartialEq, Clone, Encode, Decode, Eq, Hash, Debug, TypeInfo)]
68#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
69/// Describe ABI configuration for a gateway so that it's possible to cast types
70/// of inbound and outbound messages to that gateway
71pub struct GatewayABIConfig {
72    /// block number type in bytes
73    pub block_number_type_size: u16,
74    /// hash size in bytes
75    pub hash_size: u16,
76    /// hashing algorithm
77    pub hasher: HasherAlgo,
78    /// cryptography algorithm
79    pub crypto: CryptoAlgo,
80    /// address length in bytes
81    pub address_length: u16,
82    /// value length in bytes
83    pub value_type_size: u16,
84    /// value length in bytes
85    pub decimals: u16,
86    /// value length in bytes. ToDo: move as part of metadata.
87    pub structs: Vec<StructDecl>,
88}
89
90impl Default for GatewayABIConfig {
91    fn default() -> GatewayABIConfig {
92        GatewayABIConfig {
93            block_number_type_size: 32,
94            hash_size: 32,
95            hasher: HasherAlgo::Blake2,
96            crypto: CryptoAlgo::Sr25519,
97            address_length: 32, // 32 bytes : 32 * 8 = 256 bits
98            value_type_size: 8, // u64 = 8 bytes = 64 bits.
99            decimals: 8,
100            structs: vec![],
101        }
102    }
103}
104
105#[derive(PartialEq, Clone, Encode, Decode, Eq, Hash, Debug, TypeInfo)]
106#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
107pub struct ContractActionDesc<Hash, TargetId, AccountId> {
108    pub action_id: Hash,
109    pub target_id: Option<TargetId>,
110    pub to: Option<AccountId>,
111}
112
113#[derive(PartialEq, Clone, Encode, Decode, Eq, Hash, Debug, TypeInfo)]
114#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
115pub struct Parameter {
116    /// The name can empty (e.g. in an event field or unnamed parameter/return); encoded vector
117    pub name: Option<Vec<u8>>,
118    /// ABI type
119    pub ty: Type,
120    /// number in order
121    pub no: u32,
122    /// is indexed - follows the ethereum logs pattern where longer exceeding 32 bytes values are indexed
123    pub indexed: Option<bool>,
124}
125
126#[derive(PartialEq, Clone, Encode, Decode, Eq, Hash, Debug, TypeInfo)]
127#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
128pub struct StructDecl {
129    /// encoded name of the struct
130    pub name: Type,
131    /// list of fields, each of them will have corresponding no.
132    pub fields: Vec<Parameter>,
133    /// List of offsets of the fields, last entry is the offset for the struct overall size
134    pub offsets: Vec<u16>,
135}
136
137impl Type {
138    /// Calculate how much memory we expect this type to use when allocated on the
139    /// stack or on the heap. Depending on the llvm implementation there might be
140    /// padding between elements which is not accounted for.
141    pub fn size_of(&self, gen: &GatewayABIConfig) -> Result<usize, &'static str> {
142        match self {
143            Type::Enum(_) => Ok(1),
144            Type::Bool => Ok(1),
145            Type::Contract | Type::Address(_) => Ok(gen.address_length as usize),
146            Type::Bytes(n) => Ok(*n as usize),
147            Type::Uint(n) | Type::Int(n) => Ok((n / 8).into()),
148            Type::Struct(n) => {
149                let struct_size = gen
150                    .structs
151                    .get(*n as usize)
152                    .ok_or("Can't access requested struct from gateway genesis")?
153                    .offsets
154                    .last()
155                    .cloned()
156                    .unwrap_or(0);
157                Ok(struct_size.into())
158            },
159            Type::String | Type::DynamicBytes => Ok(4),
160            Type::Hasher(_hasher_alg, _hash_size) => Ok(gen.hash_size as usize),
161            _ => unimplemented!(),
162        }
163    }
164
165    pub fn to_string_bytes(&self) -> &[u8] {
166        match self {
167            Type::Enum(_) => b"enum",
168            Type::Bool => b"bool",
169            Type::Contract => b"contract",
170            Type::Address(_) => b"address",
171            Type::Bytes(_) => b"bytes",
172            Type::Uint(n) => match n {
173                32 => b"uint32",
174                64 => b"uint64",
175                128 => b"uint128",
176                _ => unimplemented!(),
177            },
178            Type::Int(n) => match n {
179                32 => b"int32",
180                64 => b"int64",
181                128 => b"int128",
182                _ => unimplemented!(),
183            },
184            Type::String => b"string",
185            Type::DynamicBytes => b"dynamic_bytes",
186            Type::DynamicAddress => b"dynamic_address",
187            Type::Hasher(hasher_alg, hash_size) => match hasher_alg {
188                HasherAlgo::Blake2 => match hash_size {
189                    128 => b"blake2_128",
190                    256 => b"blake2_256",
191                    _ => unimplemented!(),
192                },
193                HasherAlgo::Keccak256 => match hash_size {
194                    256 => b"blake2_256",
195                    _ => unimplemented!(),
196                },
197            },
198            Type::Crypto(crypto_alg) => match crypto_alg {
199                CryptoAlgo::Ed25519 => b"ed25519",
200                CryptoAlgo::Sr25519 => b"sr25519",
201                CryptoAlgo::Ecdsa => b"ecdsa",
202            },
203            _ => unimplemented!(),
204        }
205    }
206
207    #[cfg(feature = "runtime")]
208    pub fn to_string(&self) -> RuntimeString {
209        match self {
210            Type::Enum(_) => RuntimeString::from("enum"),
211            Type::Bool => RuntimeString::from("bool"),
212            Type::Contract => RuntimeString::from("contract"),
213            Type::Address(_) => RuntimeString::from("address"),
214            Type::Bytes(_) => RuntimeString::from("bytes"),
215            Type::Uint(n) => match n {
216                32 => RuntimeString::from("uint32"),
217                64 => RuntimeString::from("uint64"),
218                128 => RuntimeString::from("uint128"),
219                _ => unimplemented!(),
220            },
221            Type::Int(n) => match n {
222                32 => RuntimeString::from("int32"),
223                64 => RuntimeString::from("int64"),
224                128 => RuntimeString::from("int128"),
225                _ => unimplemented!(),
226            },
227            Type::String => RuntimeString::from("string"),
228            Type::DynamicBytes => RuntimeString::from("dynamic_bytes"),
229            Type::Hasher(hasher_alg, hash_size) => match hasher_alg {
230                HasherAlgo::Blake2 => match hash_size {
231                    128 => RuntimeString::from("blake2_128"),
232                    256 => RuntimeString::from("blake2_256"),
233                    _ => unimplemented!(),
234                },
235                HasherAlgo::Keccak256 => match hash_size {
236                    256 => RuntimeString::from("blake2_256"),
237                    _ => unimplemented!(),
238                },
239            },
240            Type::Crypto(crypto_alg) => match crypto_alg {
241                CryptoAlgo::Ed25519 => RuntimeString::from("ed25519"),
242                CryptoAlgo::Sr25519 => RuntimeString::from("sr25519"),
243                CryptoAlgo::Ecdsa => RuntimeString::from("ecdsa"),
244            },
245            _ => unimplemented!(),
246        }
247    }
248
249    /// eval assumes encoded_val is bytes Vector encoded with SCALE
250    #[cfg(feature = "runtime")]
251    pub fn eval_abi(
252        &self,
253        encoded_val: Vec<u8>,
254        gen: &GatewayABIConfig,
255    ) -> Result<Vec<u8>, &'static str> {
256        match self {
257            Type::Address(size) => match size {
258                20 => {
259                    let res: [u8; 20] = decode_buf2val(encoded_val)?;
260                    Ok(res.encode())
261                },
262                32 => {
263                    let res: [u8; 32] = decode_buf2val(encoded_val)?;
264                    Ok(res.encode())
265                },
266                _ => Err("Unknown Address size"),
267            },
268            Type::DynamicAddress => match gen.address_length {
269                20 => {
270                    let res: [u8; 20] = decode_buf2val(encoded_val)?;
271                    Ok(res.encode())
272                },
273                32 => {
274                    let res: [u8; 32] = decode_buf2val(encoded_val)?;
275                    Ok(res.encode())
276                },
277                _ => unimplemented!(),
278            },
279            Type::Bool => {
280                let res: bool = decode_buf2val(encoded_val)?;
281                Ok(res.encode())
282            },
283            Type::OptionalInsurance => {
284                // Assume it's gonna be an array of 2 x u128 values (Circuit's Balance)
285                //  First one is the insurance amount
286                //  Second one is the reward amount
287                // Since it's Optional - value can be an empty vector too.
288                match encoded_val.len() {
289                    0 => Ok(encoded_val),
290                    32 => {
291                        let res: [u128; 2] = decode_buf2val(encoded_val)?;
292                        Ok(res.encode())
293                    },
294                    _ => Err("ABI OptionalInsurance eval error - wrong arg size"),
295                }
296            },
297            Type::Int(size) => match size {
298                32 => {
299                    let res: i32 = decode_buf2val(encoded_val)?;
300                    Ok(res.encode())
301                },
302                64 => {
303                    let res: i64 = decode_buf2val(encoded_val)?;
304                    Ok(res.encode())
305                },
306                128 => {
307                    let res: i128 = decode_buf2val(encoded_val)?;
308                    Ok(res.encode())
309                },
310                _ => Err("Unknown Uint size"),
311            },
312            Type::Uint(size) => match size {
313                32 => {
314                    let res: u32 = decode_buf2val(encoded_val)?;
315                    Ok(res.encode())
316                },
317                64 => {
318                    let res: u64 = decode_buf2val(encoded_val)?;
319                    Ok(res.encode())
320                },
321                128 => {
322                    let res: u128 = decode_buf2val(encoded_val)?;
323                    Ok(res.encode())
324                },
325                _ => Err("Unknown Uint size"),
326            },
327            Type::Bytes(_) => {
328                let res: Bytes = decode_buf2val(encoded_val)?;
329                Ok(res.to_vec())
330            },
331            Type::DynamicBytes => Ok(encoded_val),
332            Type::String => {
333                let res: RuntimeString = decode_buf2val(encoded_val)?;
334                Ok(res.encode())
335            },
336            Type::Value => {
337                match gen.value_type_size {
338                    8 => {
339                        // 8 bytes = 64 bits
340                        let res: u64 = decode_buf2val::<u64>(encoded_val)?;
341                        Ok(res.encode())
342                    },
343                    16 => {
344                        // 16 bytes = 128 bits
345                        let res: u128 = decode_buf2val::<u128>(encoded_val)?;
346                        Ok(res.encode())
347                    },
348                    32 => {
349                        // 32 bytes = 256 bits
350                        let res: U256 = decode_buf2val::<U256>(encoded_val)?;
351                        Ok(res.encode())
352                    },
353                    _ => unimplemented!(),
354                }
355            },
356            _ => unimplemented!(),
357        }
358    }
359
360    /// eval assumes encoded_val is bytes Vector encoded with SCALE
361    #[cfg(feature = "runtime")]
362    pub fn eval(
363        &self,
364        encoded_val: Vec<u8>,
365        // _gen: &GatewayABIConfig,
366    ) -> Result<Box<dyn Any>, &'static str> {
367        match self {
368            Type::Address(size) => match size {
369                20 => {
370                    let res: [u8; 20] = decode_buf2val(encoded_val)?;
371                    Ok(Box::new(res))
372                },
373                32 => {
374                    let res: [u8; 32] = decode_buf2val(encoded_val)?;
375                    Ok(Box::new(res))
376                },
377                _ => Err("Unknown Address size"),
378            },
379            Type::DynamicAddress => {
380                let res: Vec<u8> = decode_buf2val(encoded_val)?;
381                Ok(Box::new(res))
382            },
383            Type::Bool => {
384                let res: bool = decode_buf2val(encoded_val)?;
385                Ok(Box::new(res))
386            },
387            Type::OptionalInsurance => {
388                // Assume it's gonna be an array of 2 x u128 values (Circuit's Balance)
389                //  First one is the insurance amount
390                //  Second one is the reward amount
391                // Since it's Optional - value can be an empty vector too.
392                match encoded_val.len() {
393                    0 => Ok(Box::new(encoded_val)),
394                    32 => {
395                        let res: [u128; 2] = decode_buf2val(encoded_val)?;
396                        Ok(Box::new(res))
397                    },
398                    _ => Err("ABI OptionalInsurance eval error - wrong arg size"),
399                }
400            },
401            Type::Int(size) => match size {
402                32 => {
403                    let res: i32 = decode_buf2val(encoded_val)?;
404                    Ok(Box::new(res))
405                },
406                64 => {
407                    let res: i64 = decode_buf2val(encoded_val)?;
408                    Ok(Box::new(res))
409                },
410                128 => {
411                    let res: i128 = decode_buf2val(encoded_val)?;
412                    Ok(Box::new(res))
413                },
414                _ => Err("Unknown Uint size"),
415            },
416            Type::Uint(size) => match size {
417                32 => {
418                    let res: u32 = decode_buf2val(encoded_val)?;
419                    Ok(Box::new(res))
420                },
421                64 => {
422                    let res: u64 = decode_buf2val(encoded_val)?;
423                    Ok(Box::new(res))
424                },
425                128 => {
426                    let res: u128 = decode_buf2val(encoded_val)?;
427                    Ok(Box::new(res))
428                },
429                _ => Err("Unknown Uint size"),
430            },
431            Type::Bytes(_) => {
432                let res: Bytes = decode_buf2val(encoded_val)?;
433                Ok(Box::new(res))
434            },
435            Type::DynamicBytes => {
436                let res: Vec<u8> = decode_buf2val(encoded_val)?;
437                Ok(Box::new(res))
438            },
439            Type::String => {
440                let res: RuntimeString = decode_buf2val(encoded_val)?;
441                Ok(Box::new(res))
442            },
443            Type::Hasher(hasher_alg, hash_size) => match hasher_alg {
444                HasherAlgo::Blake2 => match hash_size {
445                    128 => Ok(Box::new(sp_io::hashing::blake2_128)),
446                    256 => Ok(Box::new(sp_io::hashing::blake2_256)),
447                    _ => unimplemented!(),
448                },
449                HasherAlgo::Keccak256 => match hash_size {
450                    256 => Ok(Box::new(sp_io::hashing::keccak_256)),
451                    _ => unimplemented!(),
452                },
453            },
454            _ => unimplemented!(),
455        }
456    }
457}
458
459pub fn eval_to_encoded(t: Type, raw_val: Vec<u8>) -> Result<Vec<u8>, &'static str> {
460    match t {
461        Type::Address(size) => match size {
462            20 => {
463                let res: [u8; 20] = decode_buf2val(raw_val)?;
464                Ok(res.to_vec())
465            },
466            32 => {
467                let res: [u8; 32] = decode_buf2val(raw_val)?;
468                Ok(res.to_vec())
469            },
470            _ => Err("Unknown Address size"),
471        },
472        Type::Uint(size) => match size {
473            32 => {
474                let res: u32 = decode_buf2val(raw_val)?;
475                Ok(res.encode())
476            },
477            64 => {
478                let res: u64 = decode_buf2val(raw_val)?;
479                Ok(res.encode())
480            },
481            128 => {
482                let res: u128 = decode_buf2val(raw_val)?;
483                Ok(res.encode())
484            },
485            _ => Err("Unknown Uint size"),
486        },
487        Type::OptionalInsurance => {
488            // Assume it's gonna be an array of 2 x u128 values (Circuit's Balance)
489            //  First one is the insurance amount
490            //  Second one is the reward amount
491            // Since it's Optional - value can be an empty vector too.
492            match raw_val.len() {
493                0 => Ok(raw_val),
494                32 => {
495                    let res: [u128; 2] = decode_buf2val(raw_val)?;
496                    Ok(res.encode())
497                },
498                _ => Err("ABI OptionalInsurance eval error - wrong arg size"),
499            }
500        },
501        _ => Ok(vec![]),
502    }
503}
504
505#[cfg(feature = "runtime")]
506pub fn eval_trait_dynamically(t: Type) -> Result<Box<dyn Any>, &'static str> {
507    match t {
508        Type::Hasher(hasher_alg, hash_size) => match hasher_alg {
509            HasherAlgo::Blake2 => match hash_size {
510                256 => Ok(Box::new(sp_runtime::traits::BlakeTwo256)),
511                _ => unimplemented!(),
512            },
513            HasherAlgo::Keccak256 => match hash_size {
514                256 => Ok(Box::new(sp_runtime::traits::Keccak256)),
515                _ => unimplemented!(),
516            },
517        },
518        _ => unimplemented!(),
519    }
520}
521
522pub fn from_bytes_string(bytes_string: &[u8]) -> Type {
523    match bytes_string {
524        b"bool" => Type::Bool,
525        b"contract" => Type::Contract,
526        b"address" => Type::Address(20),
527        b"dynamic_address" => Type::DynamicAddress,
528        b"bytes" => Type::DynamicBytes,
529        b"dynamic_bytes" => Type::DynamicBytes,
530        b"uint32" => Type::Uint(32),
531        b"uint64" => Type::Uint(64),
532        b"uint128" => Type::Uint(128),
533        b"int32" => Type::Uint(32),
534        b"int64" => Type::Uint(64),
535        b"int128" => Type::Uint(128),
536        b"string" => Type::String,
537        b"blake2_256" => Type::Hasher(HasherAlgo::Blake2, 256),
538        b"blake2_128" => Type::Hasher(HasherAlgo::Blake2, 128),
539        b"keccak256" => Type::Hasher(HasherAlgo::Keccak256, 128),
540        b"sr25519" => Type::Crypto(CryptoAlgo::Sr25519),
541        b"ed25519" => Type::Crypto(CryptoAlgo::Ed25519),
542        b"ecdsa" => Type::Crypto(CryptoAlgo::Ecdsa),
543        _ => unimplemented!(),
544    }
545}
546
547pub fn create_signature(
548    name_encoded: Vec<u8>,
549    args_abi: Vec<Type>,
550) -> Result<Vec<u8>, &'static str> {
551    const BEGIN_ARGS_CHAR: u8 = b'(';
552    const END_ARGS_CHAR: u8 = b')';
553    const COMMA_SEPARATOR: u8 = b',';
554
555    let name_bytes: &[u8] = name_encoded.as_slice();
556
557    let middle_args = args_abi
558        .iter()
559        .map(|t| t.to_string_bytes())
560        .collect::<Vec<&[u8]>>()
561        .as_slice()
562        .join(&COMMA_SEPARATOR);
563
564    let r = [
565        name_bytes,
566        &[BEGIN_ARGS_CHAR],
567        middle_args.as_slice(),
568        &[END_ARGS_CHAR],
569    ]
570    .concat();
571
572    Ok(r)
573}
574
575pub fn from_signature_to_abi(signature: Vec<u8>) -> Result<(Vec<u8>, Vec<Type>), &'static str> {
576    const BEGIN_ARGS_CHAR: u8 = b'(';
577    const END_ARGS_CHAR: u8 = b')';
578    const COMMA_SEPARATOR: u8 = b',';
579
580    let mut signature_iter = signature
581        .as_slice()
582        .split(|x| x.eq(&BEGIN_ARGS_CHAR) || x.eq(&COMMA_SEPARATOR) || x.eq(&END_ARGS_CHAR))
583        .filter(|&x| !x.is_empty());
584
585    let maybe_name = signature_iter.next().unwrap_or(&[]);
586
587    assert!(
588        !maybe_name.is_empty(),
589        "Can't find a name while reading event's ABI"
590    );
591
592    let types = signature_iter.map(from_bytes_string).collect::<Vec<Type>>();
593
594    Ok((maybe_name.to_vec(), types))
595}
596
597pub fn extract_property_names_from_signature_as_bytes(
598    signature: Vec<u8>,
599) -> Result<(Vec<u8>, Vec<Vec<u8>>), &'static str> {
600    const BEGIN_ARGS_CHAR: u8 = b'(';
601    const END_ARGS_CHAR: u8 = b')';
602    const COMMA_SEPARATOR: u8 = b',';
603
604    let mut signature_iter = signature
605        .as_slice()
606        .split(|x| x.eq(&BEGIN_ARGS_CHAR) || x.eq(&COMMA_SEPARATOR) || x.eq(&END_ARGS_CHAR))
607        .filter(|&x| !x.is_empty());
608
609    let maybe_name = signature_iter.next().unwrap_or(&[]);
610
611    assert!(
612        !maybe_name.is_empty(),
613        "Can't find a name while reading event's ABI"
614    );
615
616    let property_names = signature_iter
617        .map(|arg_candidate| arg_candidate.to_vec())
618        .collect::<Vec<Vec<u8>>>();
619
620    Ok((maybe_name.to_vec(), property_names))
621}
622
623pub fn decode_buf2val<D: Decode>(buf: Vec<u8>) -> Result<D, &'static str> {
624    D::decode(&mut &buf[..]).map_err(|_| "Decoding error: decode_buf2val")
625}
626
627#[cfg(test)]
628mod tests {
629    use super::*;
630    use std::string::String;
631
632    #[test]
633    fn successfully_creates_signature() {
634        let test_types_vec: Vec<Type> = vec![Type::Bytes(64), Type::Address(20), Type::Uint(64)];
635        let test_name = b"testName".to_vec();
636        let signature_bytes = create_signature(test_name, test_types_vec).unwrap();
637        let signature_string = String::from_utf8(signature_bytes).unwrap();
638
639        assert_eq!(signature_string, "testName(bytes,address,uint64)");
640    }
641
642    #[test]
643    fn successfully_interprets_signature_into_abi_types() {
644        let test_signature_bytes = b"testName(bytes,address,uint32)".to_vec();
645
646        let res = from_signature_to_abi(test_signature_bytes).unwrap();
647        assert_eq!(
648            (
649                b"testName".to_vec(),
650                vec![Type::DynamicBytes, Type::Address(20), Type::Uint(32),],
651            ),
652            res
653        );
654    }
655
656    #[test]
657    fn successfully_abi_evals_empty_insurance_and_reward_optional_insurance() {
658        let empty_bytes: Vec<u8> = vec![];
659        let res = eval_to_encoded(Type::OptionalInsurance, empty_bytes.clone());
660        assert_eq!(res, Ok(empty_bytes));
661    }
662
663    #[test]
664    fn successfully_abi_evals_valid_insurance_and_reward_optional_insurance() {
665        let valid_insurance_args_arr: [u128; 2] = [1, 2];
666        let res = eval_to_encoded(Type::OptionalInsurance, valid_insurance_args_arr.encode());
667        assert_eq!(
668            Ok(vec![
669                1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
670                0, 0, 0, 0
671            ]),
672            res
673        );
674    }
675}