1use super::{
2 changes::{PlainStorageChangeset, StateChangeset},
3 reverts::{AccountInfoRevert, Reverts},
4 AccountRevert, AccountStatus, BundleAccount, PlainStateReverts, RevertToSlot, StorageSlot,
5 TransitionState,
6};
7use core::{mem, ops::RangeInclusive};
8use revm_interpreter::primitives::{
9 hash_map::{self, Entry},
10 AccountInfo, Address, Bytecode, HashMap, HashSet, B256, KECCAK_EMPTY, U256,
11};
12use std::{
13 collections::{BTreeMap, BTreeSet},
14 vec::Vec,
15};
16
17#[derive(Debug)]
19pub struct BundleBuilder {
20 states: HashSet<Address>,
21 state_original: HashMap<Address, AccountInfo>,
22 state_present: HashMap<Address, AccountInfo>,
23 state_storage: HashMap<Address, HashMap<U256, (U256, U256)>>,
24
25 reverts: BTreeSet<(u64, Address)>,
26 revert_range: RangeInclusive<u64>,
27 revert_account: HashMap<(u64, Address), Option<Option<AccountInfo>>>,
28 revert_storage: HashMap<(u64, Address), Vec<(U256, U256)>>,
29
30 contracts: HashMap<B256, Bytecode>,
31}
32
33#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
35pub enum OriginalValuesKnown {
36 Yes,
41 No,
47}
48impl OriginalValuesKnown {
49 pub fn is_not_known(&self) -> bool {
51 matches!(self, Self::No)
52 }
53}
54
55impl Default for BundleBuilder {
56 fn default() -> Self {
57 BundleBuilder {
58 states: HashSet::default(),
59 state_original: HashMap::default(),
60 state_present: HashMap::default(),
61 state_storage: HashMap::default(),
62 reverts: BTreeSet::new(),
63 revert_range: 0..=0,
64 revert_account: HashMap::default(),
65 revert_storage: HashMap::default(),
66 contracts: HashMap::default(),
67 }
68 }
69}
70
71impl BundleBuilder {
72 pub fn new(revert_range: RangeInclusive<u64>) -> Self {
76 BundleBuilder {
77 revert_range,
78 ..Default::default()
79 }
80 }
81
82 pub fn apply<F>(self, f: F) -> Self
84 where
85 F: FnOnce(Self) -> Self,
86 {
87 f(self)
88 }
89
90 pub fn apply_mut<F>(&mut self, f: F) -> &mut Self
92 where
93 F: FnOnce(&mut Self),
94 {
95 f(self);
96 self
97 }
98
99 pub fn state_address(mut self, address: Address) -> Self {
101 self.set_state_address(address);
102 self
103 }
104
105 pub fn state_original_account_info(mut self, address: Address, original: AccountInfo) -> Self {
107 self.set_state_original_account_info(address, original);
108 self
109 }
110
111 pub fn state_present_account_info(mut self, address: Address, present: AccountInfo) -> Self {
113 self.set_state_present_account_info(address, present);
114 self
115 }
116
117 pub fn state_storage(mut self, address: Address, storage: HashMap<U256, (U256, U256)>) -> Self {
119 self.set_state_storage(address, storage);
120 self
121 }
122
123 pub fn revert_address(mut self, block_number: u64, address: Address) -> Self {
128 self.set_revert_address(block_number, address);
129 self
130 }
131
132 pub fn revert_account_info(
137 mut self,
138 block_number: u64,
139 address: Address,
140 account: Option<Option<AccountInfo>>,
141 ) -> Self {
142 self.set_revert_account_info(block_number, address, account);
143 self
144 }
145
146 pub fn revert_storage(
151 mut self,
152 block_number: u64,
153 address: Address,
154 storage: Vec<(U256, U256)>,
155 ) -> Self {
156 self.set_revert_storage(block_number, address, storage);
157 self
158 }
159
160 pub fn contract(mut self, address: B256, bytecode: Bytecode) -> Self {
162 self.set_contract(address, bytecode);
163 self
164 }
165
166 pub fn set_state_address(&mut self, address: Address) -> &mut Self {
168 self.states.insert(address);
169 self
170 }
171
172 pub fn set_state_original_account_info(
174 &mut self,
175 address: Address,
176 original: AccountInfo,
177 ) -> &mut Self {
178 self.states.insert(address);
179 self.state_original.insert(address, original);
180 self
181 }
182
183 pub fn set_state_present_account_info(
185 &mut self,
186 address: Address,
187 present: AccountInfo,
188 ) -> &mut Self {
189 self.states.insert(address);
190 self.state_present.insert(address, present);
191 self
192 }
193
194 pub fn set_state_storage(
196 &mut self,
197 address: Address,
198 storage: HashMap<U256, (U256, U256)>,
199 ) -> &mut Self {
200 self.states.insert(address);
201 self.state_storage.insert(address, storage);
202 self
203 }
204
205 pub fn set_revert_address(&mut self, block_number: u64, address: Address) -> &mut Self {
207 self.reverts.insert((block_number, address));
208 self
209 }
210
211 pub fn set_revert_account_info(
213 &mut self,
214 block_number: u64,
215 address: Address,
216 account: Option<Option<AccountInfo>>,
217 ) -> &mut Self {
218 self.reverts.insert((block_number, address));
219 self.revert_account.insert((block_number, address), account);
220 self
221 }
222
223 pub fn set_revert_storage(
225 &mut self,
226 block_number: u64,
227 address: Address,
228 storage: Vec<(U256, U256)>,
229 ) -> &mut Self {
230 self.reverts.insert((block_number, address));
231 self.revert_storage.insert((block_number, address), storage);
232 self
233 }
234
235 pub fn set_contract(&mut self, address: B256, bytecode: Bytecode) -> &mut Self {
237 self.contracts.insert(address, bytecode);
238 self
239 }
240
241 pub fn build(mut self) -> BundleState {
243 let mut state_size = 0;
244 let state = self
245 .states
246 .into_iter()
247 .map(|address| {
248 let storage = self
249 .state_storage
250 .remove(&address)
251 .map(|s| {
252 s.into_iter()
253 .map(|(k, (o_val, p_val))| (k, StorageSlot::new_changed(o_val, p_val)))
254 .collect()
255 })
256 .unwrap_or_default();
257 let bundle_account = BundleAccount::new(
258 self.state_original.remove(&address),
259 self.state_present.remove(&address),
260 storage,
261 AccountStatus::Changed,
262 );
263 state_size += bundle_account.size_hint();
264 (address, bundle_account)
265 })
266 .collect();
267
268 let mut reverts_size = 0;
269 let mut reverts_map = BTreeMap::new();
270 for block_number in self.revert_range {
271 reverts_map.insert(block_number, Vec::new());
272 }
273 self.reverts
274 .into_iter()
275 .for_each(|(block_number, address)| {
276 let account = match self
277 .revert_account
278 .remove(&(block_number, address))
279 .unwrap_or_default()
280 {
281 Some(Some(account)) => AccountInfoRevert::RevertTo(account),
282 Some(None) => AccountInfoRevert::DeleteIt,
283 None => AccountInfoRevert::DoNothing,
284 };
285 let storage = self
286 .revert_storage
287 .remove(&(block_number, address))
288 .map(|s| {
289 s.into_iter()
290 .map(|(k, v)| (k, RevertToSlot::Some(v)))
291 .collect()
292 })
293 .unwrap_or_default();
294 let account_revert = AccountRevert {
295 account,
296 storage,
297 previous_status: AccountStatus::Changed,
298 wipe_storage: false,
299 };
300
301 if reverts_map.contains_key(&block_number) {
302 reverts_size += account_revert.size_hint();
303 reverts_map
304 .entry(block_number)
305 .or_insert(Vec::new())
306 .push((address, account_revert));
307 }
308 });
309
310 BundleState {
311 state,
312 contracts: self.contracts,
313 reverts: Reverts::new(reverts_map.into_values().collect()),
314 state_size,
315 reverts_size,
316 }
317 }
318
319 pub fn get_states(&self) -> &HashSet<Address> {
321 &self.states
322 }
323
324 pub fn get_states_mut(&mut self) -> &mut HashSet<Address> {
326 &mut self.states
327 }
328
329 pub fn get_state_original_mut(&mut self) -> &mut HashMap<Address, AccountInfo> {
331 &mut self.state_original
332 }
333
334 pub fn get_state_present_mut(&mut self) -> &mut HashMap<Address, AccountInfo> {
336 &mut self.state_present
337 }
338
339 pub fn get_state_storage_mut(&mut self) -> &mut HashMap<Address, HashMap<U256, (U256, U256)>> {
341 &mut self.state_storage
342 }
343
344 pub fn get_reverts_mut(&mut self) -> &mut BTreeSet<(u64, Address)> {
346 &mut self.reverts
347 }
348
349 pub fn get_revert_range_mut(&mut self) -> &mut RangeInclusive<u64> {
351 &mut self.revert_range
352 }
353
354 pub fn get_revert_account_mut(
356 &mut self,
357 ) -> &mut HashMap<(u64, Address), Option<Option<AccountInfo>>> {
358 &mut self.revert_account
359 }
360
361 pub fn get_revert_storage_mut(&mut self) -> &mut HashMap<(u64, Address), Vec<(U256, U256)>> {
363 &mut self.revert_storage
364 }
365
366 pub fn get_contracts_mut(&mut self) -> &mut HashMap<B256, Bytecode> {
368 &mut self.contracts
369 }
370}
371
372#[derive(Debug)]
374pub enum BundleRetention {
375 PlainState,
377 Reverts,
379}
380
381impl BundleRetention {
382 pub fn includes_reverts(&self) -> bool {
384 matches!(self, Self::Reverts)
385 }
386}
387
388#[derive(Default, Clone, Debug, PartialEq, Eq)]
396#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
397pub struct BundleState {
398 pub state: HashMap<Address, BundleAccount>,
400 pub contracts: HashMap<B256, Bytecode>,
402 pub reverts: Reverts,
407 pub state_size: usize,
409 pub reverts_size: usize,
411}
412
413impl BundleState {
414 pub fn builder(revert_range: RangeInclusive<u64>) -> BundleBuilder {
416 BundleBuilder::new(revert_range)
417 }
418
419 pub fn new(
421 state: impl IntoIterator<
422 Item = (
423 Address,
424 Option<AccountInfo>,
425 Option<AccountInfo>,
426 HashMap<U256, (U256, U256)>,
427 ),
428 >,
429 reverts: impl IntoIterator<
430 Item = impl IntoIterator<
431 Item = (
432 Address,
433 Option<Option<AccountInfo>>,
434 impl IntoIterator<Item = (U256, U256)>,
435 ),
436 >,
437 >,
438 contracts: impl IntoIterator<Item = (B256, Bytecode)>,
439 ) -> Self {
440 let mut state_size = 0;
442 let state = state
443 .into_iter()
444 .map(|(address, original, present, storage)| {
445 let account = BundleAccount::new(
446 original,
447 present,
448 storage
449 .into_iter()
450 .map(|(k, (o_val, p_val))| (k, StorageSlot::new_changed(o_val, p_val)))
451 .collect(),
452 AccountStatus::Changed,
453 );
454 state_size += account.size_hint();
455 (address, account)
456 })
457 .collect();
458
459 let mut reverts_size = 0;
461 let reverts = reverts
462 .into_iter()
463 .map(|block_reverts| {
464 block_reverts
465 .into_iter()
466 .map(|(address, account, storage)| {
467 let account = match account {
468 Some(Some(account)) => AccountInfoRevert::RevertTo(account),
469 Some(None) => AccountInfoRevert::DeleteIt,
470 None => AccountInfoRevert::DoNothing,
471 };
472 let revert = AccountRevert {
473 account,
474 storage: storage
475 .into_iter()
476 .map(|(k, v)| (k, RevertToSlot::Some(v)))
477 .collect(),
478 previous_status: AccountStatus::Changed,
479 wipe_storage: false,
480 };
481 reverts_size += revert.size_hint();
482 (address, revert)
483 })
484 .collect::<Vec<_>>()
485 })
486 .collect::<Vec<_>>();
487
488 Self {
489 state,
490 contracts: contracts.into_iter().collect(),
491 reverts: Reverts::new(reverts),
492 state_size,
493 reverts_size,
494 }
495 }
496
497 pub fn size_hint(&self) -> usize {
501 self.state_size + self.reverts_size + self.contracts.len()
502 }
503
504 pub fn state(&self) -> &HashMap<Address, BundleAccount> {
506 &self.state
507 }
508
509 pub fn is_empty(&self) -> bool {
511 self.len() == 0
512 }
513
514 pub fn len(&self) -> usize {
516 self.state.len()
517 }
518
519 pub fn account(&self, address: &Address) -> Option<&BundleAccount> {
521 self.state.get(address)
522 }
523
524 pub fn bytecode(&self, hash: &B256) -> Option<Bytecode> {
526 self.contracts.get(hash).cloned()
527 }
528
529 pub fn apply_transitions_and_create_reverts(
535 &mut self,
536 transitions: TransitionState,
537 retention: BundleRetention,
538 ) {
539 let include_reverts = retention.includes_reverts();
540 let reverts_capacity = if include_reverts {
542 transitions.transitions.len()
543 } else {
544 0
545 };
546 let mut reverts = Vec::with_capacity(reverts_capacity);
547
548 for (address, transition) in transitions.transitions.into_iter() {
549 if let Some((hash, new_bytecode)) = transition.has_new_contract() {
551 self.contracts.insert(hash, new_bytecode.clone());
552 }
553 let revert = match self.state.entry(address) {
555 hash_map::Entry::Occupied(mut entry) => {
556 let entry = entry.get_mut();
557 self.state_size -= entry.size_hint();
558 let revert = entry.update_and_create_revert(transition);
560 self.state_size += entry.size_hint();
562 revert
563 }
564 hash_map::Entry::Vacant(entry) => {
565 let present_bundle = transition.present_bundle_account();
567 let revert = transition.create_revert();
568 if revert.is_some() {
569 self.state_size += present_bundle.size_hint();
570 entry.insert(present_bundle);
571 }
572 revert
573 }
574 };
575
576 if let Some(revert) = revert.filter(|_| include_reverts) {
578 self.reverts_size += revert.size_hint();
579 reverts.push((address, revert));
580 }
581 }
582
583 self.reverts.push(reverts);
584 }
585
586 pub fn to_plain_state(&self, is_value_known: OriginalValuesKnown) -> StateChangeset {
589 let state_len = self.state.len();
591 let mut accounts = Vec::with_capacity(state_len);
592 let mut storage = Vec::with_capacity(state_len);
593
594 for (address, account) in self.state.iter() {
595 let was_destroyed = account.was_destroyed();
597 if is_value_known.is_not_known() || account.is_info_changed() {
598 let info = account.info.as_ref().map(AccountInfo::copy_without_code);
599 accounts.push((*address, info));
600 }
601
602 let mut account_storage_changed = Vec::with_capacity(account.storage.len());
607
608 for (key, slot) in account.storage.iter().map(|(k, v)| (*k, *v)) {
609 let destroyed_and_not_zero = was_destroyed && !slot.present_value.is_zero();
612
613 let not_destroyed_and_changed = !was_destroyed && slot.is_changed();
616
617 if is_value_known.is_not_known()
618 || destroyed_and_not_zero
619 || not_destroyed_and_changed
620 {
621 account_storage_changed.push((key, slot.present_value));
622 }
623 }
624
625 if !account_storage_changed.is_empty() || was_destroyed {
626 storage.push(PlainStorageChangeset {
628 address: *address,
629 wipe_storage: was_destroyed,
630 storage: account_storage_changed,
631 });
632 }
633 }
634
635 let contracts = self
636 .contracts
637 .iter()
638 .filter(|(b, _)| **b != KECCAK_EMPTY)
640 .map(|(b, code)| (*b, code.clone()))
641 .collect::<Vec<_>>();
642 StateChangeset {
643 accounts,
644 storage,
645 contracts,
646 }
647 }
648
649 #[deprecated = "Use `to_plain_state` instead"]
651 pub fn into_plain_state(self, is_value_known: OriginalValuesKnown) -> StateChangeset {
652 self.to_plain_state(is_value_known)
653 }
654
655 pub fn to_plain_state_and_reverts(
658 &self,
659 is_value_known: OriginalValuesKnown,
660 ) -> (StateChangeset, PlainStateReverts) {
661 (
662 self.to_plain_state(is_value_known),
663 self.reverts.to_plain_state_reverts(),
664 )
665 }
666
667 #[deprecated = "Use `to_plain_state_and_reverts` instead"]
670 pub fn into_plain_state_and_reverts(
671 self,
672 is_value_known: OriginalValuesKnown,
673 ) -> (StateChangeset, PlainStateReverts) {
674 self.to_plain_state_and_reverts(is_value_known)
675 }
676
677 pub fn extend_state(&mut self, other_state: HashMap<Address, BundleAccount>) {
681 for (address, other_account) in other_state {
682 match self.state.entry(address) {
683 hash_map::Entry::Occupied(mut entry) => {
684 let this = entry.get_mut();
685 self.state_size -= this.size_hint();
686
687 if other_account.was_destroyed() {
690 this.storage = other_account.storage;
691 } else {
692 for (key, storage_slot) in other_account.storage {
694 this.storage
696 .entry(key)
697 .or_insert(storage_slot)
698 .present_value = storage_slot.present_value;
699 }
700 }
701 this.info = other_account.info;
702 this.status.transition(other_account.status);
703
704 self.state_size += this.size_hint();
706 }
707 hash_map::Entry::Vacant(entry) => {
708 self.state_size += other_account.size_hint();
710 entry.insert(other_account);
711 }
712 }
713 }
714 }
715 pub fn extend(&mut self, mut other: Self) {
724 for (address, revert) in other.reverts.iter_mut().flatten() {
727 if revert.wipe_storage {
728 if let Some(this_account) = self.state.get_mut(address) {
731 for (key, value) in this_account.storage.drain() {
734 revert
735 .storage
736 .entry(key)
737 .or_insert(RevertToSlot::Some(value.present_value));
738 }
739
740 if this_account.was_destroyed() {
742 revert.wipe_storage = false;
743 }
744 }
745 }
746
747 self.reverts_size += revert.size_hint();
749 }
750 self.extend_state(other.state);
752 self.contracts.extend(other.contracts);
754 self.reverts.extend(other.reverts);
756 }
757
758 pub fn take_n_reverts(&mut self, reverts_to_take: usize) -> Reverts {
760 if reverts_to_take > self.reverts.len() {
762 return self.take_all_reverts();
763 }
764 let (detach, this) = self.reverts.split_at(reverts_to_take);
765 let detached_reverts = Reverts::new(detach.to_vec());
766 self.reverts_size = this
767 .iter()
768 .flatten()
769 .fold(0, |acc, (_, revert)| acc + revert.size_hint());
770 self.reverts = Reverts::new(this.to_vec());
771 detached_reverts
772 }
773
774 pub fn take_all_reverts(&mut self) -> Reverts {
776 self.reverts_size = 0;
777 core::mem::take(&mut self.reverts)
778 }
779
780 pub fn revert_latest(&mut self) -> bool {
786 if let Some(reverts) = self.reverts.pop() {
788 for (address, revert_account) in reverts.into_iter() {
789 self.reverts_size -= revert_account.size_hint();
790 match self.state.entry(address) {
791 Entry::Occupied(mut entry) => {
792 let account = entry.get_mut();
793 self.state_size -= account.size_hint();
794 if account.revert(revert_account) {
795 entry.remove();
796 } else {
797 self.state_size += account.size_hint();
798 }
799 }
800 Entry::Vacant(entry) => {
801 let mut account = BundleAccount::new(
804 None,
805 None,
806 HashMap::default(),
807 AccountStatus::LoadedNotExisting,
808 );
809 if !account.revert(revert_account) {
810 self.state_size += account.size_hint();
811 entry.insert(account);
812 }
813 }
814 }
815 }
816 return true;
817 }
818
819 false
820 }
821
822 pub fn revert(&mut self, mut num_transitions: usize) {
826 if num_transitions == 0 {
827 return;
828 }
829
830 while self.revert_latest() {
831 num_transitions -= 1;
832 if num_transitions == 0 {
833 break;
835 }
836 }
837 }
838
839 pub fn prepend_state(&mut self, mut other: BundleState) {
844 let this_bundle = mem::take(self);
846 other.extend_state(this_bundle.state);
848 other.contracts.extend(this_bundle.contracts);
850 mem::swap(self, &mut other)
852 }
853}
854
855#[cfg(test)]
856mod tests {
857 use super::*;
858 use crate::{db::StorageWithOriginalValues, TransitionAccount};
859
860 #[test]
861 fn transition_states() {
862 let address = Address::new([0x01; 20]);
864 let acc1 = AccountInfo {
865 balance: U256::from(10),
866 nonce: 1,
867 code_hash: KECCAK_EMPTY,
868 code: None,
869 };
870
871 let mut bundle_state = BundleState::default();
872
873 let transition = TransitionAccount {
876 info: Some(acc1),
877 status: AccountStatus::InMemoryChange,
878 previous_info: None,
879 previous_status: AccountStatus::LoadedNotExisting,
880 storage: StorageWithOriginalValues::default(),
881 storage_was_destroyed: false,
882 };
883
884 bundle_state.apply_transitions_and_create_reverts(
886 TransitionState::single(address, transition.clone()),
887 BundleRetention::Reverts,
888 );
889 }
890
891 const fn account1() -> Address {
892 Address::new([0x60; 20])
893 }
894
895 const fn account2() -> Address {
896 Address::new([0x61; 20])
897 }
898
899 fn slot1() -> U256 {
900 U256::from(5)
901 }
902
903 fn slot2() -> U256 {
904 U256::from(7)
905 }
906
907 fn test_bundle1() -> BundleState {
909 BundleState::new(
911 vec![
912 (
913 account1(),
914 None,
915 Some(AccountInfo {
916 nonce: 1,
917 balance: U256::from(10),
918 code_hash: KECCAK_EMPTY,
919 code: None,
920 }),
921 HashMap::from_iter([
922 (slot1(), (U256::from(0), U256::from(10))),
923 (slot2(), (U256::from(0), U256::from(15))),
924 ]),
925 ),
926 (
927 account2(),
928 None,
929 Some(AccountInfo {
930 nonce: 1,
931 balance: U256::from(10),
932 code_hash: KECCAK_EMPTY,
933 code: None,
934 }),
935 HashMap::default(),
936 ),
937 ],
938 vec![vec![
939 (
940 account1(),
941 Some(None),
942 vec![(slot1(), U256::from(0)), (slot2(), U256::from(0))],
943 ),
944 (account2(), Some(None), vec![]),
945 ]],
946 vec![],
947 )
948 }
949
950 fn test_bundle2() -> BundleState {
952 BundleState::new(
954 vec![(
955 account1(),
956 None,
957 Some(AccountInfo {
958 nonce: 3,
959 balance: U256::from(20),
960 code_hash: KECCAK_EMPTY,
961 code: None,
962 }),
963 HashMap::from_iter([(slot1(), (U256::from(0), U256::from(15)))]),
964 )],
965 vec![vec![(
966 account1(),
967 Some(Some(AccountInfo {
968 nonce: 1,
969 balance: U256::from(10),
970 code_hash: KECCAK_EMPTY,
971 code: None,
972 })),
973 vec![(slot1(), U256::from(10))],
974 )]],
975 vec![],
976 )
977 }
978
979 fn test_bundle3() -> BundleState {
981 BundleState::builder(0..=0)
982 .state_present_account_info(
983 account1(),
984 AccountInfo {
985 nonce: 1,
986 balance: U256::from(10),
987 code_hash: KECCAK_EMPTY,
988 code: None,
989 },
990 )
991 .state_storage(
992 account1(),
993 HashMap::from_iter([(slot1(), (U256::from(0), U256::from(10)))]),
994 )
995 .state_address(account2())
996 .state_present_account_info(
997 account2(),
998 AccountInfo {
999 nonce: 1,
1000 balance: U256::from(10),
1001 code_hash: KECCAK_EMPTY,
1002 code: None,
1003 },
1004 )
1005 .revert_address(0, account1())
1006 .revert_account_info(0, account1(), Some(None))
1007 .revert_storage(0, account1(), vec![(slot1(), U256::from(0))])
1008 .revert_account_info(0, account2(), Some(None))
1009 .build()
1010 }
1011
1012 fn test_bundle4() -> BundleState {
1014 BundleState::builder(0..=0)
1015 .state_present_account_info(
1016 account1(),
1017 AccountInfo {
1018 nonce: 3,
1019 balance: U256::from(20),
1020 code_hash: KECCAK_EMPTY,
1021 code: None,
1022 },
1023 )
1024 .state_storage(
1025 account1(),
1026 HashMap::from_iter([(slot1(), (U256::from(0), U256::from(15)))]),
1027 )
1028 .revert_address(0, account1())
1029 .revert_account_info(
1030 0,
1031 account1(),
1032 Some(Some(AccountInfo {
1033 nonce: 1,
1034 balance: U256::from(10),
1035 code_hash: KECCAK_EMPTY,
1036 code: None,
1037 })),
1038 )
1039 .revert_storage(0, account1(), vec![(slot1(), U256::from(10))])
1040 .build()
1041 }
1042
1043 fn sanity_path(bundle1: BundleState, bundle2: BundleState) {
1044 let mut extended = bundle1.clone();
1045 extended.extend(bundle2.clone());
1046
1047 let mut reverted = extended.clone();
1048 reverted.revert(0);
1050 assert_eq!(reverted, extended);
1051
1052 reverted.revert(1);
1054 assert_eq!(reverted, bundle1);
1055
1056 reverted.revert(1);
1058 assert_eq!(reverted, BundleState::default());
1059
1060 let mut reverted = extended.clone();
1061
1062 reverted.revert(10);
1064 assert_eq!(reverted, BundleState::default());
1065 }
1066
1067 #[test]
1068 fn extend_on_destroyed_values() {
1069 let base_bundle1 = test_bundle1();
1070 let base_bundle2 = test_bundle2();
1071
1072 let mut b1 = base_bundle1.clone();
1077 let mut b2 = base_bundle2.clone();
1078 b1.state.get_mut(&account1()).unwrap().status = AccountStatus::Destroyed;
1079 b2.state.get_mut(&account1()).unwrap().status = AccountStatus::Changed;
1080 b1.extend(b2);
1081 assert_eq!(
1082 b1.state.get_mut(&account1()).unwrap().status,
1083 AccountStatus::DestroyedChanged
1084 );
1085
1086 let mut b1 = base_bundle1.clone();
1091 let mut b2 = base_bundle2.clone();
1092 b1.state.get_mut(&account1()).unwrap().status = AccountStatus::Changed;
1093 b2.state.get_mut(&account1()).unwrap().status = AccountStatus::Destroyed;
1094 b2.reverts[0][0].1.wipe_storage = true;
1095 b1.extend(b2);
1096 assert_eq!(
1097 b1.state.get_mut(&account1()).unwrap().status,
1098 AccountStatus::Destroyed
1099 );
1100
1101 let mut revert1 = base_bundle2.reverts[0][0].clone();
1104 revert1.1.wipe_storage = true;
1105 revert1
1106 .1
1107 .storage
1108 .insert(slot2(), RevertToSlot::Some(U256::from(15)));
1109
1110 assert_eq!(
1111 b1.reverts.as_ref(),
1112 vec![base_bundle1.reverts[0].clone(), vec![revert1]],
1113 );
1114
1115 let mut b1 = base_bundle1.clone();
1121 let mut b2 = base_bundle2.clone();
1122 b1.state.get_mut(&account1()).unwrap().status = AccountStatus::InMemoryChange;
1123 b2.state.get_mut(&account1()).unwrap().status = AccountStatus::Changed;
1124 b1.extend(b2);
1125 assert_eq!(
1126 b1.state.get_mut(&account1()).unwrap().status,
1127 AccountStatus::InMemoryChange
1128 );
1129 }
1130
1131 #[test]
1132 fn test_sanity_path() {
1133 sanity_path(test_bundle1(), test_bundle2());
1134 sanity_path(test_bundle3(), test_bundle4());
1135 }
1136
1137 #[test]
1138 fn test_multi_reverts_with_delete() {
1139 let mut state = BundleBuilder::new(0..=3)
1140 .revert_address(0, account1())
1141 .revert_account_info(2, account1(), Some(Some(AccountInfo::default())))
1142 .revert_account_info(3, account1(), Some(None))
1143 .build();
1144
1145 state.revert_latest();
1146 assert_eq!(state.state.get(&account1()), None);
1148
1149 state.revert_latest();
1150 assert_eq!(
1152 state.state.get(&account1()),
1153 Some(&BundleAccount::new(
1154 None,
1155 Some(AccountInfo::default()),
1156 HashMap::default(),
1157 AccountStatus::Changed
1158 ))
1159 );
1160 }
1161
1162 #[test]
1163 fn test_revert_capacity() {
1164 let state = BundleState::builder(0..=3)
1165 .revert_address(0, account1())
1166 .revert_address(2, account2())
1167 .revert_account_info(0, account1(), Some(None))
1168 .revert_account_info(2, account2(), None)
1169 .revert_storage(0, account1(), vec![(slot1(), U256::from(10))])
1170 .build();
1171
1172 assert_eq!(state.reverts.len(), 4);
1173 assert_eq!(state.reverts[1], vec![]);
1174 assert_eq!(state.reverts[3], vec![]);
1175 assert_eq!(state.reverts[0].len(), 1);
1176 assert_eq!(state.reverts[2].len(), 1);
1177
1178 let (addr1, revert1) = &state.reverts[0][0];
1179 assert_eq!(addr1, &account1());
1180 assert_eq!(revert1.account, AccountInfoRevert::DeleteIt);
1181
1182 let (addr2, revert2) = &state.reverts[2][0];
1183 assert_eq!(addr2, &account2());
1184 assert_eq!(revert2.account, AccountInfoRevert::DoNothing);
1185 }
1186
1187 #[test]
1188 fn take_reverts() {
1189 let bundle1 = test_bundle1();
1190 let bundle2 = test_bundle2();
1191
1192 let mut extended = bundle1.clone();
1193 extended.extend(bundle2.clone());
1194
1195 assert_eq!(extended.reverts.len(), 2);
1197
1198 let mut extended2 = extended.clone();
1200 assert_eq!(extended2.take_n_reverts(100), extended.reverts);
1201
1202 let mut extended2 = extended.clone();
1204 assert_eq!(extended2.take_all_reverts(), extended.reverts);
1205
1206 let taken_reverts = extended.take_n_reverts(0);
1208 assert_eq!(taken_reverts, Reverts::default());
1209 assert_eq!(extended.reverts.len(), 2);
1210
1211 let taken_reverts = extended.take_n_reverts(1);
1213 assert_eq!(taken_reverts, bundle1.reverts);
1214
1215 let taken_reverts = extended.take_n_reverts(1);
1217 assert_eq!(taken_reverts, bundle2.reverts);
1218 }
1219
1220 #[test]
1221 fn prepend_state() {
1222 let address1 = account1();
1223 let address2 = account2();
1224
1225 let account1 = AccountInfo {
1226 nonce: 1,
1227 ..Default::default()
1228 };
1229 let account1_changed = AccountInfo {
1230 nonce: 1,
1231 ..Default::default()
1232 };
1233 let account2 = AccountInfo {
1234 nonce: 1,
1235 ..Default::default()
1236 };
1237
1238 let present_state = BundleState::builder(2..=2)
1239 .state_present_account_info(address1, account1_changed.clone())
1240 .build();
1241 assert_eq!(present_state.reverts.len(), 1);
1242 let previous_state = BundleState::builder(1..=1)
1243 .state_present_account_info(address1, account1)
1244 .state_present_account_info(address2, account2.clone())
1245 .build();
1246 assert_eq!(previous_state.reverts.len(), 1);
1247
1248 let mut test = present_state;
1249
1250 test.prepend_state(previous_state);
1251
1252 assert_eq!(test.state.len(), 2);
1253 assert_eq!(test.reverts.len(), 1);
1255 assert_eq!(
1257 test.state.get(&address1).unwrap().info,
1258 Some(account1_changed)
1259 );
1260 assert_eq!(test.state.get(&address2).unwrap().info, Some(account2));
1262 }
1263
1264 #[test]
1265 fn test_getters() {
1266 let mut builder = BundleBuilder::new(0..=3);
1267
1268 assert!(builder.get_states().is_empty());
1270 builder.get_states_mut().insert(account1());
1271 assert!(builder.get_states().contains(&account1()));
1272
1273 assert!(builder.get_state_original_mut().is_empty());
1275 builder
1276 .get_state_original_mut()
1277 .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
1283 .get_state_present_mut()
1284 .insert(account1(), AccountInfo::default());
1285 assert!(builder.get_state_present_mut().contains_key(&account1()));
1286
1287 assert!(builder.get_state_storage_mut().is_empty());
1289 builder
1290 .get_state_storage_mut()
1291 .insert(account1(), HashMap::default());
1292 assert!(builder.get_state_storage_mut().contains_key(&account1()));
1293
1294 assert!(builder.get_reverts_mut().is_empty());
1296 builder.get_reverts_mut().insert((0, account1()));
1297 assert!(builder.get_reverts_mut().contains(&(0, account1())));
1298
1299 assert_eq!(builder.get_revert_range_mut().clone(), 0..=3);
1301
1302 assert!(builder.get_revert_account_mut().is_empty());
1304 builder
1305 .get_revert_account_mut()
1306 .insert((0, account1()), Some(None));
1307 assert!(builder
1308 .get_revert_account_mut()
1309 .contains_key(&(0, account1())));
1310
1311 assert!(builder.get_revert_storage_mut().is_empty());
1313 builder
1314 .get_revert_storage_mut()
1315 .insert((0, account1()), vec![(slot1(), U256::from(0))]);
1316 assert!(builder
1317 .get_revert_storage_mut()
1318 .contains_key(&(0, account1())));
1319
1320 assert!(builder.get_contracts_mut().is_empty());
1322 builder
1323 .get_contracts_mut()
1324 .insert(B256::default(), Bytecode::default());
1325 assert!(builder.get_contracts_mut().contains_key(&B256::default()));
1326 }
1327}