1use super::{
2 changes::{PlainStorageChangeset, StateChangeset},
3 reverts::{AccountInfoRevert, Reverts},
4 AccountRevert, AccountStatus, BundleAccount, PlainStateReverts, RevertToSlot, StorageSlot,
5 TransitionState,
6};
7use bytecode::Bytecode;
8use core::{mem, ops::RangeInclusive};
9use primitives::{
10 hash_map::Entry, Address, HashMap, HashSet, StorageKey, StorageValue, B256, KECCAK_EMPTY,
11};
12use state::AccountInfo;
13use std::{
14 collections::{BTreeMap, BTreeSet},
15 vec::Vec,
16};
17
18#[derive(Debug)]
20pub struct BundleBuilder {
21 states: HashSet<Address>,
22 state_original: HashMap<Address, AccountInfo>,
23 state_present: HashMap<Address, AccountInfo>,
24 state_storage: HashMap<Address, HashMap<StorageKey, (StorageValue, StorageValue)>>,
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<(StorageKey, StorageValue)>>,
30
31 contracts: HashMap<B256, 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 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: HashSet::default(),
60 state_original: HashMap::default(),
61 state_present: HashMap::default(),
62 state_storage: HashMap::default(),
63 reverts: BTreeSet::new(),
64 revert_range: 0..=0,
65 revert_account: HashMap::default(),
66 revert_storage: HashMap::default(),
67 contracts: HashMap::default(),
68 }
69 }
70}
71
72impl BundleBuilder {
73 pub fn new(revert_range: RangeInclusive<u64>) -> Self {
77 BundleBuilder {
78 revert_range,
79 ..Default::default()
80 }
81 }
82
83 pub fn apply<F>(self, f: F) -> Self
85 where
86 F: FnOnce(Self) -> Self,
87 {
88 f(self)
89 }
90
91 pub fn apply_mut<F>(&mut self, f: F) -> &mut Self
93 where
94 F: FnOnce(&mut Self),
95 {
96 f(self);
97 self
98 }
99
100 pub fn state_address(mut self, address: Address) -> Self {
102 self.set_state_address(address);
103 self
104 }
105
106 pub fn state_original_account_info(mut self, address: Address, original: AccountInfo) -> Self {
108 self.set_state_original_account_info(address, original);
109 self
110 }
111
112 pub fn state_present_account_info(mut self, address: Address, present: AccountInfo) -> Self {
114 self.set_state_present_account_info(address, present);
115 self
116 }
117
118 pub fn state_storage(
120 mut self,
121 address: Address,
122 storage: HashMap<StorageKey, (StorageValue, StorageValue)>,
123 ) -> Self {
124 self.set_state_storage(address, storage);
125 self
126 }
127
128 pub fn revert_address(mut self, block_number: u64, address: Address) -> Self {
133 self.set_revert_address(block_number, address);
134 self
135 }
136
137 pub fn revert_account_info(
142 mut self,
143 block_number: u64,
144 address: Address,
145 account: Option<Option<AccountInfo>>,
146 ) -> Self {
147 self.set_revert_account_info(block_number, address, account);
148 self
149 }
150
151 pub fn revert_storage(
156 mut self,
157 block_number: u64,
158 address: Address,
159 storage: Vec<(StorageKey, StorageValue)>,
160 ) -> Self {
161 self.set_revert_storage(block_number, address, storage);
162 self
163 }
164
165 pub fn contract(mut self, address: B256, bytecode: Bytecode) -> Self {
167 self.set_contract(address, bytecode);
168 self
169 }
170
171 pub fn set_state_address(&mut self, address: Address) -> &mut Self {
173 self.states.insert(address);
174 self
175 }
176
177 pub fn set_state_original_account_info(
179 &mut self,
180 address: Address,
181 original: AccountInfo,
182 ) -> &mut Self {
183 self.states.insert(address);
184 self.state_original.insert(address, original);
185 self
186 }
187
188 pub fn set_state_present_account_info(
190 &mut self,
191 address: Address,
192 present: AccountInfo,
193 ) -> &mut Self {
194 self.states.insert(address);
195 self.state_present.insert(address, present);
196 self
197 }
198
199 pub fn set_state_storage(
201 &mut self,
202 address: Address,
203 storage: HashMap<StorageKey, (StorageValue, StorageValue)>,
204 ) -> &mut Self {
205 self.states.insert(address);
206 self.state_storage.insert(address, storage);
207 self
208 }
209
210 pub fn set_revert_address(&mut self, block_number: u64, address: Address) -> &mut Self {
212 self.reverts.insert((block_number, address));
213 self
214 }
215
216 pub fn set_revert_account_info(
218 &mut self,
219 block_number: u64,
220 address: Address,
221 account: Option<Option<AccountInfo>>,
222 ) -> &mut Self {
223 self.reverts.insert((block_number, address));
224 self.revert_account.insert((block_number, address), account);
225 self
226 }
227
228 pub fn set_revert_storage(
230 &mut self,
231 block_number: u64,
232 address: Address,
233 storage: Vec<(StorageKey, StorageValue)>,
234 ) -> &mut Self {
235 self.reverts.insert((block_number, address));
236 self.revert_storage.insert((block_number, address), storage);
237 self
238 }
239
240 pub fn set_contract(&mut self, address: B256, bytecode: Bytecode) -> &mut Self {
242 self.contracts.insert(address, bytecode);
243 self
244 }
245
246 pub fn build(mut self) -> BundleState {
248 let mut state_size = 0;
249 let state = self
250 .states
251 .into_iter()
252 .map(|address| {
253 let storage = self
254 .state_storage
255 .remove(&address)
256 .map(|s| {
257 s.into_iter()
258 .map(|(k, (o_val, p_val))| (k, StorageSlot::new_changed(o_val, p_val)))
259 .collect()
260 })
261 .unwrap_or_default();
262 let bundle_account = BundleAccount::new(
263 self.state_original.remove(&address),
264 self.state_present.remove(&address),
265 storage,
266 AccountStatus::Changed,
267 );
268 state_size += bundle_account.size_hint();
269 (address, bundle_account)
270 })
271 .collect();
272
273 let mut reverts_size = 0;
274 let mut reverts_map = BTreeMap::new();
275 for block_number in self.revert_range {
276 reverts_map.insert(block_number, Vec::new());
277 }
278 self.reverts
279 .into_iter()
280 .for_each(|(block_number, address)| {
281 let account = match self
282 .revert_account
283 .remove(&(block_number, address))
284 .unwrap_or_default()
285 {
286 Some(Some(account)) => AccountInfoRevert::RevertTo(account),
287 Some(None) => AccountInfoRevert::DeleteIt,
288 None => AccountInfoRevert::DoNothing,
289 };
290 let storage = self
291 .revert_storage
292 .remove(&(block_number, address))
293 .map(|s| {
294 s.into_iter()
295 .map(|(k, v)| (k, RevertToSlot::Some(v)))
296 .collect()
297 })
298 .unwrap_or_default();
299 let account_revert = AccountRevert {
300 account,
301 storage,
302 previous_status: AccountStatus::Changed,
303 wipe_storage: false,
304 };
305
306 if reverts_map.contains_key(&block_number) {
307 reverts_size += account_revert.size_hint();
308 reverts_map
309 .entry(block_number)
310 .or_insert(Vec::new())
311 .push((address, account_revert));
312 }
313 });
314
315 BundleState {
316 state,
317 contracts: self.contracts,
318 reverts: Reverts::new(reverts_map.into_values().collect()),
319 state_size,
320 reverts_size,
321 }
322 }
323
324 pub fn get_states(&self) -> &HashSet<Address> {
326 &self.states
327 }
328
329 pub fn get_states_mut(&mut self) -> &mut HashSet<Address> {
331 &mut self.states
332 }
333
334 pub fn get_state_original_mut(&mut self) -> &mut HashMap<Address, AccountInfo> {
336 &mut self.state_original
337 }
338
339 pub fn get_state_present_mut(&mut self) -> &mut HashMap<Address, AccountInfo> {
341 &mut self.state_present
342 }
343
344 pub fn get_state_storage_mut(
346 &mut self,
347 ) -> &mut HashMap<Address, HashMap<StorageKey, (StorageValue, StorageValue)>> {
348 &mut self.state_storage
349 }
350
351 pub fn get_reverts_mut(&mut self) -> &mut BTreeSet<(u64, Address)> {
353 &mut self.reverts
354 }
355
356 pub fn get_revert_range_mut(&mut self) -> &mut RangeInclusive<u64> {
358 &mut self.revert_range
359 }
360
361 pub fn get_revert_account_mut(
363 &mut self,
364 ) -> &mut HashMap<(u64, Address), Option<Option<AccountInfo>>> {
365 &mut self.revert_account
366 }
367
368 pub fn get_revert_storage_mut(
370 &mut self,
371 ) -> &mut HashMap<(u64, Address), Vec<(StorageKey, StorageValue)>> {
372 &mut self.revert_storage
373 }
374
375 pub fn get_contracts_mut(&mut self) -> &mut HashMap<B256, Bytecode> {
377 &mut self.contracts
378 }
379}
380
381#[derive(Debug)]
383pub enum BundleRetention {
384 PlainState,
386 Reverts,
388}
389
390impl BundleRetention {
391 pub fn includes_reverts(&self) -> bool {
393 matches!(self, Self::Reverts)
394 }
395}
396
397#[derive(Default, Clone, Debug, PartialEq, Eq)]
407#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
408pub struct BundleState {
409 pub state: HashMap<Address, BundleAccount>,
411 pub contracts: HashMap<B256, Bytecode>,
413 pub reverts: Reverts,
419 pub state_size: usize,
421 pub reverts_size: usize,
423}
424
425impl BundleState {
426 pub fn builder(revert_range: RangeInclusive<u64>) -> BundleBuilder {
428 BundleBuilder::new(revert_range)
429 }
430
431 pub fn new(
433 state: impl IntoIterator<
434 Item = (
435 Address,
436 Option<AccountInfo>,
437 Option<AccountInfo>,
438 HashMap<StorageKey, (StorageValue, StorageValue)>,
439 ),
440 >,
441 reverts: impl IntoIterator<
442 Item = impl IntoIterator<
443 Item = (
444 Address,
445 Option<Option<AccountInfo>>,
446 impl IntoIterator<Item = (StorageKey, StorageValue)>,
447 ),
448 >,
449 >,
450 contracts: impl IntoIterator<Item = (B256, Bytecode)>,
451 ) -> Self {
452 let mut state_size = 0;
454 let state = state
455 .into_iter()
456 .map(|(address, original, present, storage)| {
457 let account = BundleAccount::new(
458 original,
459 present,
460 storage
461 .into_iter()
462 .map(|(k, (o_val, p_val))| (k, StorageSlot::new_changed(o_val, p_val)))
463 .collect(),
464 AccountStatus::Changed,
465 );
466 state_size += account.size_hint();
467 (address, account)
468 })
469 .collect();
470
471 let mut reverts_size = 0;
473 let reverts = reverts
474 .into_iter()
475 .map(|block_reverts| {
476 block_reverts
477 .into_iter()
478 .map(|(address, account, storage)| {
479 let account = match account {
480 Some(Some(account)) => AccountInfoRevert::RevertTo(account),
481 Some(None) => AccountInfoRevert::DeleteIt,
482 None => AccountInfoRevert::DoNothing,
483 };
484 let revert = AccountRevert {
485 account,
486 storage: storage
487 .into_iter()
488 .map(|(k, v)| (k, RevertToSlot::Some(v)))
489 .collect(),
490 previous_status: AccountStatus::Changed,
491 wipe_storage: false,
492 };
493 reverts_size += revert.size_hint();
494 (address, revert)
495 })
496 .collect::<Vec<_>>()
497 })
498 .collect::<Vec<_>>();
499
500 Self {
501 state,
502 contracts: contracts.into_iter().collect(),
503 reverts: Reverts::new(reverts),
504 state_size,
505 reverts_size,
506 }
507 }
508
509 pub fn size_hint(&self) -> usize {
514 self.state_size + self.reverts_size + self.contracts.len()
515 }
516
517 pub fn state(&self) -> &HashMap<Address, BundleAccount> {
519 &self.state
520 }
521
522 pub fn is_empty(&self) -> bool {
524 self.len() == 0
525 }
526
527 pub fn len(&self) -> usize {
529 self.state.len()
530 }
531
532 pub fn account(&self, address: &Address) -> Option<&BundleAccount> {
534 self.state.get(address)
535 }
536
537 pub fn bytecode(&self, hash: &B256) -> Option<Bytecode> {
539 self.contracts.get(hash).cloned()
540 }
541
542 pub fn apply_transitions_and_create_reverts(
548 &mut self,
549 transitions: TransitionState,
550 retention: BundleRetention,
551 ) {
552 let include_reverts = retention.includes_reverts();
553 let reverts_capacity = if include_reverts {
555 transitions.transitions.len()
556 } else {
557 0
558 };
559 let mut reverts = Vec::with_capacity(reverts_capacity);
560
561 for (address, transition) in transitions.transitions.into_iter() {
562 if let Some((hash, new_bytecode)) = transition.has_new_contract() {
564 self.contracts.insert(hash, new_bytecode.clone());
565 }
566 let revert = match self.state.entry(address) {
568 Entry::Occupied(mut entry) => {
569 let entry = entry.get_mut();
570 self.state_size -= entry.size_hint();
571 let revert = entry.update_and_create_revert(transition);
573 self.state_size += entry.size_hint();
575 revert
576 }
577 Entry::Vacant(entry) => {
578 let present_bundle = transition.present_bundle_account();
580 let revert = transition.create_revert();
581 if revert.is_some() {
582 self.state_size += present_bundle.size_hint();
583 entry.insert(present_bundle);
584 }
585 revert
586 }
587 };
588
589 if let Some(revert) = revert.filter(|_| include_reverts) {
591 self.reverts_size += revert.size_hint();
592 reverts.push((address, revert));
593 }
594 }
595
596 self.reverts.push(reverts);
597 }
598
599 pub fn to_plain_state(&self, is_value_known: OriginalValuesKnown) -> StateChangeset {
602 let state_len = self.state.len();
604 let mut accounts = Vec::with_capacity(state_len);
605 let mut storage = Vec::with_capacity(state_len);
606
607 for (address, account) in &self.state {
608 let was_destroyed = account.was_destroyed();
610 if is_value_known.is_not_known() || account.is_info_changed() {
611 let info = account.info.as_ref().map(AccountInfo::copy_without_code);
612 accounts.push((*address, info));
613 }
614
615 let mut account_storage_changed = Vec::with_capacity(account.storage.len());
620
621 for (key, slot) in account.storage.iter().map(|(k, v)| (*k, *v)) {
622 let destroyed_and_not_zero = was_destroyed && !slot.present_value.is_zero();
625
626 let not_destroyed_and_changed = !was_destroyed && slot.is_changed();
629
630 if is_value_known.is_not_known()
631 || destroyed_and_not_zero
632 || not_destroyed_and_changed
633 {
634 account_storage_changed.push((key, slot.present_value));
635 }
636 }
637
638 if !account_storage_changed.is_empty() || was_destroyed {
639 storage.push(PlainStorageChangeset {
641 address: *address,
642 wipe_storage: was_destroyed,
643 storage: account_storage_changed,
644 });
645 }
646 }
647
648 let contracts = self
649 .contracts
650 .iter()
651 .filter(|(b, _)| **b != KECCAK_EMPTY)
653 .map(|(b, code)| (*b, code.clone()))
654 .collect::<Vec<_>>();
655 StateChangeset {
656 accounts,
657 storage,
658 contracts,
659 }
660 }
661
662 #[deprecated = "Use `to_plain_state` instead"]
664 pub fn into_plain_state(self, is_value_known: OriginalValuesKnown) -> StateChangeset {
665 self.to_plain_state(is_value_known)
666 }
667
668 pub fn to_plain_state_and_reverts(
671 &self,
672 is_value_known: OriginalValuesKnown,
673 ) -> (StateChangeset, PlainStateReverts) {
674 (
675 self.to_plain_state(is_value_known),
676 self.reverts.to_plain_state_reverts(),
677 )
678 }
679
680 #[deprecated = "Use `to_plain_state_and_reverts` instead"]
683 pub fn into_plain_state_and_reverts(
684 self,
685 is_value_known: OriginalValuesKnown,
686 ) -> (StateChangeset, PlainStateReverts) {
687 self.to_plain_state_and_reverts(is_value_known)
688 }
689
690 pub fn extend_state(&mut self, other_state: HashMap<Address, BundleAccount>) {
694 for (address, other_account) in other_state {
695 match self.state.entry(address) {
696 Entry::Occupied(mut entry) => {
697 let this = entry.get_mut();
698 self.state_size -= this.size_hint();
699
700 if other_account.was_destroyed() {
703 this.storage = other_account.storage;
704 } else {
705 for (key, storage_slot) in other_account.storage {
707 this.storage
709 .entry(key)
710 .or_insert(storage_slot)
711 .present_value = storage_slot.present_value;
712 }
713 }
714 this.info = other_account.info;
715 this.status.transition(other_account.status);
716
717 self.state_size += this.size_hint();
719 }
720 Entry::Vacant(entry) => {
721 self.state_size += other_account.size_hint();
723 entry.insert(other_account);
724 }
725 }
726 }
727 }
728 pub fn extend(&mut self, mut other: Self) {
739 for (address, revert) in other.reverts.iter_mut().flatten() {
742 if revert.wipe_storage {
743 if let Some(this_account) = self.state.get_mut(address) {
746 for (key, value) in this_account.storage.drain() {
749 revert
750 .storage
751 .entry(key)
752 .or_insert(RevertToSlot::Some(value.present_value));
753 }
754
755 if this_account.was_destroyed() {
757 revert.wipe_storage = false;
758 }
759 }
760 }
761
762 self.reverts_size += revert.size_hint();
764 }
765 self.extend_state(other.state);
767 self.contracts.extend(other.contracts);
769 self.reverts.extend(other.reverts);
771 }
772
773 pub fn take_n_reverts(&mut self, reverts_to_take: usize) -> Reverts {
775 if reverts_to_take > self.reverts.len() {
777 return self.take_all_reverts();
778 }
779 let (detach, this) = self.reverts.split_at(reverts_to_take);
780 let detached_reverts = Reverts::new(detach.to_vec());
781 self.reverts_size = this
782 .iter()
783 .flatten()
784 .fold(0, |acc, (_, revert)| acc + revert.size_hint());
785 self.reverts = Reverts::new(this.to_vec());
786 detached_reverts
787 }
788
789 pub fn take_all_reverts(&mut self) -> Reverts {
791 self.reverts_size = 0;
792 mem::take(&mut self.reverts)
793 }
794
795 pub fn revert_latest(&mut self) -> bool {
801 if let Some(reverts) = self.reverts.pop() {
803 for (address, revert_account) in reverts.into_iter() {
804 self.reverts_size -= revert_account.size_hint();
805 match self.state.entry(address) {
806 Entry::Occupied(mut entry) => {
807 let account = entry.get_mut();
808 self.state_size -= account.size_hint();
809 if account.revert(revert_account) {
810 entry.remove();
811 } else {
812 self.state_size += account.size_hint();
813 }
814 }
815 Entry::Vacant(entry) => {
816 let mut account = BundleAccount::new(
819 None,
820 None,
821 HashMap::default(),
822 AccountStatus::LoadedNotExisting,
823 );
824 if !account.revert(revert_account) {
825 self.state_size += account.size_hint();
826 entry.insert(account);
827 }
828 }
829 }
830 }
831 return true;
832 }
833
834 false
835 }
836
837 pub fn revert(&mut self, mut num_transitions: usize) {
841 if num_transitions == 0 {
842 return;
843 }
844
845 while self.revert_latest() {
846 num_transitions -= 1;
847 if num_transitions == 0 {
848 break;
850 }
851 }
852 }
853
854 pub fn prepend_state(&mut self, mut other: BundleState) {
860 let this_bundle = mem::take(self);
862 other.extend_state(this_bundle.state);
864 other.contracts.extend(this_bundle.contracts);
866 mem::swap(self, &mut other)
868 }
869}
870
871#[cfg(test)]
872mod tests {
873 use super::*;
874 use crate::{StorageWithOriginalValues, TransitionAccount};
875 use primitives::U256;
876
877 #[test]
878 fn transition_states() {
879 let address = Address::new([0x01; 20]);
881 let acc1 = AccountInfo {
882 balance: U256::from(10),
883 nonce: 1,
884 code_hash: KECCAK_EMPTY,
885 code: None,
886 };
887
888 let mut bundle_state = BundleState::default();
889
890 let transition = TransitionAccount {
893 info: Some(acc1),
894 status: AccountStatus::InMemoryChange,
895 previous_info: None,
896 previous_status: AccountStatus::LoadedNotExisting,
897 storage: StorageWithOriginalValues::default(),
898 storage_was_destroyed: false,
899 };
900
901 bundle_state.apply_transitions_and_create_reverts(
903 TransitionState::single(address, transition.clone()),
904 BundleRetention::Reverts,
905 );
906 }
907
908 const fn account1() -> Address {
909 Address::new([0x60; 20])
910 }
911
912 const fn account2() -> Address {
913 Address::new([0x61; 20])
914 }
915
916 fn slot1() -> StorageKey {
917 StorageKey::from(5)
918 }
919
920 fn slot2() -> StorageKey {
921 StorageKey::from(7)
922 }
923
924 fn test_bundle1() -> BundleState {
926 BundleState::new(
928 vec![
929 (
930 account1(),
931 None,
932 Some(AccountInfo {
933 nonce: 1,
934 balance: U256::from(10),
935 code_hash: KECCAK_EMPTY,
936 code: None,
937 }),
938 HashMap::from_iter([
939 (slot1(), (StorageValue::from(0), StorageValue::from(10))),
940 (slot2(), (StorageValue::from(0), StorageValue::from(15))),
941 ]),
942 ),
943 (
944 account2(),
945 None,
946 Some(AccountInfo {
947 nonce: 1,
948 balance: U256::from(10),
949 code_hash: KECCAK_EMPTY,
950 code: None,
951 }),
952 HashMap::default(),
953 ),
954 ],
955 vec![vec![
956 (
957 account1(),
958 Some(None),
959 vec![
960 (slot1(), StorageValue::from(0)),
961 (slot2(), StorageValue::from(0)),
962 ],
963 ),
964 (account2(), Some(None), vec![]),
965 ]],
966 vec![],
967 )
968 }
969
970 fn test_bundle2() -> BundleState {
972 BundleState::new(
974 vec![(
975 account1(),
976 None,
977 Some(AccountInfo {
978 nonce: 3,
979 balance: U256::from(20),
980 code_hash: KECCAK_EMPTY,
981 code: None,
982 }),
983 HashMap::from_iter([(slot1(), (StorageValue::from(0), StorageValue::from(15)))]),
984 )],
985 vec![vec![(
986 account1(),
987 Some(Some(AccountInfo {
988 nonce: 1,
989 balance: U256::from(10),
990 code_hash: KECCAK_EMPTY,
991 code: None,
992 })),
993 vec![(slot1(), StorageValue::from(10))],
994 )]],
995 vec![],
996 )
997 }
998
999 fn test_bundle3() -> BundleState {
1001 BundleState::builder(0..=0)
1002 .state_present_account_info(
1003 account1(),
1004 AccountInfo {
1005 nonce: 1,
1006 balance: U256::from(10),
1007 code_hash: KECCAK_EMPTY,
1008 code: None,
1009 },
1010 )
1011 .state_storage(
1012 account1(),
1013 HashMap::from_iter([(slot1(), (StorageValue::from(0), StorageValue::from(10)))]),
1014 )
1015 .state_address(account2())
1016 .state_present_account_info(
1017 account2(),
1018 AccountInfo {
1019 nonce: 1,
1020 balance: U256::from(10),
1021 code_hash: KECCAK_EMPTY,
1022 code: None,
1023 },
1024 )
1025 .revert_address(0, account1())
1026 .revert_account_info(0, account1(), Some(None))
1027 .revert_storage(0, account1(), vec![(slot1(), StorageValue::from(0))])
1028 .revert_account_info(0, account2(), Some(None))
1029 .build()
1030 }
1031
1032 fn test_bundle4() -> BundleState {
1034 BundleState::builder(0..=0)
1035 .state_present_account_info(
1036 account1(),
1037 AccountInfo {
1038 nonce: 3,
1039 balance: U256::from(20),
1040 code_hash: KECCAK_EMPTY,
1041 code: None,
1042 },
1043 )
1044 .state_storage(
1045 account1(),
1046 HashMap::from_iter([(slot1(), (StorageValue::from(0), StorageValue::from(15)))]),
1047 )
1048 .revert_address(0, account1())
1049 .revert_account_info(
1050 0,
1051 account1(),
1052 Some(Some(AccountInfo {
1053 nonce: 1,
1054 balance: U256::from(10),
1055 code_hash: KECCAK_EMPTY,
1056 code: None,
1057 })),
1058 )
1059 .revert_storage(0, account1(), vec![(slot1(), StorageValue::from(10))])
1060 .build()
1061 }
1062
1063 fn sanity_path(bundle1: BundleState, bundle2: BundleState) {
1064 let mut extended = bundle1.clone();
1065 extended.extend(bundle2.clone());
1066
1067 let mut reverted = extended.clone();
1068 reverted.revert(0);
1070 assert_eq!(reverted, extended);
1071
1072 reverted.revert(1);
1074 assert_eq!(reverted, bundle1);
1075
1076 reverted.revert(1);
1078 assert_eq!(reverted, BundleState::default());
1079
1080 let mut reverted = extended.clone();
1081
1082 reverted.revert(10);
1084 assert_eq!(reverted, BundleState::default());
1085 }
1086
1087 #[test]
1088 fn extend_on_destroyed_values() {
1089 let base_bundle1 = test_bundle1();
1090 let base_bundle2 = test_bundle2();
1091
1092 let mut b1 = base_bundle1.clone();
1097 let mut b2 = base_bundle2.clone();
1098 b1.state.get_mut(&account1()).unwrap().status = AccountStatus::Destroyed;
1099 b2.state.get_mut(&account1()).unwrap().status = AccountStatus::Changed;
1100 b1.extend(b2);
1101 assert_eq!(
1102 b1.state.get_mut(&account1()).unwrap().status,
1103 AccountStatus::DestroyedChanged
1104 );
1105
1106 let mut b1 = base_bundle1.clone();
1111 let mut b2 = base_bundle2.clone();
1112 b1.state.get_mut(&account1()).unwrap().status = AccountStatus::Changed;
1113 b2.state.get_mut(&account1()).unwrap().status = AccountStatus::Destroyed;
1114 b2.reverts[0][0].1.wipe_storage = true;
1115 b1.extend(b2);
1116 assert_eq!(
1117 b1.state.get_mut(&account1()).unwrap().status,
1118 AccountStatus::Destroyed
1119 );
1120
1121 let mut revert1 = base_bundle2.reverts[0][0].clone();
1124 revert1.1.wipe_storage = true;
1125 revert1
1126 .1
1127 .storage
1128 .insert(slot2(), RevertToSlot::Some(StorageValue::from(15)));
1129
1130 assert_eq!(
1131 b1.reverts.as_ref(),
1132 vec![base_bundle1.reverts[0].clone(), vec![revert1]],
1133 );
1134
1135 let mut b1 = base_bundle1.clone();
1141 let mut b2 = base_bundle2.clone();
1142 b1.state.get_mut(&account1()).unwrap().status = AccountStatus::InMemoryChange;
1143 b2.state.get_mut(&account1()).unwrap().status = AccountStatus::Changed;
1144 b1.extend(b2);
1145 assert_eq!(
1146 b1.state.get_mut(&account1()).unwrap().status,
1147 AccountStatus::InMemoryChange
1148 );
1149 }
1150
1151 #[test]
1152 fn test_sanity_path() {
1153 sanity_path(test_bundle1(), test_bundle2());
1154 sanity_path(test_bundle3(), test_bundle4());
1155 }
1156
1157 #[test]
1158 fn test_multi_reverts_with_delete() {
1159 let mut state = BundleBuilder::new(0..=3)
1160 .revert_address(0, account1())
1161 .revert_account_info(2, account1(), Some(Some(AccountInfo::default())))
1162 .revert_account_info(3, account1(), Some(None))
1163 .build();
1164
1165 state.revert_latest();
1166 assert_eq!(state.state.get(&account1()), None);
1168
1169 state.revert_latest();
1170 assert_eq!(
1172 state.state.get(&account1()),
1173 Some(&BundleAccount::new(
1174 None,
1175 Some(AccountInfo::default()),
1176 HashMap::default(),
1177 AccountStatus::Changed
1178 ))
1179 );
1180 }
1181
1182 #[test]
1183 fn test_revert_capacity() {
1184 let state = BundleState::builder(0..=3)
1185 .revert_address(0, account1())
1186 .revert_address(2, account2())
1187 .revert_account_info(0, account1(), Some(None))
1188 .revert_account_info(2, account2(), None)
1189 .revert_storage(0, account1(), vec![(slot1(), StorageValue::from(10))])
1190 .build();
1191
1192 assert_eq!(state.reverts.len(), 4);
1193 assert_eq!(state.reverts[1], vec![]);
1194 assert_eq!(state.reverts[3], vec![]);
1195 assert_eq!(state.reverts[0].len(), 1);
1196 assert_eq!(state.reverts[2].len(), 1);
1197
1198 let (addr1, revert1) = &state.reverts[0][0];
1199 assert_eq!(addr1, &account1());
1200 assert_eq!(revert1.account, AccountInfoRevert::DeleteIt);
1201
1202 let (addr2, revert2) = &state.reverts[2][0];
1203 assert_eq!(addr2, &account2());
1204 assert_eq!(revert2.account, AccountInfoRevert::DoNothing);
1205 }
1206
1207 #[test]
1208 fn take_reverts() {
1209 let bundle1 = test_bundle1();
1210 let bundle2 = test_bundle2();
1211
1212 let mut extended = bundle1.clone();
1213 extended.extend(bundle2.clone());
1214
1215 assert_eq!(extended.reverts.len(), 2);
1217
1218 let mut extended2 = extended.clone();
1220 assert_eq!(extended2.take_n_reverts(100), extended.reverts);
1221
1222 let mut extended2 = extended.clone();
1224 assert_eq!(extended2.take_all_reverts(), extended.reverts);
1225
1226 let taken_reverts = extended.take_n_reverts(0);
1228 assert_eq!(taken_reverts, Reverts::default());
1229 assert_eq!(extended.reverts.len(), 2);
1230
1231 let taken_reverts = extended.take_n_reverts(1);
1233 assert_eq!(taken_reverts, bundle1.reverts);
1234
1235 let taken_reverts = extended.take_n_reverts(1);
1237 assert_eq!(taken_reverts, bundle2.reverts);
1238 }
1239
1240 #[test]
1241 fn prepend_state() {
1242 let address1 = account1();
1243 let address2 = account2();
1244
1245 let account1 = AccountInfo {
1246 nonce: 1,
1247 ..Default::default()
1248 };
1249 let account1_changed = AccountInfo {
1250 nonce: 1,
1251 ..Default::default()
1252 };
1253 let account2 = AccountInfo {
1254 nonce: 1,
1255 ..Default::default()
1256 };
1257
1258 let present_state = BundleState::builder(2..=2)
1259 .state_present_account_info(address1, account1_changed.clone())
1260 .build();
1261 assert_eq!(present_state.reverts.len(), 1);
1262 let previous_state = BundleState::builder(1..=1)
1263 .state_present_account_info(address1, account1)
1264 .state_present_account_info(address2, account2.clone())
1265 .build();
1266 assert_eq!(previous_state.reverts.len(), 1);
1267
1268 let mut test = present_state;
1269
1270 test.prepend_state(previous_state);
1271
1272 assert_eq!(test.state.len(), 2);
1273 assert_eq!(test.reverts.len(), 1);
1275 assert_eq!(
1277 test.state.get(&address1).unwrap().info,
1278 Some(account1_changed)
1279 );
1280 assert_eq!(test.state.get(&address2).unwrap().info, Some(account2));
1282 }
1283
1284 #[test]
1285 fn test_getters() {
1286 let mut builder = BundleBuilder::new(0..=3);
1287
1288 assert!(builder.get_states().is_empty());
1290 builder.get_states_mut().insert(account1());
1291 assert!(builder.get_states().contains(&account1()));
1292
1293 assert!(builder.get_state_original_mut().is_empty());
1295 builder
1296 .get_state_original_mut()
1297 .insert(account1(), AccountInfo::default());
1298 assert!(builder.get_state_original_mut().contains_key(&account1()));
1299
1300 assert!(builder.get_state_present_mut().is_empty());
1302 builder
1303 .get_state_present_mut()
1304 .insert(account1(), AccountInfo::default());
1305 assert!(builder.get_state_present_mut().contains_key(&account1()));
1306
1307 assert!(builder.get_state_storage_mut().is_empty());
1309 builder
1310 .get_state_storage_mut()
1311 .insert(account1(), HashMap::default());
1312 assert!(builder.get_state_storage_mut().contains_key(&account1()));
1313
1314 assert!(builder.get_reverts_mut().is_empty());
1316 builder.get_reverts_mut().insert((0, account1()));
1317 assert!(builder.get_reverts_mut().contains(&(0, account1())));
1318
1319 assert_eq!(builder.get_revert_range_mut().clone(), 0..=3);
1321
1322 assert!(builder.get_revert_account_mut().is_empty());
1324 builder
1325 .get_revert_account_mut()
1326 .insert((0, account1()), Some(None));
1327 assert!(builder
1328 .get_revert_account_mut()
1329 .contains_key(&(0, account1())));
1330
1331 assert!(builder.get_revert_storage_mut().is_empty());
1333 builder
1334 .get_revert_storage_mut()
1335 .insert((0, account1()), vec![(slot1(), StorageValue::from(0))]);
1336 assert!(builder
1337 .get_revert_storage_mut()
1338 .contains_key(&(0, account1())));
1339
1340 assert!(builder.get_contracts_mut().is_empty());
1342 builder
1343 .get_contracts_mut()
1344 .insert(B256::default(), Bytecode::default());
1345 assert!(builder.get_contracts_mut().contains_key(&B256::default()));
1346 }
1347}