evm_coder/abi/
traits.rs

1use core::str::from_utf8;
2
3use super::{AbiDecoder, AbiEncoder, Error};
4use crate::{abi::Result, custom_signature::SignatureUnit, types::*};
5
6/// Helper for type.
7pub trait AbiType {
8	/// Signature for Ethereum ABI.
9	const SIGNATURE: SignatureUnit;
10	/// Is this a dynamic type, per spec.
11	const IS_DYNAMIC: bool;
12	/// How many AbiWords static data this type should occupy
13	const HEAD_WORDS: u32;
14
15	/// Signature as str.
16	#[must_use]
17	fn signature() -> &'static str {
18		from_utf8(&Self::SIGNATURE.data[..Self::SIGNATURE.len]).expect("bad utf-8")
19	}
20}
21impl<T> AbiType for &T
22where
23	T: AbiType,
24{
25	const SIGNATURE: SignatureUnit = T::SIGNATURE;
26	const IS_DYNAMIC: bool = T::IS_DYNAMIC;
27	const HEAD_WORDS: u32 = T::HEAD_WORDS;
28}
29
30/// Encode value using ABI encoding.
31pub trait AbiEncode: Sized + AbiType {
32	fn enc(&self, out: &mut AbiEncoder);
33	fn abi_encode(&self) -> Vec<u8> {
34		let mut encoder = AbiEncoder::new(vec![], 0, 0);
35		encoder.encode_tail(self);
36		encoder.into_inner()
37	}
38	fn abi_encode_call(&self, selector: Bytes4) -> Vec<u8> {
39		let mut encoder = AbiEncoder::new(selector.into(), 4, 4);
40		encoder.encode_tail(self);
41		encoder.into_inner()
42	}
43}
44impl<T> AbiEncode for &T
45where
46	T: AbiEncode,
47{
48	fn enc(&self, out: &mut AbiEncoder) {
49		(*self).enc(out);
50	}
51}
52pub trait AbiEncodeZero: AbiEncode {
53	fn enc_zero(out: &mut AbiEncoder);
54}
55impl<T: Default + AbiEncode> AbiEncodeZero for T {
56	fn enc_zero(out: &mut AbiEncoder) {
57		T::default().enc(out)
58	}
59}
60
61/// Decode ABI value.
62pub trait AbiDecode: Sized + AbiType {
63	fn dec(input: &mut AbiDecoder<'_>) -> Result<Self>;
64	fn abi_decode(input: &[u8]) -> Result<Self> {
65		let mut decoder = AbiDecoder::new(input, 0)?;
66		Self::dec(&mut decoder)
67	}
68	fn abi_decode_call(input: &[u8]) -> Result<(Bytes4, Self)> {
69		let mut num = [0; 4];
70		num.copy_from_slice(&input[..4]);
71		Ok((BytesFixed(num), Self::abi_decode(&input[4..])?))
72	}
73}
74/// Assert read value is zero.
75pub trait AbiDecodeZero: AbiDecode {
76	fn dec_zero(input: &mut AbiDecoder<'_>) -> Result<()>;
77}
78impl<T: Default + AbiDecode + PartialEq> AbiDecodeZero for T {
79	fn dec_zero(input: &mut AbiDecoder<'_>) -> Result<()> {
80		let value = T::dec(input)?;
81		if value != T::default() {
82			return Err(Error::InvalidRange);
83		}
84		Ok(())
85	}
86}