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    AccountChanges as AlloyAccountChanges, BalanceChange as AlloyBalanceChange,
6    BlockAccessList as AlloyBal, 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 mut accounts =
27            AddressIndexMap::with_capacity_and_hasher(alloy_bal.len(), Default::default());
28        for alloy_account in alloy_bal {
29            let (address, account_bal) = AccountBal::try_from_alloy(alloy_account)?;
30            accounts.insert(address, account_bal);
31        }
32
33        Ok(Self { accounts })
34    }
35
36    /// Clone EIP-7928 [`AlloyAccountChanges`] 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(
46        alloy_bal: &[AlloyAccountChanges],
47    ) -> Result<Self, BytecodeDecodeError> {
48        let mut accounts =
49            AddressIndexMap::with_capacity_and_hasher(alloy_bal.len(), Default::default());
50        for alloy_account in alloy_bal {
51            let (address, account_bal) = AccountBal::clone_from_alloy(alloy_account)?;
52            accounts.insert(address, account_bal);
53        }
54
55        Ok(Self { accounts })
56    }
57}
58
59impl TryFrom<AlloyBal> for Bal {
60    type Error = BytecodeDecodeError;
61
62    #[inline]
63    fn try_from(alloy_bal: AlloyBal) -> Result<Self, Self::Error> {
64        Self::try_from_alloy(alloy_bal)
65    }
66}
67
68impl From<Vec<AlloyBalanceChange>> for BalWrites<U256> {
69    fn from(value: Vec<AlloyBalanceChange>) -> Self {
70        Self {
71            writes: value
72                .into_iter()
73                .map(|change| (change.block_access_index, change.post_balance))
74                .collect(),
75        }
76    }
77}
78
79impl From<&[AlloyBalanceChange]> for BalWrites<U256> {
80    fn from(value: &[AlloyBalanceChange]) -> Self {
81        Self {
82            writes: value
83                .iter()
84                .map(|change| (change.block_access_index, change.post_balance))
85                .collect(),
86        }
87    }
88}
89
90impl From<Vec<AlloyNonceChange>> for BalWrites<u64> {
91    fn from(value: Vec<AlloyNonceChange>) -> Self {
92        Self {
93            writes: value
94                .into_iter()
95                .map(|change| (change.block_access_index, change.new_nonce))
96                .collect(),
97        }
98    }
99}
100
101impl From<&[AlloyNonceChange]> for BalWrites<u64> {
102    fn from(value: &[AlloyNonceChange]) -> Self {
103        Self {
104            writes: value
105                .iter()
106                .map(|change| (change.block_access_index, change.new_nonce))
107                .collect(),
108        }
109    }
110}
111
112impl From<Vec<AlloyStorageChange>> for BalWrites<U256> {
113    fn from(value: Vec<AlloyStorageChange>) -> Self {
114        Self {
115            writes: value
116                .into_iter()
117                .map(|change| (change.block_access_index, change.new_value))
118                .collect(),
119        }
120    }
121}
122
123impl From<&[AlloyStorageChange]> for BalWrites<U256> {
124    fn from(value: &[AlloyStorageChange]) -> Self {
125        Self {
126            writes: value
127                .iter()
128                .map(|change| (change.block_access_index, change.new_value))
129                .collect(),
130        }
131    }
132}
133
134impl TryFrom<Vec<AlloyCodeChange>> for BalWrites<(B256, Bytecode)> {
135    type Error = BytecodeDecodeError;
136
137    fn try_from(value: Vec<AlloyCodeChange>) -> Result<Self, Self::Error> {
138        Ok(Self {
139            writes: value
140                .into_iter()
141                .map(|change| {
142                    // convert bytes to bytecode.
143                    Bytecode::new_raw_checked(change.new_code).map(|bytecode| {
144                        let hash = bytecode.hash_slow();
145                        (change.block_access_index, (hash, bytecode))
146                    })
147                })
148                .collect::<Result<Vec<_>, Self::Error>>()?,
149        })
150    }
151}
152
153impl TryFrom<&[AlloyCodeChange]> for BalWrites<(B256, Bytecode)> {
154    type Error = BytecodeDecodeError;
155
156    fn try_from(value: &[AlloyCodeChange]) -> Result<Self, Self::Error> {
157        Ok(Self {
158            writes: value
159                .iter()
160                .map(|change| {
161                    Bytecode::new_raw_checked(change.new_code.clone()).map(|bytecode| {
162                        let hash = bytecode.hash_slow();
163                        (change.block_access_index, (hash, bytecode))
164                    })
165                })
166                .collect::<Result<Vec<_>, Self::Error>>()?,
167        })
168    }
169}