Skip to main content

alloy_eip8141/
address.rs

1use alloy_primitives::Address;
2use alloy_rlp::{Decodable, Encodable, Header};
3
4use crate::Eip8141Error;
5
6/// An empty or explicit address in a frame transaction.
7///
8/// Empty targets resolve to the transaction sender. Empty signature signers resolve to the sender
9/// for protocol-validated schemes and represent no signer for arbitrary signatures.
10/// RLP encodes the empty case as an empty byte string, preserving the EIP-8141 wire format.
11/// JSON uses hex byte strings, including `"0x"` for the empty case; `null` also deserializes as
12/// empty.
13#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
14#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
15#[cfg_attr(feature = "borsh", derive(borsh::BorshSerialize, borsh::BorshDeserialize))]
16pub enum FrameAddress {
17    /// The address is omitted.
18    #[default]
19    Empty,
20    /// An explicit address, including the zero address.
21    Address(Address),
22}
23
24impl FrameAddress {
25    /// Returns true if this is [`Self::Address`].
26    pub const fn is_address(self) -> bool {
27        matches!(self, Self::Address(_))
28    }
29
30    /// Returns the explicit address, if present.
31    pub const fn address(self) -> Option<Address> {
32        match self {
33            Self::Empty => None,
34            Self::Address(address) => Some(address),
35        }
36    }
37
38    /// Returns the explicit address, or `sender` when the address is omitted.
39    pub const fn resolve(self, sender: Address) -> Address {
40        match self {
41            Self::Empty => sender,
42            Self::Address(address) => address,
43        }
44    }
45
46    /// Returns whether the address is omitted.
47    pub const fn is_empty(self) -> bool {
48        matches!(self, Self::Empty)
49    }
50
51    /// Returns the byte string carried on the wire: empty when the address is omitted.
52    pub const fn as_bytes(&self) -> &[u8] {
53        match self {
54            Self::Empty => &[],
55            Self::Address(address) => address.0.as_slice(),
56        }
57    }
58}
59
60impl From<Address> for FrameAddress {
61    fn from(value: Address) -> Self {
62        Self::Address(value)
63    }
64}
65
66impl From<Option<Address>> for FrameAddress {
67    fn from(value: Option<Address>) -> Self {
68        value.map_or(Self::Empty, Self::Address)
69    }
70}
71
72impl TryFrom<&[u8]> for FrameAddress {
73    type Error = Eip8141Error;
74
75    fn try_from(value: &[u8]) -> Result<Self, Self::Error> {
76        if value.is_empty() {
77            Ok(Self::Empty)
78        } else {
79            Address::try_from(value)
80                .map(Self::Address)
81                .map_err(|_| Eip8141Error::InvalidAddressLength(value.len()))
82        }
83    }
84}
85
86impl Encodable for FrameAddress {
87    fn encode(&self, out: &mut dyn alloy_rlp::BufMut) {
88        match self {
89            Self::Empty => out.put_u8(alloy_rlp::EMPTY_STRING_CODE),
90            Self::Address(address) => address.encode(out),
91        }
92    }
93
94    fn length(&self) -> usize {
95        match self {
96            Self::Empty => 1,
97            Self::Address(address) => address.length(),
98        }
99    }
100}
101
102impl Decodable for FrameAddress {
103    fn decode(buf: &mut &[u8]) -> alloy_rlp::Result<Self> {
104        Self::try_from(Header::decode_bytes(buf, false)?)
105            .map_err(|_| alloy_rlp::Error::Custom("invalid EIP-8141 address length"))
106    }
107}
108
109#[cfg(feature = "serde")]
110impl serde::Serialize for FrameAddress {
111    fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
112        crate::serde_utils::serialize_optional_bytes(
113            self.address().map(|address| address.into_array().into()),
114            serializer,
115        )
116    }
117}
118
119#[cfg(feature = "serde")]
120impl<'de> serde::Deserialize<'de> for FrameAddress {
121    fn deserialize<D: serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
122        crate::serde_utils::deserialize_optional_bytes::<20, D>(deserializer)
123            .map(|address| Self::from(address.map(Address::from)))
124    }
125}