zabi/
encoding.rs

1//! ABI encoding and decoding functionality for Ethereum ABI.
2
3use crate::result::{Error, Result};
4
5/// ABI encode a value
6pub trait AbiEncode {
7    /// Encode the value according to Ethereum ABI rules
8    fn abi_encode(&self) -> Vec<u8>;
9}
10
11/// ABI decode a value
12pub trait AbiDecode: Sized {
13    /// Decode a value from Ethereum ABI encoded bytes
14    fn abi_decode(data: &[u8]) -> std::result::Result<Self, DecodeError>;
15}
16
17/// Errors that can occur during ABI decoding
18#[derive(Debug)]
19pub enum DecodeError {
20    InvalidData,
21    UnsupportedType,
22}
23
24impl From<DecodeError> for Error {
25    fn from(_e: DecodeError) -> Self {
26        Error::Postcard(postcard::Error::SerializeBufferFull)
27    }
28}
29
30impl AbiEncode for bool {
31    fn abi_encode(&self) -> Vec<u8> {
32        let mut result = vec![0u8; 32];
33        if *self {
34            result[31] = 1;
35        }
36        result
37    }
38}
39
40impl AbiDecode for bool {
41    fn abi_decode(data: &[u8]) -> std::result::Result<Self, DecodeError> {
42        if data.len() < 32 {
43            return Err(DecodeError::InvalidData);
44        }
45        Ok(data[31] != 0)
46    }
47}
48
49impl AbiEncode for u8 {
50    fn abi_encode(&self) -> Vec<u8> {
51        let mut result = vec![0u8; 32];
52        result[31] = *self;
53        result
54    }
55}
56
57impl AbiDecode for u8 {
58    fn abi_decode(data: &[u8]) -> std::result::Result<Self, DecodeError> {
59        if data.len() < 32 {
60            return Err(DecodeError::InvalidData);
61        }
62        Ok(data[31])
63    }
64}
65
66impl AbiEncode for u16 {
67    fn abi_encode(&self) -> Vec<u8> {
68        let mut result = vec![0u8; 32];
69        result[30..32].copy_from_slice(&self.to_be_bytes());
70        result
71    }
72}
73
74impl AbiDecode for u16 {
75    fn abi_decode(data: &[u8]) -> std::result::Result<Self, DecodeError> {
76        if data.len() < 32 {
77            return Err(DecodeError::InvalidData);
78        }
79        let mut bytes = [0u8; 2];
80        bytes.copy_from_slice(&data[30..32]);
81        Ok(u16::from_be_bytes(bytes))
82    }
83}
84
85impl AbiEncode for u32 {
86    fn abi_encode(&self) -> Vec<u8> {
87        let mut result = vec![0u8; 32];
88        result[28..32].copy_from_slice(&self.to_be_bytes());
89        result
90    }
91}
92
93impl AbiDecode for u32 {
94    fn abi_decode(data: &[u8]) -> std::result::Result<Self, DecodeError> {
95        if data.len() < 32 {
96            return Err(DecodeError::InvalidData);
97        }
98        let mut bytes = [0u8; 4];
99        bytes.copy_from_slice(&data[28..32]);
100        Ok(u32::from_be_bytes(bytes))
101    }
102}
103
104impl AbiEncode for u64 {
105    fn abi_encode(&self) -> Vec<u8> {
106        let mut result = vec![0u8; 32];
107        result[24..32].copy_from_slice(&self.to_be_bytes());
108        result
109    }
110}
111
112impl AbiDecode for u64 {
113    fn abi_decode(data: &[u8]) -> std::result::Result<Self, DecodeError> {
114        if data.len() < 32 {
115            return Err(DecodeError::InvalidData);
116        }
117        let mut bytes = [0u8; 8];
118        bytes.copy_from_slice(&data[24..32]);
119        Ok(u64::from_be_bytes(bytes))
120    }
121}
122
123impl AbiEncode for u128 {
124    fn abi_encode(&self) -> Vec<u8> {
125        let mut result = vec![0u8; 32];
126        result[16..32].copy_from_slice(&self.to_be_bytes());
127        result
128    }
129}
130
131impl AbiDecode for u128 {
132    fn abi_decode(data: &[u8]) -> std::result::Result<Self, DecodeError> {
133        if data.len() < 32 {
134            return Err(DecodeError::InvalidData);
135        }
136        let mut bytes = [0u8; 16];
137        bytes.copy_from_slice(&data[16..32]);
138        Ok(u128::from_be_bytes(bytes))
139    }
140}
141
142// ### Standalone Functions for Address and U256
143
144/// Encode an address (20 bytes) into ABI format
145#[allow(dead_code)]
146pub fn encode_address(addr: &[u8; 20]) -> Vec<u8> {
147    let mut result = vec![0u8; 32];
148    result[12..32].copy_from_slice(addr);
149    result
150}
151
152/// Decode an address from ABI-encoded data
153#[allow(dead_code)]
154pub fn decode_address(data: &[u8]) -> std::result::Result<[u8; 20], DecodeError> {
155    if data.len() < 32 {
156        return Err(DecodeError::InvalidData);
157    }
158    let mut bytes = [0u8; 20];
159    bytes.copy_from_slice(&data[12..32]);
160    Ok(bytes)
161}
162
163/// Encode a U256 (32 bytes) into ABI format
164#[allow(dead_code)]
165pub fn encode_u256(value: &[u8; 32]) -> Vec<u8> {
166    value.to_vec()
167}
168
169/// Decode a U256 from ABI-encoded data
170#[allow(dead_code)]
171pub fn decode_u256(data: &[u8]) -> std::result::Result<[u8; 32], DecodeError> {
172    if data.len() < 32 {
173        return Err(DecodeError::InvalidData);
174    }
175    let mut bytes = [0u8; 32];
176    bytes.copy_from_slice(&data[0..32]);
177    Ok(bytes)
178}
179
180impl AbiEncode for String {
181    fn abi_encode(&self) -> Vec<u8> {
182        let bytes = self.as_bytes();
183        let length = bytes.len();
184
185        let mut result = vec![0u8; 32];
186        result[28..32].copy_from_slice(&(32u32).to_be_bytes()); // Offset is 32 bytes
187
188        let mut length_bytes = vec![0u8; 32];
189        length_bytes[28..32].copy_from_slice(&(length as u32).to_be_bytes());
190        result.extend_from_slice(&length_bytes);
191
192        result.extend_from_slice(bytes);
193        let padding_needed = (32 - (bytes.len() % 32)) % 32;
194        result.extend(vec![0u8; padding_needed]);
195
196        result
197    }
198}
199
200impl AbiDecode for String {
201    fn abi_decode(data: &[u8]) -> std::result::Result<Self, DecodeError> {
202        if data.len() < 64 {
203            return Err(DecodeError::InvalidData);
204        }
205
206        let mut offset_bytes = [0u8; 4];
207        offset_bytes.copy_from_slice(&data[28..32]);
208        let offset = u32::from_be_bytes(offset_bytes) as usize;
209
210        if data.len() < offset + 32 {
211            return Err(DecodeError::InvalidData);
212        }
213
214        let mut length_bytes = [0u8; 4];
215        length_bytes.copy_from_slice(&data[offset + 28..offset + 32]);
216        let length = u32::from_be_bytes(length_bytes) as usize;
217
218        if data.len() < offset + 32 + length {
219            return Err(DecodeError::InvalidData);
220        }
221
222        let string_data = &data[offset + 32..offset + 32 + length];
223        String::from_utf8(string_data.to_vec()).map_err(|_| DecodeError::InvalidData)
224    }
225}
226
227impl<T: AbiEncode> AbiEncode for Vec<T> {
228    fn abi_encode(&self) -> Vec<u8> {
229        let length = self.len();
230
231        let mut result = vec![0u8; 32];
232        result[28..32].copy_from_slice(&(32u32).to_be_bytes()); // Offset is 32 bytes
233
234        let mut length_bytes = vec![0u8; 32];
235        length_bytes[28..32].copy_from_slice(&(length as u32).to_be_bytes());
236        result.extend_from_slice(&length_bytes);
237
238        for element in self {
239            result.extend_from_slice(&element.abi_encode());
240        }
241
242        result
243    }
244}
245
246impl<T: AbiDecode> AbiDecode for Vec<T> {
247    fn abi_decode(data: &[u8]) -> std::result::Result<Self, DecodeError> {
248        if data.len() < 64 {
249            return Err(DecodeError::InvalidData);
250        }
251
252        let mut offset_bytes = [0u8; 4];
253        offset_bytes.copy_from_slice(&data[28..32]);
254        let offset = u32::from_be_bytes(offset_bytes) as usize;
255
256        if data.len() < offset + 32 {
257            return Err(DecodeError::InvalidData);
258        }
259
260        let mut length_bytes = [0u8; 4];
261        length_bytes.copy_from_slice(&data[offset + 28..offset + 32]);
262        let length = u32::from_be_bytes(length_bytes) as usize;
263
264        let mut result = Vec::with_capacity(length);
265        let mut pos = offset + 32;
266
267        for _ in 0..length {
268            if data.len() < pos + 32 {
269                return Err(DecodeError::InvalidData);
270            }
271
272            let element = T::abi_decode(&data[pos..pos + 32])?;
273            result.push(element);
274            pos += 32;
275        }
276
277        Ok(result)
278    }
279}
280
281pub fn encode<T: AbiEncode>(value: &T) -> Vec<u8> {
282    value.abi_encode()
283}
284
285pub fn decode<T: AbiDecode>(data: &[u8]) -> Result<T> {
286    T::abi_decode(data).map_err(Into::into)
287}
288
289pub fn is_dynamic_type(solidity_type: &str) -> bool {
290    solidity_type == "string" || solidity_type == "bytes" || solidity_type.ends_with("[]")
291}