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