stratus/eth/primitives/
address.rs1use std::fmt::Display;
2use std::ops::Deref;
3use std::str::FromStr;
4
5use alloy_primitives::FixedBytes;
6use anyhow::bail;
7use display_json::DebugAsJson;
8#[cfg(test)]
9use fake::Dummy;
10#[cfg(test)]
11use fake::Faker;
12use hex_literal::hex;
13
14use crate::alias::RevmAddress;
15use crate::eth::primitives::LogTopic;
16
17#[derive(DebugAsJson, Clone, Copy, Default, Eq, PartialEq, PartialOrd, Ord, Hash, serde::Serialize, serde::Deserialize)]
19pub struct Address(pub FixedBytes<20>);
20
21impl Address {
22 pub const ZERO: Address = Address(FixedBytes::ZERO);
24
25 pub const COINBASE: Address = Address(FixedBytes(hex!("00000000000000000000000000000000000000ff")));
27 pub const BRLC: Address = Address(FixedBytes(hex!("a9a55a81a4c085ec0c31585aed4cfb09d78dfd53")));
28
29 pub const fn new(bytes: [u8; 20]) -> Self {
31 Self(FixedBytes(bytes))
32 }
33
34 pub fn is_zero(&self) -> bool {
36 self == &Self::ZERO
37 }
38
39 pub fn is_coinbase(&self) -> bool {
41 self == &Self::COINBASE
42 }
43
44 pub fn is_ignored(&self) -> bool {
49 self.is_coinbase() || self.is_zero()
50 }
51}
52
53impl Display for Address {
54 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
55 write!(f, "{}", const_hex::encode_prefixed(self.0))
56 }
57}
58
59#[cfg(test)]
60impl Dummy<Faker> for Address {
61 fn dummy_with_rng<R: rand::Rng + ?Sized>(_: &Faker, rng: &mut R) -> Self {
62 Address(FixedBytes::random_with(rng))
63 }
64}
65
66impl Deref for Address {
67 type Target = FixedBytes<20>;
68 fn deref(&self) -> &Self::Target {
69 &self.0
70 }
71}
72
73impl From<FixedBytes<20>> for Address {
78 fn from(value: FixedBytes<20>) -> Self {
79 Self(value)
80 }
81}
82
83impl From<[u8; 20]> for Address {
84 fn from(value: [u8; 20]) -> Self {
85 Self(FixedBytes::from(value))
86 }
87}
88
89impl From<RevmAddress> for Address {
90 fn from(value: RevmAddress) -> Self {
91 Address(value.0.0.into())
92 }
93}
94
95impl From<LogTopic> for Address {
96 fn from(value: LogTopic) -> Self {
97 Self(FixedBytes::from_slice(&value.0.0[12..32]))
98 }
99}
100
101impl TryFrom<Vec<u8>> for Address {
102 type Error = anyhow::Error;
103
104 fn try_from(value: Vec<u8>) -> Result<Self, Self::Error> {
105 if value.len() != 20 {
106 bail!("array of bytes to be converted to address must have exactly 20 bytes");
107 }
108 Ok(Self(FixedBytes::from_slice(&value)))
109 }
110}
111
112impl FromStr for Address {
135 type Err = anyhow::Error;
136
137 fn from_str(s: &str) -> Result<Self, Self::Err> {
138 Ok(Self(FixedBytes::from_str(s)?))
139 }
140}
141
142impl From<Address> for FixedBytes<20> {
143 fn from(value: Address) -> Self {
144 value.0
145 }
146}
147
148impl From<Address> for RevmAddress {
149 fn from(value: Address) -> Self {
150 revm::primitives::Address(value.0.0.into())
151 }
152}
153
154impl From<Address> for LogTopic {
155 fn from(value: Address) -> Self {
156 let padding = FixedBytes::<12>::ZERO;
157 Self(padding.concat_const(value.0))
158 }
159}