revm_rwasm_bytecode/
ownable_account.rs1use core::fmt;
2use primitives::{b256, bytes, Address, Bytes, B256};
3
4pub const OWNABLE_ACCOUNT_MAGIC_HASH: B256 =
6 b256!("0x85160e14613bd11c0e87050b7f84bbea3095f7f0ccd58026f217fdff9043c16b");
7
8pub const OWNABLE_ACCOUNT_MAGIC: u16 = 0xEF44;
10
11pub static OWNABLE_ACCOUNT_MAGIC_BYTES: Bytes = bytes!("ef44");
13
14pub const OWNABLE_ACCOUNT_VERSION: u8 = 0;
16
17#[derive(Clone, Debug, PartialEq, Eq, Hash, Ord, PartialOrd)]
22#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
23pub struct OwnableAccountBytecode {
24 pub owner_address: Address,
26 pub version: u8,
28 pub metadata: Bytes,
30 pub raw: Bytes,
32}
33
34impl OwnableAccountBytecode {
35 #[inline]
37 pub fn new_raw(raw: Bytes) -> Result<Self, OwnableAccountDecodeError> {
38 if raw.len() < 23 {
39 return Err(OwnableAccountDecodeError::InvalidLength);
40 } else if !raw.starts_with(&OWNABLE_ACCOUNT_MAGIC_BYTES) {
41 return Err(OwnableAccountDecodeError::InvalidMagic);
42 }
43 if raw[2] != OWNABLE_ACCOUNT_VERSION {
45 return Err(OwnableAccountDecodeError::UnsupportedVersion);
46 }
47 Ok(Self {
48 owner_address: Address::new(raw[3..23].try_into().unwrap()),
49 version: OWNABLE_ACCOUNT_VERSION,
50 metadata: raw.slice(23..),
51 raw,
52 })
53 }
54
55 pub fn new(address: Address, metadata: Bytes) -> Self {
57 let mut raw = OWNABLE_ACCOUNT_MAGIC_BYTES.to_vec();
58 raw.push(OWNABLE_ACCOUNT_VERSION);
59 raw.extend(&address);
60 raw.extend(&metadata);
61 Self {
62 owner_address: address,
63 version: OWNABLE_ACCOUNT_VERSION,
64 metadata,
65 raw: raw.into(),
66 }
67 }
68
69 #[inline]
71 pub fn metadata(&self) -> &Bytes {
72 &self.metadata
73 }
74
75 #[inline]
77 pub fn owner(&self) -> Address {
78 self.owner_address
79 }
80
81 #[inline]
83 pub fn raw(&self) -> &Bytes {
84 &self.raw
85 }
86}
87
88#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
90#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
91pub enum OwnableAccountDecodeError {
92 InvalidLength,
96 InvalidMagic,
100 UnsupportedVersion,
104}
105
106impl fmt::Display for OwnableAccountDecodeError {
107 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
108 let s = match self {
109 Self::InvalidLength => "Metadata is not 23 bytes long",
110 Self::InvalidMagic => "Metadata is not starting with 0xEF44",
111 Self::UnsupportedVersion => "Unsupported Metadata version.",
112 };
113 f.write_str(s)
114 }
115}
116
117impl core::error::Error for OwnableAccountDecodeError {}
118
119#[cfg(test)]
120mod tests {
121 use super::*;
122 use primitives::keccak256;
123
124 #[test]
125 fn magic_bytes_hash_check() {
126 let result = keccak256(&OWNABLE_ACCOUNT_MAGIC_BYTES);
127 assert_eq!(OWNABLE_ACCOUNT_MAGIC_HASH.as_slice(), result.as_slice());
128 }
129
130 #[test]
131 fn sanity_decode() {
132 let metadata = bytes!("ef44deadbeef");
133 assert_eq!(
134 OwnableAccountBytecode::new_raw(metadata),
135 Err(OwnableAccountDecodeError::InvalidLength)
136 );
137 let metadata = bytes!("ef4401deadbeef00000000000000000000000000000000");
138 assert_eq!(
139 OwnableAccountBytecode::new_raw(metadata),
140 Err(OwnableAccountDecodeError::UnsupportedVersion)
141 );
142 let raw = bytes!("ef4400deadbeef00000000000000000000000000000000");
143 let address = raw[3..].try_into().unwrap();
144 assert_eq!(
145 OwnableAccountBytecode::new_raw(raw.clone()),
146 Ok(OwnableAccountBytecode {
147 owner_address: address,
148 version: 0,
149 metadata: raw.slice(23..),
150 raw,
151 })
152 );
153 }
154
155 #[test]
156 fn create_metadata_from_address() {
157 let address = Address::new([0x01; 20]);
158 let bytecode = OwnableAccountBytecode::new(address, bytes!("0102030405"));
159 assert_eq!(bytecode.owner_address, address);
160 assert_eq!(bytecode.metadata, bytes!("0102030405"));
161 }
162}