api3_common/abi/
encode.rs

1//! ABI encoder.
2
3use crate::abi::types::{Token, Word};
4use crate::Bytes;
5
6/// Converts a u32 to a right aligned array of 32 bytes.
7pub fn pad_u32(value: u32) -> Word {
8    let mut padded = [0u8; 32];
9    padded[28..32].copy_from_slice(&value.to_be_bytes());
10    padded
11}
12
13fn pad_bytes(bytes: &[u8]) -> Vec<Word> {
14    let mut result = vec![pad_u32(bytes.len() as u32)];
15    result.extend(pad_fixed_bytes(bytes));
16    result
17}
18
19fn pad_fixed_bytes(bytes: &[u8]) -> Vec<Word> {
20    let len = (bytes.len() + 31) / 32;
21    let mut result = Vec::with_capacity(len);
22    for i in 0..len {
23        let mut padded = [0u8; 32];
24
25        let to_copy = match i == len - 1 {
26            false => 32,
27            true => match bytes.len() % 32 {
28                0 => 32,
29                x => x,
30            },
31        };
32
33        let offset = 32 * i;
34        padded[..to_copy].copy_from_slice(&bytes[offset..offset + to_copy]);
35        result.push(padded);
36    }
37
38    result
39}
40
41#[derive(Debug)]
42enum Mediate {
43    Raw(Vec<Word>),
44    Prefixed(Vec<Word>),
45}
46
47impl Mediate {
48    fn head_len(&self) -> u32 {
49        match *self {
50            Mediate::Raw(ref raw) => 32 * raw.len() as u32,
51            Mediate::Prefixed(_) => 32,
52        }
53    }
54
55    fn tail_len(&self) -> u32 {
56        match *self {
57            Mediate::Raw(_) => 0,
58            Mediate::Prefixed(ref pre) => pre.len() as u32 * 32,
59        }
60    }
61
62    fn head(&self, suffix_offset: u32) -> Vec<Word> {
63        match *self {
64            Mediate::Raw(ref raw) => raw.clone(),
65            Mediate::Prefixed(_) => vec![pad_u32(suffix_offset)],
66        }
67    }
68
69    fn tail(&self) -> Vec<Word> {
70        match *self {
71            Mediate::Raw(_) => vec![],
72            Mediate::Prefixed(ref raw) => raw.clone(),
73        }
74    }
75}
76
77fn encode_head_tail(mediates: &[Mediate]) -> Vec<Word> {
78    let heads_len = mediates.iter().fold(0, |acc, m| acc + m.head_len());
79
80    let (mut result, len) = mediates.iter().fold(
81        (Vec::with_capacity(heads_len as usize), heads_len),
82        |(mut acc, offset), m| {
83            acc.extend(m.head(offset));
84            (acc, offset + m.tail_len())
85        },
86    );
87
88    let tails = mediates.iter().fold(
89        Vec::with_capacity((len - heads_len) as usize),
90        |mut acc, m| {
91            acc.extend(m.tail());
92            acc
93        },
94    );
95
96    result.extend(tails);
97    result
98}
99
100/// Encodes vector of tokens into ABI compliant vector of bytes.
101pub fn encode(tokens: &[Token]) -> Bytes {
102    let mediates = &tokens.iter().map(encode_token).collect::<Vec<_>>();
103
104    encode_head_tail(mediates)
105        .iter()
106        .flat_map(|word| word.to_vec())
107        .collect()
108}
109
110fn encode_token(token: &Token) -> Mediate {
111    match token {
112        Token::Address(ref address) => {
113            let mut padded = [0u8; 32];
114            padded[12..].copy_from_slice(address);
115            Mediate::Raw(vec![padded])
116        }
117        Token::Bytes(ref bytes) => Mediate::Prefixed(pad_bytes(bytes)),
118        Token::String(ref s) => Mediate::Prefixed(pad_bytes(s.as_bytes())),
119        Token::FixedBytes(ref bytes) => Mediate::Raw(pad_fixed_bytes(bytes)),
120        Token::Uint(uint) => Mediate::Raw(vec![(*uint).into()]),
121        Token::Int(int) => Mediate::Raw(vec![(*int).into()]),
122    }
123}
124
125#[cfg(test)]
126mod tests {
127    use crate::abi::encode::{encode, pad_u32};
128    use crate::abi::Token;
129    use hex_literal::hex;
130
131    #[test]
132    fn encode_address() {
133        let address = Token::Address([0x11u8; 20].into());
134        let encoded = encode(&[address]);
135        let expected = hex!("0000000000000000000000001111111111111111111111111111111111111111");
136        assert_eq!(encoded, expected);
137    }
138
139    #[test]
140    fn encode_two_addresses() {
141        let address1 = Token::Address([0x11u8; 20].into());
142        let address2 = Token::Address([0x22u8; 20].into());
143        let encoded = encode(&[address1, address2]);
144        let expected = hex!(
145            "
146			0000000000000000000000001111111111111111111111111111111111111111
147			0000000000000000000000002222222222222222222222222222222222222222
148		"
149        )
150        .to_vec();
151        assert_eq!(encoded, expected);
152    }
153
154    #[test]
155    fn encode_bytes() {
156        let bytes = Token::Bytes(vec![0x12, 0x34]);
157        let encoded = encode(&[bytes]);
158        let expected = hex!(
159            "
160			0000000000000000000000000000000000000000000000000000000000000020
161			0000000000000000000000000000000000000000000000000000000000000002
162			1234000000000000000000000000000000000000000000000000000000000000
163		"
164        )
165        .to_vec();
166        assert_eq!(encoded, expected);
167    }
168
169    #[test]
170    fn encode_fixed_bytes() {
171        let bytes = Token::FixedBytes(vec![0x12, 0x34]);
172        let encoded = encode(&[bytes]);
173        let expected = hex!("1234000000000000000000000000000000000000000000000000000000000000");
174        assert_eq!(encoded, expected);
175    }
176
177    #[test]
178    fn encode_string() {
179        let s = Token::String("gavofyork".to_owned());
180        let encoded = encode(&[s]);
181        let expected = hex!(
182            "
183			0000000000000000000000000000000000000000000000000000000000000020
184			0000000000000000000000000000000000000000000000000000000000000009
185			6761766f66796f726b0000000000000000000000000000000000000000000000
186		"
187        )
188        .to_vec();
189        assert_eq!(encoded, expected);
190    }
191
192    #[test]
193    fn encode_bytes2() {
194        let bytes = Token::Bytes(
195            hex!("10000000000000000000000000000000000000000000000000000000000002").to_vec(),
196        );
197        let encoded = encode(&[bytes]);
198        let expected = hex!(
199            "
200			0000000000000000000000000000000000000000000000000000000000000020
201			000000000000000000000000000000000000000000000000000000000000001f
202			1000000000000000000000000000000000000000000000000000000000000200
203		"
204        )
205        .to_vec();
206        assert_eq!(encoded, expected);
207    }
208
209    #[test]
210    fn encode_bytes3() {
211        let bytes = Token::Bytes(
212            hex!(
213                "
214			1000000000000000000000000000000000000000000000000000000000000000
215			1000000000000000000000000000000000000000000000000000000000000000
216		"
217            )
218            .to_vec(),
219        );
220        let encoded = encode(&[bytes]);
221        let expected = hex!(
222            "
223			0000000000000000000000000000000000000000000000000000000000000020
224			0000000000000000000000000000000000000000000000000000000000000040
225			1000000000000000000000000000000000000000000000000000000000000000
226			1000000000000000000000000000000000000000000000000000000000000000
227		"
228        )
229        .to_vec();
230        assert_eq!(encoded, expected);
231    }
232
233    #[test]
234    fn encode_two_bytes() {
235        let bytes1 = Token::Bytes(
236            hex!("10000000000000000000000000000000000000000000000000000000000002").to_vec(),
237        );
238        let bytes2 = Token::Bytes(
239            hex!("0010000000000000000000000000000000000000000000000000000000000002").to_vec(),
240        );
241        let encoded = encode(&[bytes1, bytes2]);
242        let expected = hex!(
243            "
244			0000000000000000000000000000000000000000000000000000000000000040
245			0000000000000000000000000000000000000000000000000000000000000080
246			000000000000000000000000000000000000000000000000000000000000001f
247			1000000000000000000000000000000000000000000000000000000000000200
248			0000000000000000000000000000000000000000000000000000000000000020
249			0010000000000000000000000000000000000000000000000000000000000002
250		"
251        )
252        .to_vec();
253        assert_eq!(encoded, expected);
254    }
255
256    #[test]
257    fn encode_uint() {
258        let mut uint = [0u8; 32];
259        uint[31] = 4;
260        let encoded = encode(&[Token::Uint(uint.into())]);
261        let expected = hex!("0000000000000000000000000000000000000000000000000000000000000004");
262        assert_eq!(encoded, expected);
263    }
264
265    #[test]
266    fn test_pad_u32() {
267        // this will fail if endianess is not supported
268        assert_eq!(pad_u32(0x1)[31], 1);
269        assert_eq!(pad_u32(0x100)[30], 1);
270    }
271}