hypercall_signer/
encoding.rs1use alloy::primitives::Address;
2
3use crate::RsmSignerError;
4
5pub fn encode_action_bytes(
6 version: u8,
7 id: u32,
8 inner_abi: &[u8],
9) -> Result<Vec<u8>, RsmSignerError> {
10 if id > 0x00ff_ffff {
11 return Err(RsmSignerError::InvalidAction(format!(
12 "action id {} exceeds uint24 range",
13 id
14 )));
15 }
16
17 let mut encoded = Vec::with_capacity(4 + inner_abi.len());
18 encoded.push(version);
19 let id_bytes = id.to_be_bytes();
20 encoded.extend_from_slice(&id_bytes[1..]);
21 encoded.extend_from_slice(inner_abi);
22 Ok(encoded)
23}
24
25pub fn encode_directive(account: Address, nonce: u64, action_bytes: &[u8]) -> Vec<u8> {
26 let mut directive = Vec::with_capacity(28 + action_bytes.len());
27 directive.extend_from_slice(account.as_slice());
28 directive.extend_from_slice(&nonce.to_be_bytes());
29 directive.extend_from_slice(action_bytes);
30 directive
31}
32
33#[cfg(test)]
34mod tests {
35 use super::*;
36
37 #[test]
38 fn encodes_action_id_as_uint24() {
39 let encoded = encode_action_bytes(2, 0x00ab_cdef, &[0x11, 0x22]).unwrap();
40 assert_eq!(encoded, vec![0x02, 0xab, 0xcd, 0xef, 0x11, 0x22]);
41 }
42
43 #[test]
44 fn rejects_action_id_outside_uint24_range() {
45 let err = encode_action_bytes(1, 0x0100_0000, &[])
46 .unwrap_err()
47 .to_string();
48 assert!(err.contains("exceeds uint24 range"));
49 }
50
51 #[test]
52 fn directive_is_account_nonce_then_action() {
53 let account = Address::repeat_byte(0x7a);
54 let directive = encode_directive(account, 42, &[0xaa, 0xbb]);
55
56 assert_eq!(&directive[..20], account.as_slice());
57 assert_eq!(&directive[20..28], 42_u64.to_be_bytes());
58 assert_eq!(&directive[28..], &[0xaa, 0xbb]);
59 }
60}