airnode_abi/
lib.rs

1//! This library allows to encode and decode different types of data
2//! during interaction between API3 Airnode and Ethereum smart contracts
3//!
4//! See details of protocol are at [Airnode Specification](https://github.com/api3dao/api3-docs/blob/master/airnode/airnode-abi-specifications.md)
5//!
6//! Parameters from contract event logs are consumed as `Vec<U256>`, which avoids reading
7//! random raw bytes and provides guarantee of a proper data alignment on input.
8//!
9//! Second parameter of decoding is `strict` flag, which defines whether decoding
10//! could be done into extended types (`String32`,`Bool`,`Date`)
11//! that are actually represented as `Bytes32` on a protocol level.
12//!
13//! ### decoding example
14//! ```
15//! use airnode_abi::ABI;
16//! use ethereum_types::U256;
17//! use hex_literal::hex;
18//!
19//! fn main() {
20//!     let data: Vec<U256> = vec![
21//!         hex!("3162000000000000000000000000000000000000000000000000000000000000").into(),
22//!         hex!("54657374427974657333324e616d650000000000000000000000000000000000").into(),
23//!         hex!("536f6d6520627974657333322076616c75650000000000000000000000000000").into(),
24//!     ];
25//!     let res: ABI = ABI::decode(&data, true).unwrap();
26//!     println!("{:#?}", res);
27//! }
28//! ```
29//!
30//! ### encoding example
31//! ```
32//! use airnode_abi::{ABI, Param};
33//! use ethereum_types::U256;
34//!
35//! fn main() {
36//!     let param = Param::String {
37//!         name: "hello".to_owned(),
38//!         value: "world".to_owned(),
39//!     };
40//!     let res: Vec<U256> = ABI::new(vec![param]).encode().unwrap();
41//!     println!("{:#?}", res);
42//! }
43//! ```
44//! Please see more examples for each type of the parameter in unit tests.
45
46mod decode;
47mod encode;
48
49use decode::{chunk_to_address, chunk_to_int, chunk_to_str, chunk_to_vec, str_to_date};
50use encode::{address_chunk, chunks, date_chunk, int_chunk, str_chunk32, str_chunks};
51use ethereum_types::{H160, U256};
52use serde::{Deserialize, Serialize};
53use std::collections::HashMap;
54use std::fmt;
55use thiserror::Error;
56
57#[derive(Debug, Error, Serialize)]
58pub enum EncodingError {
59    #[error("too many parameters, max is 31")]
60    TooManyParams,
61    #[error("string should not exceed 32 bytes")]
62    StringTooLong,
63    #[error("invalid year")]
64    InvalidYear,
65    #[error("invalid month")]
66    InvalidMonth,
67    #[error("invalid day")]
68    InvalidDay,
69}
70
71#[derive(Debug, Clone, Error, Serialize, Deserialize)]
72pub enum DecodingError {
73    #[error("no input")]
74    NoInput,
75    #[error("schema is missing")]
76    NoSchema,
77    #[error("invalid schema {0}")]
78    InvalidSchema(String),
79    #[error("schema version is invalid")]
80    InvalidVersion,
81    #[error("invalid schema character {0}")]
82    InvalidSchemaCharacter(char),
83    #[error("invalid schema chunk string {0}")]
84    InvalidSchemaChunkString(String),
85    #[error("invalid name chunk string {0}")]
86    InvalidNameChunkString(String),
87    #[error("invalid bool chunk {0}")]
88    InvalidBoolChunk(String),
89    #[error("invalid chunk string {0}")]
90    InvalidChunkString(String),
91    #[error("invalid UTF-8 string {0}")]
92    InvalidUtf8String(String),
93    #[error("invalid bool {0}")]
94    InvalidBool(String),
95}
96
97/// Atomic parameter in the Airnode ABI
98#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)]
99#[serde(tag = "type")]
100pub enum Param {
101    /// parameter that embeds EVM address (160 bits, H160)
102    Address { name: String, value: H160 },
103    /// (non-strict) parameter that embeds boolean value, stored as single Bytes32 value, encoded as bytes of "true" or "false" string
104    Bool { name: String, value: bool },
105    /// parameter that embeds array of bytes (dynamic size)
106    Bytes { name: String, value: Vec<u8> },
107    /// parameter that embeds single 256 bits value
108    Bytes32 { name: String, value: U256 },
109    /// (non-strict) parameter that embeds date value, stored as single Bytes32 value, encoded as bytes ISO-8601 string
110    Date {
111        name: String,
112        year: i32,
113        month: u32,
114        day: u32,
115    },
116    /// parameter that embeds signed 256 bits value (there is no type of I256 in Ethereum primitives)
117    Int256 {
118        name: String,
119        value: U256,
120        sign: i32, // we need to store the sign separately as we don't have that type
121    },
122    /// parameter that embeds UTF-8 string (dynamic size)
123    String { name: String, value: String },
124    /// (non-strict) parameter that embeds string as single Bytes32 value. The length of the string should not exceed 32 bytes
125    /// it will be decoded correctly if this is non-empty valid Utf-8 string
126    String32 { name: String, value: String },
127    /// parameter that embeds unsigned 256 bits value
128    Uint256 { name: String, value: U256 },
129}
130
131impl Param {
132    /// returns name of the parameter
133    pub fn get_name(&self) -> &str {
134        match &self {
135            Self::Address { name, value: _ } => name,
136            Self::Bool { name, value: _ } => name,
137            Self::Bytes { name, value: _ } => name,
138            Self::Bytes32 { name, value: _ } => name,
139            Self::Date {
140                name,
141                year: _,
142                month: _,
143                day: _,
144            } => name,
145            Self::Int256 {
146                name,
147                value: _,
148                sign: _,
149            } => name,
150            Self::String { name, value: _ } => name,
151            Self::String32 { name, value: _ } => name,
152            Self::Uint256 { name, value: _ } => name,
153        }
154    }
155
156    /// returns value of the parameter as string (for debugging purposes only)
157    pub fn get_value(&self) -> String {
158        match &self {
159            Self::Address { name: _, value } => format!("{:?}", value),
160            Self::Bool { name: _, value } => format!("{}", value),
161            Self::Bytes { name: _, value } => format!("{:x?}", value),
162            Self::Bytes32 { name: _, value } => format!("{:x?}", value),
163            Self::Date {
164                name: _,
165                year,
166                month,
167                day,
168            } => format!("{:04}-{:02}-{:02}", year, month, day),
169            Self::Int256 {
170                name: _,
171                value,
172                sign,
173            } => {
174                if *sign >= 0 {
175                    format!("{:x?}", value)
176                } else {
177                    format!("-{:x?}", value)
178                }
179            }
180            Self::String { name: _, value } => value.clone(),
181            Self::String32 { name: _, value } => value.clone(),
182            Self::Uint256 { name: _, value } => format!("{:x?}", value),
183        }
184    }
185
186    /// returns character of the parameter for encoding
187    /// - Upper case letters refer to dynamically sized types
188    /// - Lower case letters refer to statically sized types
189    /// - String32 is encoded into Bytes32 in solidity
190    pub fn get_char(&self) -> char {
191        match &self {
192            Self::Address { name: _, value: _ } => 'a',
193            Self::Bool { name: _, value: _ } => 'f',
194            Self::Bytes { name: _, value: _ } => 'B',
195            Self::Bytes32 { name: _, value: _ } => 'b',
196            Self::Date {
197                name: _,
198                year: _,
199                month: _,
200                day: _,
201            } => 'b',
202            Self::Int256 {
203                name: _,
204                value: _,
205                sign: _,
206            } => 'i',
207            Self::String { name: _, value: _ } => 'S',
208            Self::String32 { name: _, value: _ } => 's',
209            Self::Uint256 { name: _, value: _ } => 'u',
210        }
211    }
212
213    /// returns whether the size of the parameter value is fixed
214    pub fn is_fixed_size(&self) -> bool {
215        match &self {
216            Self::Bytes { name: _, value: _ } => false,
217            Self::String { name: _, value: _ } => false,
218            _ => true,
219        }
220    }
221
222    /// returns encoded version of fixed size chunks
223    fn fixed_chunks(&self) -> Result<Vec<U256>, EncodingError> {
224        match &self {
225            Self::Address { name, value } => Ok(vec![str_chunk32(name)?, address_chunk(*value)]),
226            Self::Bool { name, value } => Ok(vec![
227                str_chunk32(name)?,
228                if *value {
229                    str_chunk32("true")?
230                } else {
231                    str_chunk32("false")?
232                },
233            ]),
234            Self::Bytes { name, value: _ } => {
235                // dynamic structure, second parameter is reserved to be overwritten later
236                // it will contain the offset of the data
237                Ok(vec![str_chunk32(name)?, U256::from(0)])
238            }
239            Self::Bytes32 { name, value } => Ok(vec![str_chunk32(name)?, value.clone()]),
240            Self::Date {
241                name,
242                year,
243                month,
244                day,
245            } => Ok(vec![str_chunk32(name)?, date_chunk(*year, *month, *day)?]),
246            Self::Int256 { name, value, sign } => {
247                Ok(vec![str_chunk32(name)?, int_chunk(*value, *sign)])
248            }
249            Self::String { name, value: _ } => {
250                // dynamic structure, second parameter is reserved to be overwritten later
251                // it will contain the offset of the data
252                Ok(vec![str_chunk32(name)?, U256::from(0)])
253            }
254            Self::String32 { name, value } => Ok(vec![str_chunk32(name)?, str_chunk32(value)?]),
255            Self::Uint256 { name, value } => Ok(vec![str_chunk32(name)?, value.clone()]),
256        }
257    }
258
259    /// returns encoded version of dynamic size chunks
260    fn dynamic_chunks(&self) -> Vec<U256> {
261        match &self {
262            Self::Bytes { name: _, value } => vec![U256::from(value.len())]
263                .into_iter()
264                .chain(chunks(value).into_iter())
265                .collect(),
266            Self::String { name: _, value } => vec![U256::from(value.len())]
267                .into_iter()
268                .chain(str_chunks(value).into_iter())
269                .collect(),
270            _ => vec![],
271        }
272    }
273}
274
275impl fmt::Display for Param {
276    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
277        write!(
278            f,
279            "{}({}={})",
280            self.get_char(),
281            self.get_name(),
282            self.get_value()
283        )
284    }
285}
286
287fn default_version() -> u8 {
288    return 1;
289}
290
291/// Airnode ABI object that can be encoded into the vector of U256 and decoded from it
292#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)]
293pub struct ABI {
294    /// Id of the ABI version. It is always "1" so far
295    #[serde(skip_serializing)]
296    #[serde(default = "default_version")]
297    pub version: u8,
298    /// Schema string. Each parameter is represented by a char
299    pub schema: String,
300    /// List of ABI parameters.
301    pub params: Vec<Param>,
302}
303
304/// get parameters encoded into schema string.
305/// Each parameter type will be represented by a char.
306/// The first character, 1, represents the encoding version.
307fn encode_schema(version: u8, params: &Vec<Param>) -> String {
308    let s: String = params.iter().map(|p| p.get_char()).collect();
309    format!("{}{}", version as char, s)
310}
311
312impl ABI {
313    /// constructor of Airnode ABI from the list of parameters
314    pub fn new(params: Vec<Param>) -> Self {
315        Self {
316            version: 0x31,
317            schema: encode_schema(0x31, &params),
318            params,
319        }
320    }
321
322    /// constructor of Airnode ABI with no parameters
323    pub fn none() -> Self {
324        Self {
325            version: 0x31,
326            schema: "1".to_owned(),
327            params: vec![],
328        }
329    }
330
331    /// constructor of Airnode ABI with a single parameter
332    pub fn only(param: Param) -> Self {
333        let params = vec![param];
334        Self {
335            version: 0x31,
336            schema: encode_schema(0x31, &params),
337            params,
338        }
339    }
340
341    /// get parameter by its name
342    pub fn get(&self, key: &str) -> Option<Param> {
343        let filtered: Vec<&Param> = self
344            .params
345            .iter()
346            .filter(|&x| x.get_name() == key)
347            .collect();
348        if filtered.len() > 0 {
349            Some(filtered[0].clone())
350        } else {
351            None
352        }
353    }
354
355    /// encodes ABI into vector or 256 bit values
356    /// The function can encode up to 31 parameters (and 1 byte is used to encode the encoding version).
357    pub fn encode(&self) -> Result<Vec<U256>, EncodingError> {
358        if self.params.len() > 31 {
359            return Err(EncodingError::TooManyParams);
360        }
361        let mut out = vec![str_chunk32(encode_schema(0x31, &self.params).as_str())?];
362        let mut m: HashMap<usize, usize> = HashMap::new();
363        // first loop - pushing chunks of the fixed size
364        for (i, p) in self.params.iter().enumerate() {
365            if !p.is_fixed_size() {
366                m.insert(i, out.len() + 1);
367            }
368            let chunks = p.fixed_chunks()?;
369            chunks.iter().for_each(|chunk| {
370                out.push(chunk.clone());
371            });
372        }
373
374        // second loop - pushing chunks of dynamic size and adjusting their offsets
375        let mut offset: usize = out.len() * 0x20;
376        self.params.iter().enumerate().for_each(|(i, p)| {
377            let w_offset = m.get(&i);
378            p.dynamic_chunks().iter().for_each(|chunk| {
379                out[*w_offset.unwrap()] = U256::from(offset);
380                out.push(chunk.clone());
381            });
382            offset = out.len() * 0x20;
383        });
384        Ok(out)
385    }
386
387    /// decodes ABI from the vector or 256 bit values.
388    /// This function can be used when data doesn't contain schema, but you know it from the other source.
389    pub fn decode_with_schema(
390        schema: String,
391        data: &Vec<U256>,
392        strict: bool,
393    ) -> Result<Self, DecodingError> {
394        let schema_chunk = match str_chunk32(&schema) {
395            Ok(x) => x,
396            Err(e) => return Err(DecodingError::InvalidSchema(e.to_string())),
397        };
398        let input: Vec<U256> = vec![schema_chunk]
399            .into_iter()
400            .chain(data.clone().into_iter())
401            .collect();
402        Self::decode(&input, strict)
403    }
404
405    /// decodes ABI from the vector or 256 bit values
406    pub fn decode(input: &Vec<U256>, strict: bool) -> Result<Self, DecodingError> {
407        if input.len() < 1 {
408            return Err(DecodingError::NoInput);
409        }
410        if input.len() == 1 {
411            // if there is just 1 item in input vector - there will be no schema
412            return Ok(Self::new(vec![Param::Bytes32 {
413                name: "raw".to_string(),
414                value: input[0].clone(),
415            }]));
416        }
417
418        let schema_chunk = input.get(0).unwrap();
419        if schema_chunk.is_zero() {
420            return Err(DecodingError::NoSchema);
421        }
422
423        let schema: String = match chunk_to_str(*schema_chunk) {
424            Ok(x) => x,
425            Err(e) => return Err(DecodingError::InvalidSchemaChunkString(format!("{}", e))),
426        };
427
428        let mut params: Vec<Param> = vec![];
429        if schema.len() > 1 {
430            let ch_version = schema.chars().nth(0).unwrap();
431            if ch_version != '1' {
432                return Err(DecodingError::InvalidVersion);
433            }
434            let mut offs: usize = 1;
435            let mut errors: Vec<DecodingError> = vec![];
436            schema.chars().skip(1).for_each(|ch| {
437                match Self::from_chunks(ch, &input, &mut offs, strict) {
438                    Ok(p) => params.push(p),
439                    Err(e) => {
440                        errors.push(e);
441                    }
442                }
443            });
444            if errors.len() > 0 {
445                // it would be nice to use schema in the thrown error..
446                return Err(errors[0].clone());
447            }
448        }
449        Ok(Self::new(params))
450    }
451
452    /// decodes name and value from array of chunks, starting at the given `offset`
453    /// and using type from `ch` character.
454    /// Returns `Param` instance and updates `offset` with the bigger value.
455    fn from_chunks(
456        ch: char,
457        arr: &Vec<U256>,
458        offset: &mut usize,
459        strict: bool,
460    ) -> Result<Param, DecodingError> {
461        let name: String = match chunk_to_str(arr[*offset]) {
462            Ok(x) => x,
463            Err(e) => return Err(DecodingError::InvalidNameChunkString(format!("{}", e))),
464        };
465        *offset += 1;
466        if ch == 'b' {
467            let value = arr[*offset];
468            *offset += 1;
469            if !strict {
470                // if we are not in the strict mode, we will be trying to parse to a string or to some known type
471                if let Ok(v) = chunk_to_str(value) {
472                    if v == "true" {
473                        return Ok(Param::Bool { name, value: true });
474                    } else if v == "false" {
475                        return Ok(Param::Bool { name, value: false });
476                    }
477                    if let Some((year, month, day)) = str_to_date(&v) {
478                        return Ok(Param::Date {
479                            name,
480                            year,
481                            month,
482                            day,
483                        });
484                    }
485                    return Ok(Param::String32 { name, value: v });
486                }
487            }
488            return Ok(Param::Bytes32 { name, value });
489        } else if ch == 'f' {
490            let value = arr[*offset];
491            *offset += 1;
492            match chunk_to_str(value) {
493                Ok(v) => {
494                    if v == "true" {
495                        return Ok(Param::Bool { name, value: true });
496                    } else if v == "false" {
497                        return Ok(Param::Bool { name, value: false });
498                    }
499                    return Err(DecodingError::InvalidBool(v));
500                }
501                Err(e) => {
502                    return Err(DecodingError::InvalidBoolChunk(format!("{}", e)));
503                }
504            };
505        } else if ch == 'u' {
506            let value = arr[*offset];
507            *offset += 1;
508            return Ok(Param::Uint256 { name, value });
509        } else if ch == 'a' {
510            let value = chunk_to_address(arr[*offset]);
511            *offset += 1;
512            return Ok(Param::Address { name, value });
513        } else if ch == 'i' {
514            let (value, sign) = chunk_to_int(arr[*offset]);
515            *offset += 1;
516            return Ok(Param::Int256 { name, value, sign });
517        } else if ch == 's' {
518            let value = arr[*offset];
519            *offset += 1;
520            match chunk_to_str(value) {
521                Ok(s) => return Ok(Param::String32 { name, value: s }),
522                Err(e) => return Err(DecodingError::InvalidChunkString(format!("{}", e))),
523            };
524        } else if ch == 'B' || ch == 'S' {
525            let value_index: usize = arr[*offset].as_usize(); // todo: handle failure
526            *offset += 1;
527            let data_offset = value_index / 32;
528            let value_size: usize = arr[data_offset].as_usize(); // todo: handle failure
529            let value = chunk_to_vec(arr, data_offset + 1, value_size);
530            if ch == 'B' {
531                return Ok(Param::Bytes { name, value });
532            }
533            let s = match String::from_utf8(value) {
534                Ok(s) => s,
535                Err(e) => return Err(DecodingError::InvalidUtf8String(format!("{}", e))),
536            };
537            return Ok(Param::String { name, value: s });
538        }
539        Err(DecodingError::InvalidSchemaCharacter(ch))
540    }
541}
542
543#[cfg(test)]
544mod tests {
545    use super::*;
546    use encode::into32;
547    use ethereum_types::{H160, U256};
548    use hex_literal::hex;
549    use rand::{thread_rng, Rng};
550
551    fn rand_str() -> String {
552        thread_rng()
553            .sample_iter(&rand::distributions::Alphanumeric)
554            .take(30)
555            .map(char::from)
556            .collect()
557    }
558
559    fn rand_vec(sz: usize) -> Vec<u8> {
560        thread_rng()
561            .sample_iter(&rand::distributions::Alphanumeric)
562            .take(sz)
563            .collect()
564    }
565
566    #[test]
567    fn it_encodes_decodes_bytes() {
568        let param = Param::Bytes {
569            name: rand_str(),
570            value: rand_vec(16),
571        };
572        let value = ABI::only(param);
573        let decoded = ABI::decode(&value.encode().unwrap(), true).unwrap();
574        assert_eq!(decoded, value);
575    }
576
577    #[test]
578    fn it_encodes_decodes_string32() {
579        let param = Param::String32 {
580            name: rand_str(),
581            value: rand_str(),
582        };
583        let value = ABI::only(param);
584        let decoded = ABI::decode(&value.encode().unwrap(), true).unwrap();
585        assert_eq!(decoded, value);
586    }
587
588    #[test]
589    fn it_encodes_decodes_string() {
590        let param = Param::String {
591            name: rand_str(),
592            value: rand_str(),
593        };
594        let value = ABI::only(param);
595        let decoded = ABI::decode(&value.encode().unwrap(), true).unwrap();
596        assert_eq!(decoded, value);
597    }
598
599    #[test]
600    fn it_encodes_decodes_bytes32() {
601        let r = rand_vec(32);
602        let param = Param::Bytes32 {
603            name: rand_str(),
604            value: U256::from(into32(&r)),
605        };
606        let value = ABI::only(param);
607        let decoded = ABI::decode(&value.encode().unwrap(), true).unwrap();
608        assert_eq!(decoded, value);
609    }
610
611    #[test]
612    fn it_encodes_decodes_address() {
613        let r = rand_vec(20);
614        let param = Param::Address {
615            name: rand_str(),
616            value: H160::from(H160::from_slice(&r)),
617        };
618        let value = ABI::only(param);
619        let decoded = ABI::decode(&value.encode().unwrap(), true).unwrap();
620        assert_eq!(decoded, value);
621    }
622
623    #[test]
624    fn it_encodes_decodes_uint256() {
625        let r = rand_vec(32);
626        let input = U256::from(into32(&r));
627        let param = Param::Uint256 {
628            name: rand_str(),
629            value: input,
630        };
631        let value = ABI::only(param);
632        let decoded = ABI::decode(&value.encode().unwrap(), true).unwrap();
633        assert_eq!(decoded, value);
634    }
635
636    #[test]
637    fn it_encodes_decodes_int256_positive() {
638        let mut r = rand_vec(32);
639        r[0] &= 0b0111_1111; // Unset the first bit to get positive
640        let input = U256::from(into32(&r));
641        let param = Param::Uint256 {
642            name: rand_str(),
643            value: input,
644        };
645        let value = ABI::only(param);
646        let decoded = ABI::decode(&value.encode().unwrap(), true).unwrap();
647        assert_eq!(decoded, value);
648    }
649
650    #[test]
651    fn it_encodes_decodes_int256_negative() {
652        let mut r = rand_vec(32);
653        r[0] |= 0b1000_0000; // Set the first bit to get negative
654        let input = U256::from(into32(&r));
655        let param = Param::Uint256 {
656            name: rand_str(),
657            value: input,
658        };
659        let value = ABI::only(param);
660        let decoded = ABI::decode(&value.encode().unwrap(), true).unwrap();
661        assert_eq!(decoded, value);
662    }
663
664    #[test]
665    fn it_encodes_empty() {
666        let value = ABI::none().encode().unwrap();
667        let expected: U256 =
668            hex!("3100000000000000000000000000000000000000000000000000000000000000").into();
669        assert_eq!(value, vec![expected]);
670    }
671
672    #[test]
673    fn it_decodes_empty() {
674        let data: Vec<U256> =
675            vec![hex!("3100000000000000000000000000000000000000000000000000000000000000").into()];
676        let res = ABI::decode(&data, true).unwrap();
677        assert_eq!(res, ABI::none());
678    }
679
680    #[test]
681    fn it_decodes_address() {
682        let data: Vec<U256> = vec![
683            hex!("3161000000000000000000000000000000000000000000000000000000000000").into(),
684            hex!("54657374416464726573734e616d650000000000000000000000000000000000").into(),
685            hex!("0000000000000000000000004128922394c63a204dd98ea6fbd887780b78bb7d").into(),
686        ];
687        let res = ABI::decode(&data, true).unwrap();
688        let expected = ABI::only(Param::Address {
689            name: "TestAddressName".to_owned(),
690            value: hex!("4128922394C63A204Dd98ea6fbd887780b78bb7d").into(),
691        });
692        assert_eq!(res, expected);
693    }
694
695    #[test]
696    fn it_decodes_int256() {
697        let data: Vec<U256> = vec![
698            hex!("3169000000000000000000000000000000000000000000000000000000000000").into(),
699            hex!("54657374496e744e616d65000000000000000000000000000000000000000000").into(),
700            hex!("fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc18").into(),
701        ];
702        let res = ABI::decode(&data, true).unwrap();
703        let expected = ABI::only(Param::Int256 {
704            name: "TestIntName".to_owned(),
705            value: U256::from(1000),
706            sign: -1,
707        });
708        assert_eq!(res, expected);
709    }
710
711    #[test]
712    fn it_decodes_uint256() {
713        let data: Vec<U256> = vec![
714            hex!("3175000000000000000000000000000000000000000000000000000000000000").into(),
715            hex!("5465737455496e744e616d650000000000000000000000000000000000000000").into(),
716            hex!("00000000000000000000000000000000000000000000000000000000000007d0").into(),
717        ];
718        let res = ABI::decode(&data, true).unwrap();
719        let expected = ABI::only(Param::Uint256 {
720            name: "TestUIntName".to_owned(),
721            value: U256::from(2000),
722        });
723        assert_eq!(res, expected);
724    }
725
726    #[test]
727    fn it_decodes_bytes() {
728        let data: Vec<U256> = vec![
729            hex!("3142000000000000000000000000000000000000000000000000000000000000").into(),
730            hex!("5465737442797465734e616d6500000000000000000000000000000000000000").into(),
731            hex!("0000000000000000000000000000000000000000000000000000000000000060").into(),
732            hex!("0000000000000000000000000000000000000000000000000000000000000003").into(),
733            hex!("123abc0000000000000000000000000000000000000000000000000000000000").into(),
734        ];
735        let res = ABI::decode(&data, true).unwrap();
736        let expected = ABI::only(Param::Bytes {
737            name: "TestBytesName".to_owned(),
738            value: vec![0x12, 0x3a, 0xbc],
739        });
740        assert_eq!(res, expected);
741    }
742
743    #[test]
744    fn it_decodes_bytes32() {
745        let data: Vec<U256> = vec![
746            hex!("3162000000000000000000000000000000000000000000000000000000000000").into(),
747            hex!("54657374427974657333324e616d650000000000000000000000000000000000").into(),
748            hex!("536f6d6520627974657333322076616c75650000000000000000000000000000").into(),
749        ];
750        let res = ABI::decode(&data, true).unwrap(); // strict mode "on" is importnant
751        let expected = ABI::only(Param::Bytes32 {
752            name: "TestBytes32Name".to_owned(),
753            value: hex!("536f6d6520627974657333322076616c75650000000000000000000000000000").into(),
754        });
755        assert_eq!(res, expected);
756    }
757
758    #[test]
759    fn it_decodes_string32() {
760        let data: Vec<U256> = vec![
761            hex!("3162000000000000000000000000000000000000000000000000000000000000").into(),
762            hex!("54657374427974657333324e616d650000000000000000000000000000000000").into(),
763            hex!("536f6d6520627974657333322076616c75650000000000000000000000000000").into(),
764        ];
765        let res = ABI::decode(&data, false).unwrap(); // strict mode "off"
766        let expected = ABI::only(Param::String32 {
767            name: "TestBytes32Name".to_owned(),
768            value: "Some bytes32 value".to_owned(),
769        });
770        assert_eq!(res, expected);
771    }
772
773    #[test]
774    fn it_decodes_date() {
775        let data: Vec<U256> = vec![
776            hex!("3162000000000000000000000000000000000000000000000000000000000000").into(),
777            hex!("73746172745F6461746500000000000000000000000000000000000000000000").into(),
778            hex!("323032312D30312D313900000000000000000000000000000000000000000000").into(),
779        ];
780        let res = ABI::decode(&data, false).unwrap(); // strict mode "off" is importnant
781        let expected = ABI::only(Param::Date {
782            name: "start_date".to_owned(),
783            year: 2021,
784            month: 1,
785            day: 19,
786        });
787        assert_eq!(res, expected);
788    }
789
790    #[test]
791    fn it_encodes_decodes_date() {
792        let param = Param::Date {
793            name: "start_date".to_owned(),
794            year: 2021,
795            month: 1,
796            day: 19,
797        };
798        let value = ABI::only(param);
799        let decoded = ABI::decode(&value.encode().unwrap(), false).unwrap();
800        assert_eq!(decoded, value);
801    }
802
803    #[test]
804    fn it_encodes_decodes_true() {
805        let param = Param::Bool {
806            name: "some bool".to_owned(),
807            value: true,
808        };
809        let value = ABI::only(param);
810        let decoded = ABI::decode(&value.encode().unwrap(), false).unwrap();
811        assert_eq!(decoded, value);
812        let decoded = ABI::decode(&value.encode().unwrap(), true).unwrap();
813        assert_eq!(decoded, value);
814    }
815
816    #[test]
817    fn it_encodes_decodes_false() {
818        let param = Param::Bool {
819            name: "some bool".to_owned(),
820            value: false,
821        };
822        let value = ABI::only(param);
823        let decoded = ABI::decode(&value.encode().unwrap(), false).unwrap();
824        assert_eq!(decoded, value);
825        let decoded = ABI::decode(&value.encode().unwrap(), true).unwrap();
826        assert_eq!(decoded, value);
827    }
828
829    #[test]
830    fn it_decodes_true_from_bytes() {
831        let data: Vec<U256> = vec![
832            hex!("3162000000000000000000000000000000000000000000000000000000000000").into(),
833            hex!("54657374426F6F6C000000000000000000000000000000000000000000000000").into(),
834            hex!("7472756500000000000000000000000000000000000000000000000000000000").into(),
835        ];
836        let res = ABI::decode(&data, false).unwrap(); // strict mode "off" is importnant
837        let expected = ABI::only(Param::Bool {
838            name: "TestBool".to_owned(),
839            value: true,
840        });
841        assert_eq!(res, expected);
842    }
843
844    #[test]
845    fn it_decodes_false_from_bytes() {
846        let data: Vec<U256> = vec![
847            hex!("3162000000000000000000000000000000000000000000000000000000000000").into(),
848            hex!("54657374426F6F6C000000000000000000000000000000000000000000000000").into(),
849            hex!("66616C7365000000000000000000000000000000000000000000000000000000").into(),
850        ];
851        let res = ABI::decode(&data, false).unwrap(); // strict mode "off" is importnant
852        let expected = ABI::only(Param::Bool {
853            name: "TestBool".to_owned(),
854            value: false,
855        });
856        assert_eq!(res, expected);
857    }
858
859    #[test]
860    fn it_decodes_string() {
861        let data: Vec<U256> = vec![
862            hex!("3153000000000000000000000000000000000000000000000000000000000000").into(),
863            hex!("54657374537472696e674e616d65000000000000000000000000000000000000").into(),
864            hex!("0000000000000000000000000000000000000000000000000000000000000060").into(),
865            hex!("0000000000000000000000000000000000000000000000000000000000000011").into(),
866            hex!("536f6d6520737472696e672076616c7565000000000000000000000000000000").into(),
867        ];
868        let res = ABI::decode(&data, true).unwrap();
869        let expected = ABI::only(Param::String {
870            name: "TestStringName".to_owned(),
871            value: "Some string value".to_owned(),
872        });
873        assert_eq!(res, expected);
874    }
875
876    #[test]
877    fn it_decodes_multiple() {
878        let data: Vec<U256> = vec![
879            hex!("3162615369427500000000000000000000000000000000000000000000000000").into(), //:00, 1baSiBu
880            hex!("62797465733332206e616d650000000000000000000000000000000000000000").into(), //:20  "bytes name"
881            hex!("62797465732033322076616c7565000000000000000000000000000000000000").into(), //:40  "bytes 32 value"
882            hex!("77616c6c65740000000000000000000000000000000000000000000000000000").into(), //:60  "wallet"
883            hex!("0000000000000000000000004128922394c63a204dd98ea6fbd887780b78bb7d").into(), //:80  0x4128922394C63A204Dd98ea6fbd887780b78bb7d
884            hex!("737472696e67206e616d65000000000000000000000000000000000000000000").into(), //:a0  "string name"
885            hex!("00000000000000000000000000000000000000000000000000000000000001a0").into(), //:c0  offs: 1a0
886            hex!("62616c616e636500000000000000000000000000000000000000000000000000").into(), //:e0  "balance"
887            hex!("ffffffffffffffffffffffffffffffffffffffffffffffff7538dcfb76180000").into(), //:10  -10000000000000000000
888            hex!("6279746573206e616d6500000000000000000000000000000000000000000000").into(), //:12  "bytes name"
889            hex!("00000000000000000000000000000000000000000000000000000000000001e0").into(), //:14  offs: 1e0
890            hex!("686f6c6465727300000000000000000000000000000000000000000000000000").into(), //:16  "holders"
891            hex!("000000000000000000000000000000000000000000000001158e460913d00000").into(), //:18  20000000000000000000
892            hex!("000000000000000000000000000000000000000000000000000000000000000c").into(), //:1a  size: 12 bytes    [13]
893            hex!("737472696e672076616c75650000000000000000000000000000000000000000").into(), //:1c  "string value"
894            hex!("0000000000000000000000000000000000000000000000000000000000000003").into(), //:1e  size: 3 bytes     [15]
895            hex!("123abc0000000000000000000000000000000000000000000000000000000000").into(), //:20  [0x12, 0x3a, 0xbc]
896        ];
897        let res = ABI::decode(&data, true).unwrap();
898        let expected = ABI::new(vec![
899            Param::Bytes32 {
900                name: "bytes32 name".to_owned(),
901                value: encode::str_chunk32("bytes 32 value").unwrap(),
902            },
903            Param::Address {
904                name: "wallet".to_owned(),
905                value: hex!("4128922394C63A204Dd98ea6fbd887780b78bb7d").into(),
906            },
907            Param::String {
908                name: "string name".to_owned(),
909                value: "string value".to_owned(),
910            },
911            Param::Int256 {
912                name: "balance".to_owned(),
913                value: U256::from_dec_str("10000000000000000000").unwrap(),
914                sign: -1,
915            },
916            Param::Bytes {
917                name: "bytes name".to_owned(),
918                value: hex!("123abc").into(),
919            },
920            Param::Uint256 {
921                name: "holders".to_owned(),
922                value: U256::from_dec_str("20000000000000000000").unwrap(),
923            },
924        ]);
925        assert_eq!(res, expected);
926    }
927
928    #[test]
929    #[should_panic]
930    fn it_shouldnt_decode_zero() {
931        let data: Vec<U256> = vec![U256::from(0)];
932        ABI::decode(&data, true).unwrap();
933    }
934
935    #[test]
936    fn it_shouldnt_decode_invalid_version() {
937        // checking every number except the valid version
938        for i in 0..255 {
939            let ch = format!("{:x}", i).chars().next().unwrap();
940            if ch != '1' {
941                break;
942            }
943            let mut b = rand_vec(32);
944            b[0] = i;
945            let data: Vec<U256> = vec![U256::from(into32(&b))];
946            if let Ok(_) = ABI::decode(&data, true) {
947                panic!("decodes data, started with 0x{:x} {:?}", i, data);
948            }
949        }
950    }
951}