solidity_abi/
lib.rs

1// Copyright 2020 Conflux Foundation. All rights reserved.
2// Conflux is free software and distributed under GNU General Public License.
3// See http://www.gnu.org/licenses/
4
5mod array;
6mod basic;
7mod bytes;
8mod string;
9
10#[cfg(test)]
11mod tests;
12mod utils;
13
14pub use self::utils::{
15    read_abi_list, string_revert_reason_decode, ABIListWriter, LinkedBytes,
16};
17use cfx_types::H256;
18use keccak_hash::keccak;
19
20#[derive(Debug, PartialEq)]
21pub struct ABIDecodeError(pub &'static str);
22
23/// A type implements `ABIDecodable` must be a tuple of types implement
24/// `ABIVariable`. For convenient, for the tuple with only one element like
25/// `(U256,)`, we implement `ABIDecodable` for `U256` instead.
26pub trait ABIDecodable: Sized {
27    fn abi_decode(data: &[u8]) -> Result<Self, ABIDecodeError>;
28}
29
30/// A type implements `ABIEncodable` must be a tuple of types implement
31/// `ABIVariable`. For convenient, for the tuple with only one element like
32/// `(U256,)`, we implement `ABIEncodable` for `U256` instead.
33pub trait ABIEncodable: Sized {
34    fn abi_encode(&self) -> Vec<u8>;
35}
36
37/// A type implements `ABIPackedEncodable` must be a tuple of types implement
38/// `ABIVariable`. For convenient, for the tuple with only one element like
39/// `(U256,)`, we implement `ABIPackedEncodable` for `U256` instead.
40pub trait ABIPackedEncodable: Sized {
41    fn abi_packed_encode(&self) -> Vec<u8>;
42}
43
44/// A type implements `EventIndexEncodable` must be a tuple of types implement
45/// `EventIndexEncodable`. For convenient, for the tuple with only one element
46/// like `(U256,)`, we implement `EventIndexEncodable` for `U256` instead.
47pub trait EventIndexEncodable: Sized {
48    fn indexed_event_encode(&self) -> Vec<H256>;
49}
50
51pub trait ABIVariable: Sized {
52    const BASIC_TYPE: bool;
53    const STATIC_LENGTH: Option<usize>;
54
55    fn from_abi(data: &[u8]) -> Result<Self, ABIDecodeError>;
56    fn to_abi(&self) -> LinkedBytes;
57    fn to_packed_abi(&self) -> LinkedBytes;
58}
59
60impl ABIDecodable for () {
61    fn abi_decode(_: &[u8]) -> Result<Self, ABIDecodeError> { Ok(()) }
62}
63
64impl ABIEncodable for () {
65    fn abi_encode(&self) -> Vec<u8> { Vec::new() }
66}
67
68impl ABIPackedEncodable for () {
69    fn abi_packed_encode(&self) -> Vec<u8> { Vec::new() }
70}
71
72impl EventIndexEncodable for () {
73    fn indexed_event_encode(&self) -> Vec<H256> { Vec::new() }
74}
75
76impl<T: ABIVariable> ABIDecodable for T {
77    fn abi_decode(data: &[u8]) -> Result<Self, ABIDecodeError> {
78        Ok(read_abi_list::<T>(data, &mut data.iter())?)
79    }
80}
81
82impl<T: ABIVariable> ABIEncodable for T {
83    fn abi_encode(&self) -> Vec<u8> {
84        let mut recorder =
85            ABIListWriter::with_heads_length(T::STATIC_LENGTH.unwrap_or(32));
86        recorder.write_down(self);
87        recorder.into_linked_bytes().to_vec()
88    }
89}
90
91impl<T: ABIVariable> ABIPackedEncodable for T {
92    fn abi_packed_encode(&self) -> Vec<u8> { self.to_packed_abi().to_vec() }
93}
94
95impl<T: ABIVariable> EventIndexEncodable for T {
96    fn indexed_event_encode(&self) -> Vec<H256> {
97        let answer = if T::BASIC_TYPE {
98            H256::from_slice(&self.to_abi().to_vec())
99        } else {
100            keccak(self.abi_packed_encode())
101        };
102        vec![answer]
103    }
104}
105
106macro_rules! impl_abi_serde {
107    ($( ($idx:tt => $name:ident) ),* ) => {
108        impl<$($name:ABIVariable),*> ABIDecodable for ($($name),* ) {
109            fn abi_decode(data: &[u8]) -> Result<Self, ABIDecodeError> {
110                let mut pointer = data.iter();
111                Ok((
112                    $(read_abi_list::<$name>(data, &mut pointer)?),*
113                ))
114            }
115        }
116
117        impl<$($name:ABIVariable),*> ABIEncodable for ($($name),*) {
118            fn abi_encode(&self) -> Vec<u8> {
119                let heads_length: usize = 0 $( + $name::STATIC_LENGTH.unwrap_or(32) )* ;
120                let mut recorder = ABIListWriter::with_heads_length(heads_length);
121                $(recorder.write_down(&self.$idx);)*
122                recorder.into_linked_bytes().to_vec()
123            }
124        }
125
126        impl<$($name:ABIVariable),*> ABIPackedEncodable for ($($name),*) {
127            fn abi_packed_encode(&self) -> Vec<u8> {
128                let mut recorder = LinkedBytes::new();
129                $(recorder.append(&mut self.$idx.to_packed_abi());)*
130                recorder.to_vec()
131            }
132        }
133
134        impl<$($name:ABIVariable),*> EventIndexEncodable for ($($name),*) {
135            fn indexed_event_encode(&self) -> Vec<H256> {
136                let mut answer = Vec::new();
137                $(answer.push(if $name::BASIC_TYPE {
138                    H256::from_slice(&self.$idx.to_abi().to_vec())
139                } else {
140                    keccak(self.$idx.abi_packed_encode())
141                });)*
142                answer
143            }
144        }
145    };
146}
147
148// Now we supply a function/events with at most five parameters
149impl_abi_serde!((0=>A),(1=>B));
150impl_abi_serde!((0=>A),(1=>B),(2=>C));
151impl_abi_serde!((0=>A),(1=>B),(2=>C),(3=>D));
152impl_abi_serde!((0=>A),(1=>B),(2=>C),(3=>D),(4=>E));