ethers_core/abi/
mod.rs

1//! Extensions to the [`ethabi`](https://docs.rs/ethabi) API.
2//!
3//! Adapted from [Gnosis' `ethcontract-rs`](https://github.com/gnosis/ethcontract-rs).
4
5use crate::{
6    types::{self, Selector, Uint8, H256, H512, I256, U128, U256, U64},
7    utils::id,
8};
9pub use ethabi::{self, Contract as Abi, *};
10
11mod tokens;
12pub use tokens::{Detokenize, InvalidOutputType, Tokenizable, TokenizableItem, Tokenize};
13
14pub mod struct_def;
15pub use struct_def::SolStruct;
16
17mod codec;
18pub use codec::{AbiDecode, AbiEncode};
19
20mod error;
21pub use error::{AbiError, ParseError};
22
23mod human_readable;
24pub use human_readable::{
25    lexer::HumanReadableParser, parse as parse_abi, parse_str as parse_abi_str, AbiParser,
26};
27
28mod raw;
29pub use raw::{AbiObject, Component, Item, JsonAbi, RawAbi};
30
31mod packed;
32pub use packed::{encode_packed, EncodePackedError};
33
34mod sealed {
35    use ethabi::{Event, Function};
36
37    /// private trait to ensure extension traits are used as intended
38    pub trait Sealed {}
39    impl Sealed for Function {}
40    impl Sealed for Event {}
41    impl Sealed for ethabi::AbiError {}
42}
43
44/// Extension trait for `ethabi::Function`.
45pub trait FunctionExt: sealed::Sealed {
46    /// Compute the method signature in the standard ABI format. This does not
47    /// include the output types.
48    fn abi_signature(&self) -> String;
49
50    /// Compute the Keccak256 function selector used by contract ABIs.
51    fn selector(&self) -> Selector;
52}
53
54impl FunctionExt for Function {
55    fn abi_signature(&self) -> String {
56        let mut full_signature = self.signature();
57        if let Some(colon) = full_signature.find(':') {
58            full_signature.truncate(colon);
59        }
60
61        full_signature
62    }
63
64    fn selector(&self) -> Selector {
65        id(self.abi_signature())
66    }
67}
68
69/// Extension trait for `ethabi::Event`.
70pub trait EventExt: sealed::Sealed {
71    /// Compute the event signature in human-readable format. The `keccak256`
72    /// hash of this value is the actual event signature that is used as topic0
73    /// in the transaction logs.
74    fn abi_signature(&self) -> String;
75}
76
77impl EventExt for Event {
78    fn abi_signature(&self) -> String {
79        format!(
80            "{}({}){}",
81            self.name,
82            self.inputs.iter().map(|input| input.kind.to_string()).collect::<Vec<_>>().join(","),
83            if self.anonymous { " anonymous" } else { "" },
84        )
85    }
86}
87
88/// Extension trait for `ethabi::AbiError`.
89pub trait ErrorExt: sealed::Sealed {
90    /// Compute the method signature in the standard ABI format.
91    fn abi_signature(&self) -> String;
92
93    /// Compute the Keccak256 error selector used by contract ABIs.
94    fn selector(&self) -> Selector;
95}
96
97impl ErrorExt for ethabi::AbiError {
98    fn abi_signature(&self) -> String {
99        if self.inputs.is_empty() {
100            return format!("{}()", self.name)
101        }
102        let inputs = self.inputs.iter().map(|p| p.kind.to_string()).collect::<Vec<_>>().join(",");
103        format!("{}({inputs})", self.name)
104    }
105
106    fn selector(&self) -> Selector {
107        id(self.abi_signature())
108    }
109}
110
111/// A trait for types that can be represented in the Ethereum ABI.
112pub trait AbiType {
113    /// The native ABI type this type represents.
114    fn param_type() -> ParamType;
115
116    /// A hint of the minimum number of bytes this type takes up in the ABI.
117    fn minimum_size() -> usize {
118        minimum_size(&Self::param_type())
119    }
120}
121
122/// Returns the minimum number of bytes that `ty` takes up in the ABI.
123pub fn minimum_size(ty: &ParamType) -> usize {
124    match ty {
125        // 1 word
126        ParamType::Uint(_) |
127        ParamType::Int(_) |
128        ParamType::Bool |
129        ParamType::Address |
130        ParamType::FixedBytes(_) => 32,
131        // min 2 words (offset, length)
132        ParamType::Bytes | ParamType::String | ParamType::Array(_) => 64,
133        // sum of all elements
134        ParamType::FixedArray(ty, len) => minimum_size(ty) * len,
135        ParamType::Tuple(tys) => tys.iter().map(minimum_size).sum(),
136    }
137}
138
139impl AbiType for u8 {
140    fn param_type() -> ParamType {
141        ParamType::Uint(8)
142    }
143}
144
145/// Additional trait for types that can appear in arrays
146///
147/// NOTE: this is necessary to handle the special case of `Vec<u8> => Bytes`
148pub trait AbiArrayType: AbiType {}
149
150impl<T: AbiArrayType> AbiType for Vec<T> {
151    fn param_type() -> ParamType {
152        ParamType::Array(Box::new(T::param_type()))
153    }
154}
155impl<T: AbiArrayType> AbiArrayType for Vec<T> {}
156
157impl<T: AbiArrayType, const N: usize> AbiType for [T; N] {
158    fn param_type() -> ParamType {
159        ParamType::FixedArray(Box::new(T::param_type()), N)
160    }
161}
162
163impl<T: AbiArrayType, const N: usize> AbiArrayType for [T; N] {}
164
165impl<const N: usize> AbiType for [u8; N] {
166    fn param_type() -> ParamType {
167        ParamType::FixedBytes(N)
168    }
169}
170impl<const N: usize> AbiArrayType for [u8; N] {}
171
172macro_rules! impl_abi_type {
173    ($($name:ty => $var:ident $(($value:expr))? ),*) => {
174        $(
175            impl AbiType for $name {
176                fn param_type() -> ParamType {
177                    ParamType::$var $( ($value) )?
178                }
179            }
180
181            impl AbiArrayType for $name {}
182        )*
183    };
184}
185
186impl_abi_type!(
187    types::Bytes => Bytes,
188    bytes::Bytes => Bytes,
189    Vec<u8> =>  Array(Box::new(ParamType::Uint(8))),
190    Address => Address,
191    bool => Bool,
192    String => String,
193    str => String,
194    H256 => FixedBytes(32),
195    H512 => FixedBytes(64),
196    Uint8 => Uint(8),
197    U64 => Uint(64),
198    U128 => Uint(128),
199    U256 => Uint(256),
200    u16 => Uint(16),
201    u32 => Uint(32),
202    u64 => Uint(64),
203    u128 => Uint(128),
204    i8 => Int(8),
205    i16 => Int(16),
206    i32 => Int(32),
207    i64 => Int(64),
208    i128 => Int(128),
209    I256 => Int(256)
210);
211
212impl<'a> AbiType for &'a str {
213    fn param_type() -> ParamType {
214        ParamType::String
215    }
216}
217
218impl<'a> AbiArrayType for &'a str {}
219
220macro_rules! impl_abi_type_tuple {
221    ($( $ty: ident),+) => {
222        impl<$($ty, )+> AbiType for ($($ty,)+) where
223            $(
224                $ty: AbiType,
225            )+
226        {
227            fn param_type() -> ParamType {
228                ParamType::Tuple(
229                    ::std::vec![
230                         $(
231                           $ty::param_type(),
232                        )+
233                    ]
234                )
235            }
236        }
237
238        impl<$($ty, )+> AbiArrayType for ($($ty,)+) where
239            $(
240                $ty: AbiType,
241            )+ {}
242    }
243}
244
245impl_abi_type_tuple!(A);
246impl_abi_type_tuple!(A, B);
247impl_abi_type_tuple!(A, B, C);
248impl_abi_type_tuple!(A, B, C, D);
249impl_abi_type_tuple!(A, B, C, D, E);
250impl_abi_type_tuple!(A, B, C, D, E, F);
251impl_abi_type_tuple!(A, B, C, D, E, F, G);
252impl_abi_type_tuple!(A, B, C, D, E, F, G, H);
253impl_abi_type_tuple!(A, B, C, D, E, F, G, H, I);
254impl_abi_type_tuple!(A, B, C, D, E, F, G, H, I, J);
255impl_abi_type_tuple!(A, B, C, D, E, F, G, H, I, J, K);
256impl_abi_type_tuple!(A, B, C, D, E, F, G, H, I, J, K, L);
257impl_abi_type_tuple!(A, B, C, D, E, F, G, H, I, J, K, L, M);
258impl_abi_type_tuple!(A, B, C, D, E, F, G, H, I, J, K, L, M, N);
259impl_abi_type_tuple!(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O);
260impl_abi_type_tuple!(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P);
261impl_abi_type_tuple!(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q);
262impl_abi_type_tuple!(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R);
263impl_abi_type_tuple!(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S);
264impl_abi_type_tuple!(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T);
265impl_abi_type_tuple!(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U);
266
267#[allow(clippy::extra_unused_type_parameters)]
268#[cfg(test)]
269mod tests {
270    use super::*;
271
272    #[test]
273    fn format_function_signature() {
274        for (f, expected) in &[
275            (
276                r#"{"name":"foo","inputs":[],"outputs":[], "stateMutability": "nonpayable"}"#,
277                "foo()",
278            ),
279            (
280                r#"{"name":"bar","inputs":[{"name":"a","type":"uint256"},{"name":"b","type":"bool"}],"outputs":[], "stateMutability": "nonpayable"}"#,
281                "bar(uint256,bool)",
282            ),
283            (
284                r#"{"name":"baz","inputs":[{"name":"a","type":"uint256"}],"outputs":[{"name":"b","type":"bool"}], "stateMutability": "nonpayable"}"#,
285                "baz(uint256)",
286            ),
287            (
288                r#"{"name":"bax","inputs":[],"outputs":[{"name":"a","type":"uint256"},{"name":"b","type":"bool"}], "stateMutability": "nonpayable"}"#,
289                "bax()",
290            ),
291        ] {
292            let function: Function = serde_json::from_str(f).expect("invalid function JSON");
293            let signature = function.abi_signature();
294            assert_eq!(signature, *expected);
295        }
296    }
297
298    #[test]
299    fn format_event_signature() {
300        for (e, expected) in &[
301            (r#"{"name":"foo","inputs":[],"anonymous":false}"#, "foo()"),
302            (
303                r#"{"name":"bar","inputs":[{"name":"a","type":"uint256"},{"name":"b","type":"bool"}],"anonymous":false}"#,
304                "bar(uint256,bool)",
305            ),
306            (
307                r#"{"name":"baz","inputs":[{"name":"a","type":"uint256"}],"anonymous":true}"#,
308                "baz(uint256) anonymous",
309            ),
310            (r#"{"name":"bax","inputs":[],"anonymous":true}"#, "bax() anonymous"),
311        ] {
312            let event: Event = serde_json::from_str(e).expect("invalid event JSON");
313            let signature = event.abi_signature();
314            assert_eq!(signature, *expected);
315        }
316    }
317
318    #[test]
319    fn abi_type_works() {
320        assert_eq!(ParamType::Bytes, types::Bytes::param_type());
321        assert_eq!(ParamType::Array(Box::new(ParamType::Uint(8))), Vec::<u8>::param_type());
322        assert_eq!(ParamType::Array(Box::new(ParamType::Bytes)), Vec::<types::Bytes>::param_type());
323        assert_eq!(
324            ParamType::Array(Box::new(ParamType::Array(Box::new(ParamType::Uint(8))))),
325            Vec::<Vec<u8>>::param_type()
326        );
327        assert_eq!(
328            ParamType::Array(Box::new(ParamType::Array(Box::new(ParamType::Array(Box::new(
329                ParamType::Uint(8)
330            )))))),
331            Vec::<Vec<Vec<u8>>>::param_type()
332        );
333
334        assert_eq!(ParamType::Array(Box::new(ParamType::Uint(16))), Vec::<u16>::param_type());
335
336        assert_eq!(
337            ParamType::Tuple(vec![ParamType::Bytes, ParamType::Address]),
338            <(types::Bytes, Address)>::param_type()
339        );
340
341        assert_eq!(ParamType::FixedBytes(32), <[u8; 32]>::param_type());
342        assert_eq!(
343            ParamType::Array(Box::new(ParamType::FixedBytes(32))),
344            Vec::<[u8; 32]>::param_type()
345        );
346
347        assert_eq!(
348            ParamType::FixedArray(Box::new(ParamType::Uint(16)), 32),
349            <[u16; 32]>::param_type()
350        );
351
352        assert_eq!(ParamType::String, str::param_type());
353        assert_eq!(ParamType::String, <&str>::param_type());
354    }
355
356    #[test]
357    fn abi_type_tuples_work() {
358        fn assert_abitype<T: AbiType>() {}
359        fn assert_abiarraytype<T: AbiArrayType>() {}
360
361        assert_abitype::<(u64, u64)>();
362        assert_abiarraytype::<(u64, u64)>();
363
364        assert_abitype::<(u8, u8)>();
365        assert_abiarraytype::<(u8, u8)>();
366
367        assert_abitype::<Vec<(u64, u64)>>();
368        assert_abiarraytype::<Vec<(u64, u64)>>();
369
370        assert_abitype::<Vec<(u8, u8)>>();
371        assert_abiarraytype::<Vec<(u8, u8)>>();
372    }
373}