1use super::{
2 changes::{PlainStorageChangeset, StateChangeset},
3 reverts::{AccountInfoRevert, Reverts},
4 AccountRevert, AccountStatus, BundleAccount, PlainStateReverts, RevertToSlot, StorageSlot,
5 TransitionState,
6};
7use alloc::{
8 collections::{BTreeMap, BTreeSet},
9 vec::Vec,
10};
11use alloy_primitives::{
12 map::{hash_map::Entry, AddressMap, AddressSet, B256Map, HashMap, U256Map},
13 Address, B256, KECCAK256_EMPTY, U256,
14};
15use core::{mem, ops::RangeInclusive};
16use evm2::{bytecode::Bytecode, evm::AccountInfo};
17
18#[derive(Debug)]
20pub struct BundleBuilder {
21 states: AddressSet,
22 state_original: AddressMap<AccountInfo>,
23 state_present: AddressMap<AccountInfo>,
24 state_storage: AddressMap<U256Map<(U256, U256)>>,
25
26 reverts: BTreeSet<(u64, Address)>,
27 revert_range: RangeInclusive<u64>,
28 revert_account: HashMap<(u64, Address), Option<Option<AccountInfo>>>,
29 revert_storage: HashMap<(u64, Address), Vec<(U256, U256)>>,
30
31 contracts: B256Map<Bytecode>,
32}
33
34#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
36pub enum OriginalValuesKnown {
37 Yes,
42 No,
48}
49impl OriginalValuesKnown {
50 pub const fn is_not_known(&self) -> bool {
52 matches!(self, Self::No)
53 }
54}
55
56impl Default for BundleBuilder {
57 fn default() -> Self {
58 BundleBuilder {
59 states: AddressSet::default(),
60 state_original: AddressMap::default(),
61 state_present: AddressMap::default(),
62 state_storage: AddressMap::default(),
63 reverts: BTreeSet::new(),
64 revert_range: 0..=0,
65 revert_account: HashMap::default(),
66 revert_storage: HashMap::default(),
67 contracts: B256Map::default(),
68 }
69 }
70}
71
72impl BundleBuilder {
73 pub fn new(revert_range: RangeInclusive<u64>) -> Self {
77 BundleBuilder { revert_range, ..Default::default() }
78 }
79
80 pub fn apply<F>(self, f: F) -> Self
82 where
83 F: FnOnce(Self) -> Self,
84 {
85 f(self)
86 }
87
88 pub fn apply_mut<F>(&mut self, f: F) -> &mut Self
90 where
91 F: FnOnce(&mut Self),
92 {
93 f(self);
94 self
95 }
96
97 pub fn state_address(mut self, address: Address) -> Self {
99 self.set_state_address(address);
100 self
101 }
102
103 pub fn state_original_account_info(mut self, address: Address, original: AccountInfo) -> Self {
105 self.set_state_original_account_info(address, original);
106 self
107 }
108
109 pub fn state_present_account_info(mut self, address: Address, present: AccountInfo) -> Self {
111 self.set_state_present_account_info(address, present);
112 self
113 }
114
115 pub fn state_storage(mut self, address: Address, storage: U256Map<(U256, U256)>) -> Self {
117 self.set_state_storage(address, storage);
118 self
119 }
120
121 pub fn revert_address(mut self, block_number: u64, address: Address) -> Self {
126 self.set_revert_address(block_number, address);
127 self
128 }
129
130 pub fn revert_account_info(
135 mut self,
136 block_number: u64,
137 address: Address,
138 account: Option<Option<AccountInfo>>,
139 ) -> Self {
140 self.set_revert_account_info(block_number, address, account);
141 self
142 }
143
144 pub fn revert_storage(
149 mut self,
150 block_number: u64,
151 address: Address,
152 storage: Vec<(U256, U256)>,
153 ) -> Self {
154 self.set_revert_storage(block_number, address, storage);
155 self
156 }
157
158 pub fn contract(mut self, address: B256, bytecode: Bytecode) -> Self {
160 self.set_contract(address, bytecode);
161 self
162 }
163
164 pub fn set_state_address(&mut self, address: Address) -> &mut Self {
166 self.states.insert(address);
167 self
168 }
169
170 pub fn set_state_original_account_info(
172 &mut self,
173 address: Address,
174 original: AccountInfo,
175 ) -> &mut Self {
176 self.states.insert(address);
177 self.state_original.insert(address, original);
178 self
179 }
180
181 pub fn set_state_present_account_info(
183 &mut self,
184 address: Address,
185 present: AccountInfo,
186 ) -> &mut Self {
187 self.states.insert(address);
188 self.state_present.insert(address, present);
189 self
190 }
191
192 pub fn set_state_storage(
194 &mut self,
195 address: Address,
196 storage: U256Map<(U256, U256)>,
197 ) -> &mut Self {
198 self.states.insert(address);
199 self.state_storage.insert(address, storage);
200 self
201 }
202
203 pub fn set_revert_address(&mut self, block_number: u64, address: Address) -> &mut Self {
205 self.reverts.insert((block_number, address));
206 self
207 }
208
209 pub fn set_revert_account_info(
211 &mut self,
212 block_number: u64,
213 address: Address,
214 account: Option<Option<AccountInfo>>,
215 ) -> &mut Self {
216 self.reverts.insert((block_number, address));
217 self.revert_account.insert((block_number, address), account);
218 self
219 }
220
221 pub fn set_revert_storage(
223 &mut self,
224 block_number: u64,
225 address: Address,
226 storage: Vec<(U256, U256)>,
227 ) -> &mut Self {
228 self.reverts.insert((block_number, address));
229 self.revert_storage.insert((block_number, address), storage);
230 self
231 }
232
233 pub fn set_contract(&mut self, address: B256, bytecode: Bytecode) -> &mut Self {
235 self.contracts.insert(address, bytecode);
236 self
237 }
238
239 pub fn build(mut self) -> BundleState {
241 let mut state_size = 0;
242 let state = self
243 .states
244 .into_iter()
245 .map(|address| {
246 let storage = self
247 .state_storage
248 .remove(&address)
249 .map(|s| {
250 s.into_iter()
251 .map(|(k, (o_val, p_val))| (k, StorageSlot::new_changed(o_val, p_val)))
252 .collect()
253 })
254 .unwrap_or_default();
255 let bundle_account = BundleAccount::new(
256 self.state_original.remove(&address),
257 self.state_present.remove(&address),
258 storage,
259 AccountStatus::Changed,
260 );
261 state_size += bundle_account.size_hint();
262 (address, bundle_account)
263 })
264 .collect();
265
266 let mut reverts_size = 0;
267 let mut reverts_map = BTreeMap::new();
268 for block_number in self.revert_range {
269 reverts_map.insert(block_number, Vec::new());
270 }
271 self.reverts.into_iter().for_each(|(block_number, address)| {
272 let account =
273 match self.revert_account.remove(&(block_number, address)).unwrap_or_default() {
274 Some(Some(account)) => AccountInfoRevert::RevertTo(account),
275 Some(None) => AccountInfoRevert::DeleteIt,
276 None => AccountInfoRevert::DoNothing,
277 };
278 let storage = self
279 .revert_storage
280 .remove(&(block_number, address))
281 .map(|s| s.into_iter().map(|(k, v)| (k, RevertToSlot::Some(v))).collect())
282 .unwrap_or_default();
283 let account_revert = AccountRevert {
284 account,
285 storage,
286 previous_status: AccountStatus::Changed,
287 wipe_storage: false,
288 };
289
290 if let Some(vec) = reverts_map.get_mut(&block_number) {
291 reverts_size += account_revert.size_hint();
292 vec.push((address, account_revert));
293 }
294 });
295
296 BundleState {
297 state,
298 contracts: self.contracts,
299 reverts: Reverts::new(reverts_map.into_values().collect()),
300 state_size,
301 reverts_size,
302 }
303 }
304
305 pub const fn get_states(&self) -> &AddressSet {
307 &self.states
308 }
309
310 pub const fn get_states_mut(&mut self) -> &mut AddressSet {
312 &mut self.states
313 }
314
315 pub const fn get_state_original_mut(&mut self) -> &mut AddressMap<AccountInfo> {
317 &mut self.state_original
318 }
319
320 pub const fn get_state_present_mut(&mut self) -> &mut AddressMap<AccountInfo> {
322 &mut self.state_present
323 }
324
325 pub const fn get_state_storage_mut(&mut self) -> &mut AddressMap<U256Map<(U256, U256)>> {
327 &mut self.state_storage
328 }
329
330 pub const fn get_reverts_mut(&mut self) -> &mut BTreeSet<(u64, Address)> {
332 &mut self.reverts
333 }
334
335 pub const fn get_revert_range_mut(&mut self) -> &mut RangeInclusive<u64> {
337 &mut self.revert_range
338 }
339
340 pub const fn get_revert_account_mut(
342 &mut self,
343 ) -> &mut HashMap<(u64, Address), Option<Option<AccountInfo>>> {
344 &mut self.revert_account
345 }
346
347 pub const fn get_revert_storage_mut(
349 &mut self,
350 ) -> &mut HashMap<(u64, Address), Vec<(U256, U256)>> {
351 &mut self.revert_storage
352 }
353
354 pub const fn get_contracts_mut(&mut self) -> &mut B256Map<Bytecode> {
356 &mut self.contracts
357 }
358}
359
360#[derive(Debug)]
362pub enum BundleRetention {
363 PlainState,
365 Reverts,
367}
368
369impl BundleRetention {
370 pub const fn includes_reverts(&self) -> bool {
372 matches!(self, Self::Reverts)
373 }
374}
375
376#[derive(Default, Clone, Debug, PartialEq, Eq)]
386#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
387pub struct BundleState {
388 pub state: AddressMap<BundleAccount>,
390 pub contracts: B256Map<Bytecode>,
392 pub reverts: Reverts,
398 pub state_size: usize,
400 pub reverts_size: usize,
402}
403
404impl BundleState {
405 pub fn builder(revert_range: RangeInclusive<u64>) -> BundleBuilder {
407 BundleBuilder::new(revert_range)
408 }
409
410 pub fn new(
412 state: impl IntoIterator<
413 Item = (Address, Option<AccountInfo>, Option<AccountInfo>, HashMap<U256, (U256, U256)>),
414 >,
415 reverts: impl IntoIterator<
416 Item = impl IntoIterator<
417 Item = (
418 Address,
419 Option<Option<AccountInfo>>,
420 impl IntoIterator<Item = (U256, U256)>,
421 ),
422 >,
423 >,
424 contracts: impl IntoIterator<Item = (B256, Bytecode)>,
425 ) -> Self {
426 let mut state_size = 0;
428 let state = state
429 .into_iter()
430 .map(|(address, original, present, storage)| {
431 let account = BundleAccount::new(
432 original,
433 present,
434 storage
435 .into_iter()
436 .map(|(k, (o_val, p_val))| (k, StorageSlot::new_changed(o_val, p_val)))
437 .collect(),
438 AccountStatus::Changed,
439 );
440 state_size += account.size_hint();
441 (address, account)
442 })
443 .collect();
444
445 let mut reverts_size = 0;
447 let reverts = reverts
448 .into_iter()
449 .map(|block_reverts| {
450 block_reverts
451 .into_iter()
452 .map(|(address, account, storage)| {
453 let account = match account {
454 Some(Some(account)) => AccountInfoRevert::RevertTo(account),
455 Some(None) => AccountInfoRevert::DeleteIt,
456 None => AccountInfoRevert::DoNothing,
457 };
458 let revert = AccountRevert {
459 account,
460 storage: storage
461 .into_iter()
462 .map(|(k, v)| (k, RevertToSlot::Some(v)))
463 .collect(),
464 previous_status: AccountStatus::Changed,
465 wipe_storage: false,
466 };
467 reverts_size += revert.size_hint();
468 (address, revert)
469 })
470 .collect::<Vec<_>>()
471 })
472 .collect::<Vec<_>>();
473
474 Self {
475 state,
476 contracts: contracts.into_iter().collect(),
477 reverts: Reverts::new(reverts),
478 state_size,
479 reverts_size,
480 }
481 }
482
483 pub fn size_hint(&self) -> usize {
488 self.state_size + self.reverts_size + self.contracts.len()
489 }
490
491 pub const fn state(&self) -> &AddressMap<BundleAccount> {
493 &self.state
494 }
495
496 pub fn is_empty(&self) -> bool {
498 self.len() == 0
499 }
500
501 pub fn len(&self) -> usize {
503 self.state.len()
504 }
505
506 pub fn account(&self, address: &Address) -> Option<&BundleAccount> {
508 self.state.get(address)
509 }
510
511 pub fn bytecode(&self, hash: &B256) -> Option<Bytecode> {
513 self.contracts.get(hash).cloned()
514 }
515
516 pub fn storage(&self, address: &Address, storage_key: U256) -> Option<U256> {
520 self.account(address).and_then(|account| account.storage_slot(storage_key))
521 }
522
523 pub fn apply_transitions_and_create_reverts(
529 &mut self,
530 transitions: TransitionState,
531 retention: BundleRetention,
532 ) {
533 let include_reverts = retention.includes_reverts();
534 let reverts_capacity = if include_reverts { transitions.transitions.len() } else { 0 };
536 let mut reverts = Vec::with_capacity(reverts_capacity);
537
538 self.state.reserve(transitions.transitions.len());
539 for (address, transition) in transitions.transitions.into_iter() {
540 if let Some((hash, new_bytecode)) = transition.has_new_contract() {
542 self.contracts.insert(hash, new_bytecode.clone());
543 }
544 let revert = match self.state.entry(address) {
546 Entry::Occupied(mut entry) => {
547 let entry = entry.get_mut();
548 self.state_size -= entry.size_hint();
549 let revert = entry.update_and_create_revert(transition);
551 self.state_size += entry.size_hint();
553 revert
554 }
555 Entry::Vacant(entry) => {
556 let present_bundle = transition.present_bundle_account();
558 let revert = transition.create_revert();
559 if revert.is_some() {
560 self.state_size += present_bundle.size_hint();
561 entry.insert(present_bundle);
562 }
563 revert
564 }
565 };
566
567 if let Some(revert) = revert.filter(|_| include_reverts) {
569 self.reverts_size += revert.size_hint();
570 reverts.push((address, revert));
571 }
572 }
573
574 self.reverts.push(reverts);
575 }
576
577 pub fn to_plain_state(&self, is_value_known: OriginalValuesKnown) -> StateChangeset {
580 let state_len = self.state.len();
582 let mut accounts = Vec::with_capacity(state_len);
583 let mut storage = Vec::with_capacity(state_len);
584
585 for (address, account) in &self.state {
586 let was_destroyed = account.was_destroyed();
588 if is_value_known.is_not_known() || account.is_info_changed() {
589 let info =
590 account.info.as_ref().map(|info| AccountInfo { code: None, ..info.clone() });
591 accounts.push((*address, info));
592 }
593
594 let mut account_storage_changed = Vec::with_capacity(account.storage.len());
599
600 for (&key, &slot) in account.storage.iter() {
601 let destroyed_and_not_zero = was_destroyed && !slot.present_value.is_zero();
604
605 let not_destroyed_and_changed = !was_destroyed && slot.is_changed();
608
609 if is_value_known.is_not_known() ||
610 destroyed_and_not_zero ||
611 not_destroyed_and_changed
612 {
613 account_storage_changed.push((key, slot.present_value));
614 }
615 }
616
617 if !account_storage_changed.is_empty() || was_destroyed {
618 storage.push(PlainStorageChangeset {
620 address: *address,
621 wipe_storage: was_destroyed,
622 storage: account_storage_changed,
623 });
624 }
625 }
626
627 let contracts = self
628 .contracts
629 .iter()
630 .filter(|(b, _)| **b != KECCAK256_EMPTY)
632 .map(|(b, code)| (*b, code.clone()))
633 .collect::<Vec<_>>();
634 StateChangeset { accounts, storage, contracts }
635 }
636
637 pub fn to_plain_state_and_reverts(
640 &self,
641 is_value_known: OriginalValuesKnown,
642 ) -> (StateChangeset, PlainStateReverts) {
643 (self.to_plain_state(is_value_known), self.reverts.to_plain_state_reverts())
644 }
645
646 #[deprecated = "Use `to_plain_state_and_reverts` instead"]
649 pub fn into_plain_state_and_reverts(
650 self,
651 is_value_known: OriginalValuesKnown,
652 ) -> (StateChangeset, PlainStateReverts) {
653 self.to_plain_state_and_reverts(is_value_known)
654 }
655
656 pub fn extend_state(&mut self, other_state: AddressMap<BundleAccount>) {
660 self.state.reserve(other_state.len());
661 for (address, other_account) in other_state {
662 match self.state.entry(address) {
663 Entry::Occupied(mut entry) => {
664 let this = entry.get_mut();
665 self.state_size -= this.size_hint();
666
667 if other_account.was_destroyed() {
670 this.storage = other_account.storage;
671 } else {
672 this.storage.reserve(other_account.storage.len());
674 for (key, storage_slot) in other_account.storage {
675 this.storage.entry(key).or_insert(storage_slot).present_value =
677 storage_slot.present_value;
678 }
679 }
680 this.info = other_account.info;
681 this.status.transition(other_account.status);
682
683 self.state_size += this.size_hint();
685 }
686 Entry::Vacant(entry) => {
687 self.state_size += other_account.size_hint();
689 entry.insert(other_account);
690 }
691 }
692 }
693 }
694 pub fn extend(&mut self, mut other: Self) {
705 let mut seen = AddressSet::default();
708 for (address, revert) in other.reverts.iter_mut().flatten() {
709 if seen.insert(*address) &&
712 let Some(this_account) = self.state.get(address)
713 {
714 revert.previous_status = this_account.status;
715 }
716
717 if revert.wipe_storage {
718 if let Some(this_account) = self.state.get_mut(address) {
721 for (key, value) in this_account.storage.drain() {
726 let previous = RevertToSlot::Some(value.present_value);
727 revert
728 .storage
729 .entry(key)
730 .and_modify(|slot| {
731 if *slot == RevertToSlot::Destroyed {
732 *slot = previous;
733 }
734 })
735 .or_insert(previous);
736 }
737
738 if this_account.was_destroyed() {
740 revert.wipe_storage = false;
741 }
742 }
743 }
744
745 self.reverts_size += revert.size_hint();
747 }
748 self.extend_state(other.state);
750 self.contracts.extend(other.contracts);
752 self.reverts.extend(other.reverts);
754 }
755
756 pub fn take_n_reverts(&mut self, reverts_to_take: usize) -> Reverts {
758 if reverts_to_take > self.reverts.len() {
760 return self.take_all_reverts();
761 }
762 let this = self.reverts.split_off(reverts_to_take);
763 self.reverts_size =
764 this.iter().flatten().fold(0, |acc, (_, revert)| acc + revert.size_hint());
765 mem::replace(&mut self.reverts, Reverts::new(this))
766 }
767
768 pub fn take_all_reverts(&mut self) -> Reverts {
770 self.reverts_size = 0;
771 mem::take(&mut self.reverts)
772 }
773
774 pub fn revert_latest(&mut self) -> bool {
780 if let Some(reverts) = self.reverts.pop() {
782 for (address, revert_account) in reverts.into_iter() {
783 self.reverts_size -= revert_account.size_hint();
784 match self.state.entry(address) {
785 Entry::Occupied(mut entry) => {
786 let account = entry.get_mut();
787 self.state_size -= account.size_hint();
788 if account.revert(revert_account) {
789 entry.remove();
790 } else {
791 self.state_size += account.size_hint();
792 }
793 }
794 Entry::Vacant(entry) => {
795 let mut account = BundleAccount::new(
798 None,
799 None,
800 HashMap::default(),
801 AccountStatus::LoadedNotExisting,
802 );
803 if !account.revert(revert_account) {
804 self.state_size += account.size_hint();
805 entry.insert(account);
806 }
807 }
808 }
809 }
810 return true;
811 }
812
813 false
814 }
815
816 pub fn revert(&mut self, mut num_transitions: usize) {
820 if num_transitions == 0 {
821 return;
822 }
823
824 while self.revert_latest() {
825 num_transitions -= 1;
826 if num_transitions == 0 {
827 break;
829 }
830 }
831 }
832
833 pub fn prepend_state(&mut self, mut other: BundleState) {
839 let this_bundle = mem::take(self);
841 other.extend_state(this_bundle.state);
843 other.contracts.extend(this_bundle.contracts);
845 mem::swap(self, &mut other)
847 }
848}
849
850#[cfg(test)]
851mod tests {
852 use super::*;
853 use crate::bundle_state::{StorageWithOriginalValues, TransitionAccount};
854
855 #[test]
856 fn transition_states() {
857 let address = Address::new([0x01; 20]);
859 let acc1 = AccountInfo { balance: U256::from(10), nonce: 1, ..Default::default() };
860
861 let mut bundle_state = BundleState::default();
862
863 let transition = TransitionAccount {
866 info: Some(acc1),
867 status: AccountStatus::InMemoryChange,
868 previous_info: None,
869 previous_status: AccountStatus::LoadedNotExisting,
870 storage: StorageWithOriginalValues::default(),
871 storage_was_destroyed: false,
872 };
873
874 bundle_state.apply_transitions_and_create_reverts(
876 TransitionState::single(address, transition.clone()),
877 BundleRetention::Reverts,
878 );
879 }
880
881 const fn account1() -> Address {
882 Address::new([0x60; 20])
883 }
884
885 const fn account2() -> Address {
886 Address::new([0x61; 20])
887 }
888
889 fn slot1() -> U256 {
890 U256::from(5)
891 }
892
893 fn slot2() -> U256 {
894 U256::from(7)
895 }
896
897 fn test_bundle1() -> BundleState {
899 BundleState::new(
901 vec![
902 (
903 account1(),
904 None,
905 Some(AccountInfo { nonce: 1, balance: U256::from(10), ..Default::default() }),
906 HashMap::from_iter([
907 (slot1(), (U256::from(0), U256::from(10))),
908 (slot2(), (U256::from(0), U256::from(15))),
909 ]),
910 ),
911 (
912 account2(),
913 None,
914 Some(AccountInfo { nonce: 1, balance: U256::from(10), ..Default::default() }),
915 HashMap::default(),
916 ),
917 ],
918 vec![vec![
919 (account1(), Some(None), vec![(slot1(), U256::from(0)), (slot2(), U256::from(0))]),
920 (account2(), Some(None), vec![]),
921 ]],
922 vec![],
923 )
924 }
925
926 fn test_bundle2() -> BundleState {
928 BundleState::new(
930 vec![(
931 account1(),
932 None,
933 Some(AccountInfo { nonce: 3, balance: U256::from(20), ..Default::default() }),
934 HashMap::from_iter([(slot1(), (U256::from(0), U256::from(15)))]),
935 )],
936 vec![vec![(
937 account1(),
938 Some(Some(AccountInfo { nonce: 1, balance: U256::from(10), ..Default::default() })),
939 vec![(slot1(), U256::from(10))],
940 )]],
941 vec![],
942 )
943 }
944
945 fn test_bundle3() -> BundleState {
947 BundleState::builder(0..=0)
948 .state_present_account_info(
949 account1(),
950 AccountInfo { nonce: 1, balance: U256::from(10), ..Default::default() },
951 )
952 .state_storage(
953 account1(),
954 HashMap::from_iter([(slot1(), (U256::from(0), U256::from(10)))]),
955 )
956 .state_address(account2())
957 .state_present_account_info(
958 account2(),
959 AccountInfo { nonce: 1, balance: U256::from(10), ..Default::default() },
960 )
961 .revert_address(0, account1())
962 .revert_account_info(0, account1(), Some(None))
963 .revert_storage(0, account1(), vec![(slot1(), U256::from(0))])
964 .revert_account_info(0, account2(), Some(None))
965 .build()
966 }
967
968 fn test_bundle4() -> BundleState {
970 BundleState::builder(0..=0)
971 .state_present_account_info(
972 account1(),
973 AccountInfo { nonce: 3, balance: U256::from(20), ..Default::default() },
974 )
975 .state_storage(
976 account1(),
977 HashMap::from_iter([(slot1(), (U256::from(0), U256::from(15)))]),
978 )
979 .revert_address(0, account1())
980 .revert_account_info(
981 0,
982 account1(),
983 Some(Some(AccountInfo { nonce: 1, balance: U256::from(10), ..Default::default() })),
984 )
985 .revert_storage(0, account1(), vec![(slot1(), U256::from(10))])
986 .build()
987 }
988
989 #[test]
992 fn extend_reverts_to_accumulated_status() {
993 let address = Address::new([0x70; 20]);
994 let info = AccountInfo { nonce: 1, balance: U256::from(10), ..Default::default() };
995 let destroy = TransitionAccount {
996 info: None,
997 status: AccountStatus::Destroyed,
998 previous_info: Some(info.clone()),
999 previous_status: AccountStatus::Loaded,
1000 storage: HashMap::from_iter([(
1001 slot1(),
1002 StorageSlot::new_changed(U256::from(3), U256::ZERO),
1003 )]),
1004 storage_was_destroyed: true,
1005 };
1006 let recreate = TransitionAccount {
1007 info: Some(info),
1008 status: AccountStatus::InMemoryChange,
1009 previous_info: None,
1010 previous_status: AccountStatus::LoadedNotExisting,
1011 storage: HashMap::from_iter([(
1012 slot2(),
1013 StorageSlot::new_changed(U256::ZERO, U256::from(5)),
1014 )]),
1015 storage_was_destroyed: false,
1016 };
1017 let block_bundle = |transition| {
1018 let mut bundle = BundleState::default();
1019 bundle.apply_transitions_and_create_reverts(
1020 TransitionState::single(address, transition),
1021 BundleRetention::Reverts,
1022 );
1023 bundle
1024 };
1025
1026 let first = block_bundle(destroy);
1027 let mut merged = first.clone();
1028 merged.extend(block_bundle(recreate.clone()));
1029
1030 let mut cumulative = first.clone();
1032 cumulative.apply_transitions_and_create_reverts(
1033 TransitionState::single(
1034 address,
1035 TransitionAccount {
1036 status: AccountStatus::DestroyedChanged,
1037 previous_status: AccountStatus::Destroyed,
1038 ..recreate
1039 },
1040 ),
1041 BundleRetention::Reverts,
1042 );
1043 assert_eq!(merged.state[&address].status, AccountStatus::DestroyedChanged);
1044 assert_eq!(merged.reverts, cumulative.reverts);
1045
1046 merged.revert(1);
1047 cumulative.revert(1);
1048 let account = &merged.state[&address];
1049 assert_eq!(account.status, AccountStatus::Destroyed);
1050 assert!(account.was_destroyed());
1051 assert_eq!(merged, cumulative);
1052 }
1053
1054 fn sanity_path(bundle1: BundleState, bundle2: BundleState) {
1055 let mut extended = bundle1.clone();
1056 extended.extend(bundle2.clone());
1057
1058 let mut reverted = extended.clone();
1059 reverted.revert(0);
1061 assert_eq!(reverted, extended);
1062
1063 reverted.revert(1);
1065 assert_eq!(reverted, bundle1);
1066
1067 reverted.revert(1);
1069 assert_eq!(reverted, BundleState::default());
1070
1071 let mut reverted = extended.clone();
1072
1073 reverted.revert(10);
1075 assert_eq!(reverted, BundleState::default());
1076 }
1077
1078 #[test]
1079 fn extend_on_destroyed_values() {
1080 let base_bundle1 = test_bundle1();
1081 let base_bundle2 = test_bundle2();
1082
1083 let mut b1 = base_bundle1.clone();
1088 let mut b2 = base_bundle2.clone();
1089 b1.state.get_mut(&account1()).unwrap().status = AccountStatus::Destroyed;
1090 b2.state.get_mut(&account1()).unwrap().status = AccountStatus::Changed;
1091 b1.extend(b2);
1092 assert_eq!(b1.state.get_mut(&account1()).unwrap().status, AccountStatus::DestroyedChanged);
1093
1094 let mut b1 = base_bundle1.clone();
1099 let mut b2 = base_bundle2.clone();
1100 b1.state.get_mut(&account1()).unwrap().status = AccountStatus::Changed;
1101 b2.state.get_mut(&account1()).unwrap().status = AccountStatus::Destroyed;
1102 b2.reverts[0][0].1.wipe_storage = true;
1103 b1.extend(b2);
1104 assert_eq!(b1.state.get_mut(&account1()).unwrap().status, AccountStatus::Destroyed);
1105
1106 let mut revert1 = base_bundle2.reverts[0][0].clone();
1109 revert1.1.wipe_storage = true;
1110 revert1.1.storage.insert(slot2(), RevertToSlot::Some(U256::from(15)));
1111
1112 assert_eq!(b1.reverts.as_ref(), vec![base_bundle1.reverts[0].clone(), vec![revert1]],);
1113
1114 let mut b1 = base_bundle1.clone();
1120 let mut b2 = base_bundle2.clone();
1121 b1.state.get_mut(&account1()).unwrap().status = AccountStatus::InMemoryChange;
1122 b2.state.get_mut(&account1()).unwrap().status = AccountStatus::Changed;
1123 b1.extend(b2);
1124 assert_eq!(b1.state.get_mut(&account1()).unwrap().status, AccountStatus::InMemoryChange);
1125 }
1126
1127 #[test]
1128 fn extend_replaces_destroyed_revert_with_previous_value() {
1129 let mut b1 = test_bundle1();
1132 let mut b2 = test_bundle2();
1133 b2.state.get_mut(&account1()).unwrap().status = AccountStatus::DestroyedChanged;
1134 let revert = &mut b2.reverts[0][0].1;
1135 revert.wipe_storage = true;
1136 revert.storage.insert(slot1(), RevertToSlot::Destroyed);
1137
1138 b1.extend(b2);
1139 let revert = &b1.reverts[1][0].1;
1140 assert!(revert.wipe_storage);
1141 assert_eq!(revert.storage.get(&slot1()), Some(&RevertToSlot::Some(U256::from(10))));
1142 assert_eq!(revert.storage.get(&slot2()), Some(&RevertToSlot::Some(U256::from(15))));
1143 }
1144
1145 #[test]
1146 fn test_sanity_path() {
1147 sanity_path(test_bundle1(), test_bundle2());
1148 sanity_path(test_bundle3(), test_bundle4());
1149 }
1150
1151 #[test]
1152 fn test_multi_reverts_with_delete() {
1153 let mut state = BundleBuilder::new(0..=3)
1154 .revert_address(0, account1())
1155 .revert_account_info(2, account1(), Some(Some(AccountInfo::default())))
1156 .revert_account_info(3, account1(), Some(None))
1157 .build();
1158
1159 state.revert_latest();
1160 assert_eq!(state.state.get(&account1()), None);
1162
1163 state.revert_latest();
1164 assert_eq!(
1166 state.state.get(&account1()),
1167 Some(&BundleAccount::new(
1168 None,
1169 Some(AccountInfo::default()),
1170 HashMap::default(),
1171 AccountStatus::Changed
1172 ))
1173 );
1174 }
1175
1176 #[test]
1177 fn test_revert_capacity() {
1178 let state = BundleState::builder(0..=3)
1179 .revert_address(0, account1())
1180 .revert_address(2, account2())
1181 .revert_account_info(0, account1(), Some(None))
1182 .revert_account_info(2, account2(), None)
1183 .revert_storage(0, account1(), vec![(slot1(), U256::from(10))])
1184 .build();
1185
1186 assert_eq!(state.reverts.len(), 4);
1187 assert_eq!(state.reverts[1], vec![]);
1188 assert_eq!(state.reverts[3], vec![]);
1189 assert_eq!(state.reverts[0].len(), 1);
1190 assert_eq!(state.reverts[2].len(), 1);
1191
1192 let (addr1, revert1) = &state.reverts[0][0];
1193 assert_eq!(addr1, &account1());
1194 assert_eq!(revert1.account, AccountInfoRevert::DeleteIt);
1195
1196 let (addr2, revert2) = &state.reverts[2][0];
1197 assert_eq!(addr2, &account2());
1198 assert_eq!(revert2.account, AccountInfoRevert::DoNothing);
1199 }
1200
1201 #[test]
1202 fn take_reverts() {
1203 let bundle1 = test_bundle1();
1204 let bundle2 = test_bundle2();
1205
1206 let mut extended = bundle1.clone();
1207 extended.extend(bundle2.clone());
1208
1209 assert_eq!(extended.reverts.len(), 2);
1211
1212 let mut extended2 = extended.clone();
1214 assert_eq!(extended2.take_n_reverts(100), extended.reverts);
1215
1216 let mut extended2 = extended.clone();
1218 assert_eq!(extended2.take_all_reverts(), extended.reverts);
1219
1220 let taken_reverts = extended.take_n_reverts(0);
1222 assert_eq!(taken_reverts, Reverts::default());
1223 assert_eq!(extended.reverts.len(), 2);
1224
1225 let taken_reverts = extended.take_n_reverts(1);
1227 assert_eq!(taken_reverts, bundle1.reverts);
1228
1229 let taken_reverts = extended.take_n_reverts(1);
1231 assert_eq!(taken_reverts, bundle2.reverts);
1232 }
1233
1234 #[test]
1235 fn prepend_state() {
1236 let address1 = account1();
1237 let address2 = account2();
1238
1239 let account1 = AccountInfo { nonce: 1, ..Default::default() };
1240 let account1_changed = AccountInfo { nonce: 1, ..Default::default() };
1241 let account2 = AccountInfo { nonce: 1, ..Default::default() };
1242
1243 let present_state = BundleState::builder(2..=2)
1244 .state_present_account_info(address1, account1_changed.clone())
1245 .build();
1246 assert_eq!(present_state.reverts.len(), 1);
1247 let previous_state = BundleState::builder(1..=1)
1248 .state_present_account_info(address1, account1)
1249 .state_present_account_info(address2, account2.clone())
1250 .build();
1251 assert_eq!(previous_state.reverts.len(), 1);
1252
1253 let mut test = present_state;
1254
1255 test.prepend_state(previous_state);
1256
1257 assert_eq!(test.state.len(), 2);
1258 assert_eq!(test.reverts.len(), 1);
1260 assert_eq!(test.state.get(&address1).unwrap().info, Some(account1_changed));
1262 assert_eq!(test.state.get(&address2).unwrap().info, Some(account2));
1264 }
1265
1266 #[test]
1267 fn test_getters() {
1268 let mut builder = BundleBuilder::new(0..=3);
1269
1270 assert!(builder.get_states().is_empty());
1272 builder.get_states_mut().insert(account1());
1273 assert!(builder.get_states().contains(&account1()));
1274
1275 assert!(builder.get_state_original_mut().is_empty());
1277 builder.get_state_original_mut().insert(account1(), AccountInfo::default());
1278 assert!(builder.get_state_original_mut().contains_key(&account1()));
1279
1280 assert!(builder.get_state_present_mut().is_empty());
1282 builder.get_state_present_mut().insert(account1(), AccountInfo::default());
1283 assert!(builder.get_state_present_mut().contains_key(&account1()));
1284
1285 assert!(builder.get_state_storage_mut().is_empty());
1287 builder.get_state_storage_mut().insert(account1(), HashMap::default());
1288 assert!(builder.get_state_storage_mut().contains_key(&account1()));
1289
1290 assert!(builder.get_reverts_mut().is_empty());
1292 builder.get_reverts_mut().insert((0, account1()));
1293 assert!(builder.get_reverts_mut().contains(&(0, account1())));
1294
1295 assert_eq!(builder.get_revert_range_mut().clone(), 0..=3);
1297
1298 assert!(builder.get_revert_account_mut().is_empty());
1300 builder.get_revert_account_mut().insert((0, account1()), Some(None));
1301 assert!(builder.get_revert_account_mut().contains_key(&(0, account1())));
1302
1303 assert!(builder.get_revert_storage_mut().is_empty());
1305 builder.get_revert_storage_mut().insert((0, account1()), vec![(slot1(), U256::from(0))]);
1306 assert!(builder.get_revert_storage_mut().contains_key(&(0, account1())));
1307
1308 assert!(builder.get_contracts_mut().is_empty());
1310 builder.get_contracts_mut().insert(B256::default(), Bytecode::default());
1311 assert!(builder.get_contracts_mut().contains_key(&B256::default()));
1312 }
1313}