Skip to main content

revm_state/bal/
alloy.rs

1//! Alloy BAL types conversions.
2
3// Re-export Alloy BAL types.
4pub use alloy_eip7928::{
5    BalanceChange as AlloyBalanceChange, BlockAccessList as AlloyBal,
6    CodeChange as AlloyCodeChange, NonceChange as AlloyNonceChange,
7    StorageChange as AlloyStorageChange,
8};
9
10use crate::bal::{AccountBal, Bal, BalWrites};
11use bytecode::{Bytecode, BytecodeDecodeError};
12use primitives::{AddressIndexMap, B256, U256};
13use std::vec::Vec;
14
15impl Bal {
16    /// Convert an EIP-7928 [`AlloyBal`] into a [`Bal`].
17    ///
18    /// # Errors
19    ///
20    /// Returns [`BytecodeDecodeError`] if any account code change contains bytecode
21    /// rejected by [`Bytecode::new_raw_checked`]. This currently happens for malformed
22    /// EIP-7702 bytecode, such as bytes with the EIP-7702 magic prefix but an invalid
23    /// length or unsupported version.
24    #[inline]
25    pub fn try_from_alloy(alloy_bal: AlloyBal) -> Result<Self, BytecodeDecodeError> {
26        let accounts = AddressIndexMap::from_iter(
27            alloy_bal
28                .into_iter()
29                .map(AccountBal::try_from_alloy)
30                .collect::<Result<Vec<_>, _>>()?,
31        );
32
33        Ok(Self { accounts })
34    }
35
36    /// Clone an EIP-7928 [`AlloyBal`] into a [`Bal`] without consuming the source.
37    ///
38    /// # Errors
39    ///
40    /// Returns [`BytecodeDecodeError`] if any account code change contains bytecode
41    /// rejected by [`Bytecode::new_raw_checked`]. This currently happens for malformed
42    /// EIP-7702 bytecode, such as bytes with the EIP-7702 magic prefix but an invalid
43    /// length or unsupported version.
44    #[inline]
45    pub fn clone_from_alloy(alloy_bal: &AlloyBal) -> Result<Self, BytecodeDecodeError> {
46        let accounts = AddressIndexMap::from_iter(
47            alloy_bal
48                .iter()
49                .map(AccountBal::clone_from_alloy)
50                .collect::<Result<Vec<_>, _>>()?,
51        );
52
53        Ok(Self { accounts })
54    }
55}
56
57impl TryFrom<AlloyBal> for Bal {
58    type Error = BytecodeDecodeError;
59
60    #[inline]
61    fn try_from(alloy_bal: AlloyBal) -> Result<Self, Self::Error> {
62        Self::try_from_alloy(alloy_bal)
63    }
64}
65
66impl From<Vec<AlloyBalanceChange>> for BalWrites<U256> {
67    fn from(value: Vec<AlloyBalanceChange>) -> Self {
68        Self {
69            writes: value
70                .into_iter()
71                .map(|change| (change.block_access_index, change.post_balance))
72                .collect(),
73        }
74    }
75}
76
77impl From<&[AlloyBalanceChange]> for BalWrites<U256> {
78    fn from(value: &[AlloyBalanceChange]) -> Self {
79        Self {
80            writes: value
81                .iter()
82                .map(|change| (change.block_access_index, change.post_balance))
83                .collect(),
84        }
85    }
86}
87
88impl From<Vec<AlloyNonceChange>> for BalWrites<u64> {
89    fn from(value: Vec<AlloyNonceChange>) -> Self {
90        Self {
91            writes: value
92                .into_iter()
93                .map(|change| (change.block_access_index, change.new_nonce))
94                .collect(),
95        }
96    }
97}
98
99impl From<&[AlloyNonceChange]> for BalWrites<u64> {
100    fn from(value: &[AlloyNonceChange]) -> Self {
101        Self {
102            writes: value
103                .iter()
104                .map(|change| (change.block_access_index, change.new_nonce))
105                .collect(),
106        }
107    }
108}
109
110impl From<Vec<AlloyStorageChange>> for BalWrites<U256> {
111    fn from(value: Vec<AlloyStorageChange>) -> Self {
112        Self {
113            writes: value
114                .into_iter()
115                .map(|change| (change.block_access_index, change.new_value))
116                .collect(),
117        }
118    }
119}
120
121impl From<&[AlloyStorageChange]> for BalWrites<U256> {
122    fn from(value: &[AlloyStorageChange]) -> Self {
123        Self {
124            writes: value
125                .iter()
126                .map(|change| (change.block_access_index, change.new_value))
127                .collect(),
128        }
129    }
130}
131
132impl TryFrom<Vec<AlloyCodeChange>> for BalWrites<(B256, Bytecode)> {
133    type Error = BytecodeDecodeError;
134
135    fn try_from(value: Vec<AlloyCodeChange>) -> Result<Self, Self::Error> {
136        Ok(Self {
137            writes: value
138                .into_iter()
139                .map(|change| {
140                    // convert bytes to bytecode.
141                    Bytecode::new_raw_checked(change.new_code).map(|bytecode| {
142                        let hash = bytecode.hash_slow();
143                        (change.block_access_index, (hash, bytecode))
144                    })
145                })
146                .collect::<Result<Vec<_>, Self::Error>>()?,
147        })
148    }
149}
150
151impl TryFrom<&[AlloyCodeChange]> for BalWrites<(B256, Bytecode)> {
152    type Error = BytecodeDecodeError;
153
154    fn try_from(value: &[AlloyCodeChange]) -> Result<Self, Self::Error> {
155        Ok(Self {
156            writes: value
157                .iter()
158                .map(|change| {
159                    Bytecode::new_raw_checked(change.new_code.clone()).map(|bytecode| {
160                        let hash = bytecode.hash_slow();
161                        (change.block_access_index, (hash, bytecode))
162                    })
163                })
164                .collect::<Result<Vec<_>, Self::Error>>()?,
165        })
166    }
167}