alloy_consensus/receipt/
status.rs1use alloy_primitives::B256;
2use alloy_rlp::{Buf, BufMut, Decodable, Encodable, Error, Header};
3
4#[derive(Copy, Clone, Debug, PartialEq, Eq)]
6#[cfg_attr(any(test, feature = "arbitrary"), derive(arbitrary::Arbitrary))]
7#[cfg_attr(feature = "borsh", derive(borsh::BorshSerialize, borsh::BorshDeserialize))]
8pub enum Eip658Value {
9 Eip658(bool),
13 PostState(B256),
17}
18
19impl Eip658Value {
20 pub const fn success() -> Self {
22 Self::Eip658(true)
23 }
24
25 pub const fn coerce_status(&self) -> bool {
30 matches!(self, Self::Eip658(true) | Self::PostState(_))
31 }
32
33 pub const fn coerced_eip658(&mut self) {
35 *self = Self::Eip658(self.coerce_status())
36 }
37
38 pub const fn is_post_state(&self) -> bool {
42 matches!(self, Self::PostState(_))
43 }
44
45 pub const fn is_eip658(&self) -> bool {
47 !matches!(self, Self::PostState(_))
48 }
49
50 pub const fn as_post_state(&self) -> Option<B256> {
52 match self {
53 Self::PostState(state) => Some(*state),
54 _ => None,
55 }
56 }
57
58 pub const fn as_eip658(&self) -> Option<bool> {
62 match self {
63 Self::Eip658(status) => Some(*status),
64 _ => None,
65 }
66 }
67}
68
69impl From<bool> for Eip658Value {
70 fn from(status: bool) -> Self {
71 Self::Eip658(status)
72 }
73}
74
75impl From<B256> for Eip658Value {
76 fn from(state: B256) -> Self {
77 Self::PostState(state)
78 }
79}
80
81impl Default for Eip658Value {
83 fn default() -> Self {
84 Self::Eip658(true)
85 }
86}
87
88#[cfg(feature = "serde")]
89mod serde_eip658 {
90 use super::*;
97 use serde::{Deserialize, Serialize};
98
99 #[derive(serde::Serialize, serde::Deserialize)]
100 #[serde(untagged)]
101 enum SerdeHelper {
102 Eip658 {
103 #[serde(with = "alloy_serde::quantity")]
104 status: bool,
105 },
106 PostState {
107 root: B256,
108 },
109 }
110
111 impl Serialize for Eip658Value {
112 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
113 where
114 S: serde::Serializer,
115 {
116 match self {
117 Self::Eip658(status) => {
118 SerdeHelper::Eip658 { status: *status }.serialize(serializer)
119 }
120 Self::PostState(state) => {
121 SerdeHelper::PostState { root: *state }.serialize(serializer)
122 }
123 }
124 }
125 }
126
127 impl<'de> Deserialize<'de> for Eip658Value {
128 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
129 where
130 D: serde::Deserializer<'de>,
131 {
132 let helper = SerdeHelper::deserialize(deserializer)?;
133 match helper {
134 SerdeHelper::Eip658 { status } => Ok(Self::Eip658(status)),
135 SerdeHelper::PostState { root } => Ok(Self::PostState(root)),
136 }
137 }
138 }
139}
140
141impl Encodable for Eip658Value {
142 fn encode(&self, buf: &mut dyn BufMut) {
143 match self {
144 Self::Eip658(status) => {
145 status.encode(buf);
146 }
147 Self::PostState(state) => {
148 state.encode(buf);
149 }
150 }
151 }
152
153 fn length(&self) -> usize {
154 match self {
155 Self::Eip658(inner) => inner.length(),
156 Self::PostState(inner) => inner.length(),
157 }
158 }
159}
160
161impl Decodable for Eip658Value {
162 fn decode(buf: &mut &[u8]) -> Result<Self, Error> {
163 let h = Header::decode(buf)?;
164
165 match h.payload_length {
166 0 => Ok(Self::Eip658(false)),
167 1 => {
168 let status = buf.get_u8() != 0;
169 Ok(status.into())
170 }
171 32 => {
172 if buf.remaining() < 32 {
173 return Err(Error::InputTooShort);
174 }
175 let mut state = B256::default();
176 buf.copy_to_slice(state.as_mut_slice());
177 Ok(state.into())
178 }
179 _ => Err(Error::UnexpectedLength),
180 }
181 }
182}
183
184#[cfg(test)]
185mod test {
186 use super::*;
187
188 #[test]
189 fn rlp_sanity() {
190 let mut buf = Vec::new();
191 let status = Eip658Value::Eip658(true);
192 status.encode(&mut buf);
193 assert_eq!(Eip658Value::decode(&mut buf.as_slice()), Ok(status));
194
195 let mut buf = Vec::new();
196 let state = Eip658Value::PostState(B256::default());
197 state.encode(&mut buf);
198 assert_eq!(Eip658Value::decode(&mut buf.as_slice()), Ok(state));
199 }
200
201 #[cfg(feature = "serde")]
202 #[test]
203 fn serde_sanity() {
204 let status: Eip658Value = true.into();
205 let json = serde_json::to_string(&status).unwrap();
206 assert_eq!(json, r#"{"status":"0x1"}"#);
207 assert_eq!(serde_json::from_str::<Eip658Value>(&json).unwrap(), status);
208
209 let state: Eip658Value = false.into();
210 let json = serde_json::to_string(&state).unwrap();
211 assert_eq!(json, r#"{"status":"0x0"}"#);
212
213 let state: Eip658Value = B256::repeat_byte(1).into();
214 let json = serde_json::to_string(&state).unwrap();
215 assert_eq!(
216 json,
217 r#"{"root":"0x0101010101010101010101010101010101010101010101010101010101010101"}"#
218 );
219 }
220}