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::{self, Entry},
11 Address, HashMap, HashSet, B256, KECCAK_EMPTY, U256,
12};
13use state::AccountInfo;
14use std::{
15 collections::{BTreeMap, BTreeSet},
16 vec::Vec,
17};
18
19#[derive(Debug)]
21pub struct BundleBuilder {
22 states: HashSet<Address>,
23 state_original: HashMap<Address, AccountInfo>,
24 state_present: HashMap<Address, AccountInfo>,
25 state_storage: HashMap<Address, HashMap<U256, (U256, U256)>>,
26
27 reverts: BTreeSet<(u64, Address)>,
28 revert_range: RangeInclusive<u64>,
29 revert_account: HashMap<(u64, Address), Option<Option<AccountInfo>>>,
30 revert_storage: HashMap<(u64, Address), Vec<(U256, U256)>>,
31
32 contracts: HashMap<B256, Bytecode>,
33}
34
35#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
37pub enum OriginalValuesKnown {
38 Yes,
43 No,
49}
50impl OriginalValuesKnown {
51 pub fn is_not_known(&self) -> bool {
53 matches!(self, Self::No)
54 }
55}
56
57impl Default for BundleBuilder {
58 fn default() -> Self {
59 BundleBuilder {
60 states: HashSet::default(),
61 state_original: HashMap::default(),
62 state_present: HashMap::default(),
63 state_storage: HashMap::default(),
64 reverts: BTreeSet::new(),
65 revert_range: 0..=0,
66 revert_account: HashMap::default(),
67 revert_storage: HashMap::default(),
68 contracts: HashMap::default(),
69 }
70 }
71}
72
73impl BundleBuilder {
74 pub fn new(revert_range: RangeInclusive<u64>) -> Self {
78 BundleBuilder {
79 revert_range,
80 ..Default::default()
81 }
82 }
83
84 pub fn apply<F>(self, f: F) -> Self
86 where
87 F: FnOnce(Self) -> Self,
88 {
89 f(self)
90 }
91
92 pub fn apply_mut<F>(&mut self, f: F) -> &mut Self
94 where
95 F: FnOnce(&mut Self),
96 {
97 f(self);
98 self
99 }
100
101 pub fn state_address(mut self, address: Address) -> Self {
103 self.set_state_address(address);
104 self
105 }
106
107 pub fn state_original_account_info(mut self, address: Address, original: AccountInfo) -> Self {
109 self.set_state_original_account_info(address, original);
110 self
111 }
112
113 pub fn state_present_account_info(mut self, address: Address, present: AccountInfo) -> Self {
115 self.set_state_present_account_info(address, present);
116 self
117 }
118
119 pub fn state_storage(mut self, address: Address, storage: HashMap<U256, (U256, U256)>) -> Self {
121 self.set_state_storage(address, storage);
122 self
123 }
124
125 pub fn revert_address(mut self, block_number: u64, address: Address) -> Self {
130 self.set_revert_address(block_number, address);
131 self
132 }
133
134 pub fn revert_account_info(
139 mut self,
140 block_number: u64,
141 address: Address,
142 account: Option<Option<AccountInfo>>,
143 ) -> Self {
144 self.set_revert_account_info(block_number, address, account);
145 self
146 }
147
148 pub fn revert_storage(
153 mut self,
154 block_number: u64,
155 address: Address,
156 storage: Vec<(U256, U256)>,
157 ) -> Self {
158 self.set_revert_storage(block_number, address, storage);
159 self
160 }
161
162 pub fn contract(mut self, address: B256, bytecode: Bytecode) -> Self {
164 self.set_contract(address, bytecode);
165 self
166 }
167
168 pub fn set_state_address(&mut self, address: Address) -> &mut Self {
170 self.states.insert(address);
171 self
172 }
173
174 pub fn set_state_original_account_info(
176 &mut self,
177 address: Address,
178 original: AccountInfo,
179 ) -> &mut Self {
180 self.states.insert(address);
181 self.state_original.insert(address, original);
182 self
183 }
184
185 pub fn set_state_present_account_info(
187 &mut self,
188 address: Address,
189 present: AccountInfo,
190 ) -> &mut Self {
191 self.states.insert(address);
192 self.state_present.insert(address, present);
193 self
194 }
195
196 pub fn set_state_storage(
198 &mut self,
199 address: Address,
200 storage: HashMap<U256, (U256, U256)>,
201 ) -> &mut Self {
202 self.states.insert(address);
203 self.state_storage.insert(address, storage);
204 self
205 }
206
207 pub fn set_revert_address(&mut self, block_number: u64, address: Address) -> &mut Self {
209 self.reverts.insert((block_number, address));
210 self
211 }
212
213 pub fn set_revert_account_info(
215 &mut self,
216 block_number: u64,
217 address: Address,
218 account: Option<Option<AccountInfo>>,
219 ) -> &mut Self {
220 self.reverts.insert((block_number, address));
221 self.revert_account.insert((block_number, address), account);
222 self
223 }
224
225 pub fn set_revert_storage(
227 &mut self,
228 block_number: u64,
229 address: Address,
230 storage: Vec<(U256, U256)>,
231 ) -> &mut Self {
232 self.reverts.insert((block_number, address));
233 self.revert_storage.insert((block_number, address), storage);
234 self
235 }
236
237 pub fn set_contract(&mut self, address: B256, bytecode: Bytecode) -> &mut Self {
239 self.contracts.insert(address, bytecode);
240 self
241 }
242
243 pub fn build(mut self) -> BundleState {
245 let mut state_size = 0;
246 let state = self
247 .states
248 .into_iter()
249 .map(|address| {
250 let storage = self
251 .state_storage
252 .remove(&address)
253 .map(|s| {
254 s.into_iter()
255 .map(|(k, (o_val, p_val))| (k, StorageSlot::new_changed(o_val, p_val)))
256 .collect()
257 })
258 .unwrap_or_default();
259 let bundle_account = BundleAccount::new(
260 self.state_original.remove(&address),
261 self.state_present.remove(&address),
262 storage,
263 AccountStatus::Changed,
264 );
265 state_size += bundle_account.size_hint();
266 (address, bundle_account)
267 })
268 .collect();
269
270 let mut reverts_size = 0;
271 let mut reverts_map = BTreeMap::new();
272 for block_number in self.revert_range {
273 reverts_map.insert(block_number, Vec::new());
274 }
275 self.reverts
276 .into_iter()
277 .for_each(|(block_number, address)| {
278 let account = match self
279 .revert_account
280 .remove(&(block_number, address))
281 .unwrap_or_default()
282 {
283 Some(Some(account)) => AccountInfoRevert::RevertTo(account),
284 Some(None) => AccountInfoRevert::DeleteIt,
285 None => AccountInfoRevert::DoNothing,
286 };
287 let storage = self
288 .revert_storage
289 .remove(&(block_number, address))
290 .map(|s| {
291 s.into_iter()
292 .map(|(k, v)| (k, RevertToSlot::Some(v)))
293 .collect()
294 })
295 .unwrap_or_default();
296 let account_revert = AccountRevert {
297 account,
298 storage,
299 previous_status: AccountStatus::Changed,
300 wipe_storage: false,
301 };
302
303 if reverts_map.contains_key(&block_number) {
304 reverts_size += account_revert.size_hint();
305 reverts_map
306 .entry(block_number)
307 .or_insert(Vec::new())
308 .push((address, account_revert));
309 }
310 });
311
312 BundleState {
313 state,
314 contracts: self.contracts,
315 reverts: Reverts::new(reverts_map.into_values().collect()),
316 state_size,
317 reverts_size,
318 }
319 }
320
321 pub fn get_states(&self) -> &HashSet<Address> {
323 &self.states
324 }
325
326 pub fn get_states_mut(&mut self) -> &mut HashSet<Address> {
328 &mut self.states
329 }
330
331 pub fn get_state_original_mut(&mut self) -> &mut HashMap<Address, AccountInfo> {
333 &mut self.state_original
334 }
335
336 pub fn get_state_present_mut(&mut self) -> &mut HashMap<Address, AccountInfo> {
338 &mut self.state_present
339 }
340
341 pub fn get_state_storage_mut(&mut self) -> &mut HashMap<Address, HashMap<U256, (U256, U256)>> {
343 &mut self.state_storage
344 }
345
346 pub fn get_reverts_mut(&mut self) -> &mut BTreeSet<(u64, Address)> {
348 &mut self.reverts
349 }
350
351 pub fn get_revert_range_mut(&mut self) -> &mut RangeInclusive<u64> {
353 &mut self.revert_range
354 }
355
356 pub fn get_revert_account_mut(
358 &mut self,
359 ) -> &mut HashMap<(u64, Address), Option<Option<AccountInfo>>> {
360 &mut self.revert_account
361 }
362
363 pub fn get_revert_storage_mut(&mut self) -> &mut HashMap<(u64, Address), Vec<(U256, U256)>> {
365 &mut self.revert_storage
366 }
367
368 pub fn get_contracts_mut(&mut self) -> &mut HashMap<B256, Bytecode> {
370 &mut self.contracts
371 }
372}
373
374#[derive(Debug)]
376pub enum BundleRetention {
377 PlainState,
379 Reverts,
381}
382
383impl BundleRetention {
384 pub fn includes_reverts(&self) -> bool {
386 matches!(self, Self::Reverts)
387 }
388}
389
390#[derive(Default, Clone, Debug, PartialEq, Eq)]
400#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
401pub struct BundleState {
402 pub state: HashMap<Address, BundleAccount>,
404 pub contracts: HashMap<B256, Bytecode>,
406 pub reverts: Reverts,
412 pub state_size: usize,
414 pub reverts_size: usize,
416}
417
418impl BundleState {
419 pub fn builder(revert_range: RangeInclusive<u64>) -> BundleBuilder {
421 BundleBuilder::new(revert_range)
422 }
423
424 pub fn new(
426 state: impl IntoIterator<
427 Item = (
428 Address,
429 Option<AccountInfo>,
430 Option<AccountInfo>,
431 HashMap<U256, (U256, U256)>,
432 ),
433 >,
434 reverts: impl IntoIterator<
435 Item = impl IntoIterator<
436 Item = (
437 Address,
438 Option<Option<AccountInfo>>,
439 impl IntoIterator<Item = (U256, U256)>,
440 ),
441 >,
442 >,
443 contracts: impl IntoIterator<Item = (B256, Bytecode)>,
444 ) -> Self {
445 let mut state_size = 0;
447 let state = state
448 .into_iter()
449 .map(|(address, original, present, storage)| {
450 let account = BundleAccount::new(
451 original,
452 present,
453 storage
454 .into_iter()
455 .map(|(k, (o_val, p_val))| (k, StorageSlot::new_changed(o_val, p_val)))
456 .collect(),
457 AccountStatus::Changed,
458 );
459 state_size += account.size_hint();
460 (address, account)
461 })
462 .collect();
463
464 let mut reverts_size = 0;
466 let reverts = reverts
467 .into_iter()
468 .map(|block_reverts| {
469 block_reverts
470 .into_iter()
471 .map(|(address, account, storage)| {
472 let account = match account {
473 Some(Some(account)) => AccountInfoRevert::RevertTo(account),
474 Some(None) => AccountInfoRevert::DeleteIt,
475 None => AccountInfoRevert::DoNothing,
476 };
477 let revert = AccountRevert {
478 account,
479 storage: storage
480 .into_iter()
481 .map(|(k, v)| (k, RevertToSlot::Some(v)))
482 .collect(),
483 previous_status: AccountStatus::Changed,
484 wipe_storage: false,
485 };
486 reverts_size += revert.size_hint();
487 (address, revert)
488 })
489 .collect::<Vec<_>>()
490 })
491 .collect::<Vec<_>>();
492
493 Self {
494 state,
495 contracts: contracts.into_iter().collect(),
496 reverts: Reverts::new(reverts),
497 state_size,
498 reverts_size,
499 }
500 }
501
502 pub fn size_hint(&self) -> usize {
507 self.state_size + self.reverts_size + self.contracts.len()
508 }
509
510 pub fn state(&self) -> &HashMap<Address, BundleAccount> {
512 &self.state
513 }
514
515 pub fn is_empty(&self) -> bool {
517 self.len() == 0
518 }
519
520 pub fn len(&self) -> usize {
522 self.state.len()
523 }
524
525 pub fn account(&self, address: &Address) -> Option<&BundleAccount> {
527 self.state.get(address)
528 }
529
530 pub fn bytecode(&self, hash: &B256) -> Option<Bytecode> {
532 self.contracts.get(hash).cloned()
533 }
534
535 pub fn apply_transitions_and_create_reverts(
541 &mut self,
542 transitions: TransitionState,
543 retention: BundleRetention,
544 ) {
545 let include_reverts = retention.includes_reverts();
546 let reverts_capacity = if include_reverts {
548 transitions.transitions.len()
549 } else {
550 0
551 };
552 let mut reverts = Vec::with_capacity(reverts_capacity);
553
554 for (address, transition) in transitions.transitions.into_iter() {
555 if let Some((hash, new_bytecode)) = transition.has_new_contract() {
557 self.contracts.insert(hash, new_bytecode.clone());
558 }
559 let revert = match self.state.entry(address) {
561 hash_map::Entry::Occupied(mut entry) => {
562 let entry = entry.get_mut();
563 self.state_size -= entry.size_hint();
564 let revert = entry.update_and_create_revert(transition);
566 self.state_size += entry.size_hint();
568 revert
569 }
570 hash_map::Entry::Vacant(entry) => {
571 let present_bundle = transition.present_bundle_account();
573 let revert = transition.create_revert();
574 if revert.is_some() {
575 self.state_size += present_bundle.size_hint();
576 entry.insert(present_bundle);
577 }
578 revert
579 }
580 };
581
582 if let Some(revert) = revert.filter(|_| include_reverts) {
584 self.reverts_size += revert.size_hint();
585 reverts.push((address, revert));
586 }
587 }
588
589 self.reverts.push(reverts);
590 }
591
592 pub fn to_plain_state(&self, is_value_known: OriginalValuesKnown) -> StateChangeset {
595 let state_len = self.state.len();
597 let mut accounts = Vec::with_capacity(state_len);
598 let mut storage = Vec::with_capacity(state_len);
599
600 for (address, account) in self.state.iter() {
601 let was_destroyed = account.was_destroyed();
603 if is_value_known.is_not_known() || account.is_info_changed() {
604 let info = account.info.as_ref().map(AccountInfo::copy_without_code);
605 accounts.push((*address, info));
606 }
607
608 let mut account_storage_changed = Vec::with_capacity(account.storage.len());
613
614 for (key, slot) in account.storage.iter().map(|(k, v)| (*k, *v)) {
615 let destroyed_and_not_zero = was_destroyed && !slot.present_value.is_zero();
618
619 let not_destroyed_and_changed = !was_destroyed && slot.is_changed();
622
623 if is_value_known.is_not_known()
624 || destroyed_and_not_zero
625 || not_destroyed_and_changed
626 {
627 account_storage_changed.push((key, slot.present_value));
628 }
629 }
630
631 if !account_storage_changed.is_empty() || was_destroyed {
632 storage.push(PlainStorageChangeset {
634 address: *address,
635 wipe_storage: was_destroyed,
636 storage: account_storage_changed,
637 });
638 }
639 }
640
641 let contracts = self
642 .contracts
643 .iter()
644 .filter(|(b, _)| **b != KECCAK_EMPTY)
646 .map(|(b, code)| (*b, code.clone()))
647 .collect::<Vec<_>>();
648 StateChangeset {
649 accounts,
650 storage,
651 contracts,
652 }
653 }
654
655 #[deprecated = "Use `to_plain_state` instead"]
657 pub fn into_plain_state(self, is_value_known: OriginalValuesKnown) -> StateChangeset {
658 self.to_plain_state(is_value_known)
659 }
660
661 pub fn to_plain_state_and_reverts(
664 &self,
665 is_value_known: OriginalValuesKnown,
666 ) -> (StateChangeset, PlainStateReverts) {
667 (
668 self.to_plain_state(is_value_known),
669 self.reverts.to_plain_state_reverts(),
670 )
671 }
672
673 #[deprecated = "Use `to_plain_state_and_reverts` instead"]
676 pub fn into_plain_state_and_reverts(
677 self,
678 is_value_known: OriginalValuesKnown,
679 ) -> (StateChangeset, PlainStateReverts) {
680 self.to_plain_state_and_reverts(is_value_known)
681 }
682
683 pub fn extend_state(&mut self, other_state: HashMap<Address, BundleAccount>) {
687 for (address, other_account) in other_state {
688 match self.state.entry(address) {
689 hash_map::Entry::Occupied(mut entry) => {
690 let this = entry.get_mut();
691 self.state_size -= this.size_hint();
692
693 if other_account.was_destroyed() {
696 this.storage = other_account.storage;
697 } else {
698 for (key, storage_slot) in other_account.storage {
700 this.storage
702 .entry(key)
703 .or_insert(storage_slot)
704 .present_value = storage_slot.present_value;
705 }
706 }
707 this.info = other_account.info;
708 this.status.transition(other_account.status);
709
710 self.state_size += this.size_hint();
712 }
713 hash_map::Entry::Vacant(entry) => {
714 self.state_size += other_account.size_hint();
716 entry.insert(other_account);
717 }
718 }
719 }
720 }
721 pub fn extend(&mut self, mut other: Self) {
732 for (address, revert) in other.reverts.iter_mut().flatten() {
735 if revert.wipe_storage {
736 if let Some(this_account) = self.state.get_mut(address) {
739 for (key, value) in this_account.storage.drain() {
742 revert
743 .storage
744 .entry(key)
745 .or_insert(RevertToSlot::Some(value.present_value));
746 }
747
748 if this_account.was_destroyed() {
750 revert.wipe_storage = false;
751 }
752 }
753 }
754
755 self.reverts_size += revert.size_hint();
757 }
758 self.extend_state(other.state);
760 self.contracts.extend(other.contracts);
762 self.reverts.extend(other.reverts);
764 }
765
766 pub fn take_n_reverts(&mut self, reverts_to_take: usize) -> Reverts {
768 if reverts_to_take > self.reverts.len() {
770 return self.take_all_reverts();
771 }
772 let (detach, this) = self.reverts.split_at(reverts_to_take);
773 let detached_reverts = Reverts::new(detach.to_vec());
774 self.reverts_size = this
775 .iter()
776 .flatten()
777 .fold(0, |acc, (_, revert)| acc + revert.size_hint());
778 self.reverts = Reverts::new(this.to_vec());
779 detached_reverts
780 }
781
782 pub fn take_all_reverts(&mut self) -> Reverts {
784 self.reverts_size = 0;
785 core::mem::take(&mut self.reverts)
786 }
787
788 pub fn revert_latest(&mut self) -> bool {
794 if let Some(reverts) = self.reverts.pop() {
796 for (address, revert_account) in reverts.into_iter() {
797 self.reverts_size -= revert_account.size_hint();
798 match self.state.entry(address) {
799 Entry::Occupied(mut entry) => {
800 let account = entry.get_mut();
801 self.state_size -= account.size_hint();
802 if account.revert(revert_account) {
803 entry.remove();
804 } else {
805 self.state_size += account.size_hint();
806 }
807 }
808 Entry::Vacant(entry) => {
809 let mut account = BundleAccount::new(
812 None,
813 None,
814 HashMap::default(),
815 AccountStatus::LoadedNotExisting,
816 );
817 if !account.revert(revert_account) {
818 self.state_size += account.size_hint();
819 entry.insert(account);
820 }
821 }
822 }
823 }
824 return true;
825 }
826
827 false
828 }
829
830 pub fn revert(&mut self, mut num_transitions: usize) {
834 if num_transitions == 0 {
835 return;
836 }
837
838 while self.revert_latest() {
839 num_transitions -= 1;
840 if num_transitions == 0 {
841 break;
843 }
844 }
845 }
846
847 pub fn prepend_state(&mut self, mut other: BundleState) {
853 let this_bundle = mem::take(self);
855 other.extend_state(this_bundle.state);
857 other.contracts.extend(this_bundle.contracts);
859 mem::swap(self, &mut other)
861 }
862}
863
864#[cfg(test)]
865mod tests {
866 use super::*;
867 use crate::{StorageWithOriginalValues, TransitionAccount};
868
869 #[test]
870 fn transition_states() {
871 let address = Address::new([0x01; 20]);
873 let acc1 = AccountInfo {
874 balance: U256::from(10),
875 nonce: 1,
876 code_hash: KECCAK_EMPTY,
877 code: None,
878 };
879
880 let mut bundle_state = BundleState::default();
881
882 let transition = TransitionAccount {
885 info: Some(acc1),
886 status: AccountStatus::InMemoryChange,
887 previous_info: None,
888 previous_status: AccountStatus::LoadedNotExisting,
889 storage: StorageWithOriginalValues::default(),
890 storage_was_destroyed: false,
891 };
892
893 bundle_state.apply_transitions_and_create_reverts(
895 TransitionState::single(address, transition.clone()),
896 BundleRetention::Reverts,
897 );
898 }
899
900 const fn account1() -> Address {
901 Address::new([0x60; 20])
902 }
903
904 const fn account2() -> Address {
905 Address::new([0x61; 20])
906 }
907
908 fn slot1() -> U256 {
909 U256::from(5)
910 }
911
912 fn slot2() -> U256 {
913 U256::from(7)
914 }
915
916 fn test_bundle1() -> BundleState {
918 BundleState::new(
920 vec![
921 (
922 account1(),
923 None,
924 Some(AccountInfo {
925 nonce: 1,
926 balance: U256::from(10),
927 code_hash: KECCAK_EMPTY,
928 code: None,
929 }),
930 HashMap::from_iter([
931 (slot1(), (U256::from(0), U256::from(10))),
932 (slot2(), (U256::from(0), U256::from(15))),
933 ]),
934 ),
935 (
936 account2(),
937 None,
938 Some(AccountInfo {
939 nonce: 1,
940 balance: U256::from(10),
941 code_hash: KECCAK_EMPTY,
942 code: None,
943 }),
944 HashMap::default(),
945 ),
946 ],
947 vec![vec![
948 (
949 account1(),
950 Some(None),
951 vec![(slot1(), U256::from(0)), (slot2(), U256::from(0))],
952 ),
953 (account2(), Some(None), vec![]),
954 ]],
955 vec![],
956 )
957 }
958
959 fn test_bundle2() -> BundleState {
961 BundleState::new(
963 vec![(
964 account1(),
965 None,
966 Some(AccountInfo {
967 nonce: 3,
968 balance: U256::from(20),
969 code_hash: KECCAK_EMPTY,
970 code: None,
971 }),
972 HashMap::from_iter([(slot1(), (U256::from(0), U256::from(15)))]),
973 )],
974 vec![vec![(
975 account1(),
976 Some(Some(AccountInfo {
977 nonce: 1,
978 balance: U256::from(10),
979 code_hash: KECCAK_EMPTY,
980 code: None,
981 })),
982 vec![(slot1(), U256::from(10))],
983 )]],
984 vec![],
985 )
986 }
987
988 fn test_bundle3() -> BundleState {
990 BundleState::builder(0..=0)
991 .state_present_account_info(
992 account1(),
993 AccountInfo {
994 nonce: 1,
995 balance: U256::from(10),
996 code_hash: KECCAK_EMPTY,
997 code: None,
998 },
999 )
1000 .state_storage(
1001 account1(),
1002 HashMap::from_iter([(slot1(), (U256::from(0), U256::from(10)))]),
1003 )
1004 .state_address(account2())
1005 .state_present_account_info(
1006 account2(),
1007 AccountInfo {
1008 nonce: 1,
1009 balance: U256::from(10),
1010 code_hash: KECCAK_EMPTY,
1011 code: None,
1012 },
1013 )
1014 .revert_address(0, account1())
1015 .revert_account_info(0, account1(), Some(None))
1016 .revert_storage(0, account1(), vec![(slot1(), U256::from(0))])
1017 .revert_account_info(0, account2(), Some(None))
1018 .build()
1019 }
1020
1021 fn test_bundle4() -> BundleState {
1023 BundleState::builder(0..=0)
1024 .state_present_account_info(
1025 account1(),
1026 AccountInfo {
1027 nonce: 3,
1028 balance: U256::from(20),
1029 code_hash: KECCAK_EMPTY,
1030 code: None,
1031 },
1032 )
1033 .state_storage(
1034 account1(),
1035 HashMap::from_iter([(slot1(), (U256::from(0), U256::from(15)))]),
1036 )
1037 .revert_address(0, account1())
1038 .revert_account_info(
1039 0,
1040 account1(),
1041 Some(Some(AccountInfo {
1042 nonce: 1,
1043 balance: U256::from(10),
1044 code_hash: KECCAK_EMPTY,
1045 code: None,
1046 })),
1047 )
1048 .revert_storage(0, account1(), vec![(slot1(), U256::from(10))])
1049 .build()
1050 }
1051
1052 fn sanity_path(bundle1: BundleState, bundle2: BundleState) {
1053 let mut extended = bundle1.clone();
1054 extended.extend(bundle2.clone());
1055
1056 let mut reverted = extended.clone();
1057 reverted.revert(0);
1059 assert_eq!(reverted, extended);
1060
1061 reverted.revert(1);
1063 assert_eq!(reverted, bundle1);
1064
1065 reverted.revert(1);
1067 assert_eq!(reverted, BundleState::default());
1068
1069 let mut reverted = extended.clone();
1070
1071 reverted.revert(10);
1073 assert_eq!(reverted, BundleState::default());
1074 }
1075
1076 #[test]
1077 fn extend_on_destroyed_values() {
1078 let base_bundle1 = test_bundle1();
1079 let base_bundle2 = test_bundle2();
1080
1081 let mut b1 = base_bundle1.clone();
1086 let mut b2 = base_bundle2.clone();
1087 b1.state.get_mut(&account1()).unwrap().status = AccountStatus::Destroyed;
1088 b2.state.get_mut(&account1()).unwrap().status = AccountStatus::Changed;
1089 b1.extend(b2);
1090 assert_eq!(
1091 b1.state.get_mut(&account1()).unwrap().status,
1092 AccountStatus::DestroyedChanged
1093 );
1094
1095 let mut b1 = base_bundle1.clone();
1100 let mut b2 = base_bundle2.clone();
1101 b1.state.get_mut(&account1()).unwrap().status = AccountStatus::Changed;
1102 b2.state.get_mut(&account1()).unwrap().status = AccountStatus::Destroyed;
1103 b2.reverts[0][0].1.wipe_storage = true;
1104 b1.extend(b2);
1105 assert_eq!(
1106 b1.state.get_mut(&account1()).unwrap().status,
1107 AccountStatus::Destroyed
1108 );
1109
1110 let mut revert1 = base_bundle2.reverts[0][0].clone();
1113 revert1.1.wipe_storage = true;
1114 revert1
1115 .1
1116 .storage
1117 .insert(slot2(), RevertToSlot::Some(U256::from(15)));
1118
1119 assert_eq!(
1120 b1.reverts.as_ref(),
1121 vec![base_bundle1.reverts[0].clone(), vec![revert1]],
1122 );
1123
1124 let mut b1 = base_bundle1.clone();
1130 let mut b2 = base_bundle2.clone();
1131 b1.state.get_mut(&account1()).unwrap().status = AccountStatus::InMemoryChange;
1132 b2.state.get_mut(&account1()).unwrap().status = AccountStatus::Changed;
1133 b1.extend(b2);
1134 assert_eq!(
1135 b1.state.get_mut(&account1()).unwrap().status,
1136 AccountStatus::InMemoryChange
1137 );
1138 }
1139
1140 #[test]
1141 fn test_sanity_path() {
1142 sanity_path(test_bundle1(), test_bundle2());
1143 sanity_path(test_bundle3(), test_bundle4());
1144 }
1145
1146 #[test]
1147 fn test_multi_reverts_with_delete() {
1148 let mut state = BundleBuilder::new(0..=3)
1149 .revert_address(0, account1())
1150 .revert_account_info(2, account1(), Some(Some(AccountInfo::default())))
1151 .revert_account_info(3, account1(), Some(None))
1152 .build();
1153
1154 state.revert_latest();
1155 assert_eq!(state.state.get(&account1()), None);
1157
1158 state.revert_latest();
1159 assert_eq!(
1161 state.state.get(&account1()),
1162 Some(&BundleAccount::new(
1163 None,
1164 Some(AccountInfo::default()),
1165 HashMap::default(),
1166 AccountStatus::Changed
1167 ))
1168 );
1169 }
1170
1171 #[test]
1172 fn test_revert_capacity() {
1173 let state = BundleState::builder(0..=3)
1174 .revert_address(0, account1())
1175 .revert_address(2, account2())
1176 .revert_account_info(0, account1(), Some(None))
1177 .revert_account_info(2, account2(), None)
1178 .revert_storage(0, account1(), vec![(slot1(), U256::from(10))])
1179 .build();
1180
1181 assert_eq!(state.reverts.len(), 4);
1182 assert_eq!(state.reverts[1], vec![]);
1183 assert_eq!(state.reverts[3], vec![]);
1184 assert_eq!(state.reverts[0].len(), 1);
1185 assert_eq!(state.reverts[2].len(), 1);
1186
1187 let (addr1, revert1) = &state.reverts[0][0];
1188 assert_eq!(addr1, &account1());
1189 assert_eq!(revert1.account, AccountInfoRevert::DeleteIt);
1190
1191 let (addr2, revert2) = &state.reverts[2][0];
1192 assert_eq!(addr2, &account2());
1193 assert_eq!(revert2.account, AccountInfoRevert::DoNothing);
1194 }
1195
1196 #[test]
1197 fn take_reverts() {
1198 let bundle1 = test_bundle1();
1199 let bundle2 = test_bundle2();
1200
1201 let mut extended = bundle1.clone();
1202 extended.extend(bundle2.clone());
1203
1204 assert_eq!(extended.reverts.len(), 2);
1206
1207 let mut extended2 = extended.clone();
1209 assert_eq!(extended2.take_n_reverts(100), extended.reverts);
1210
1211 let mut extended2 = extended.clone();
1213 assert_eq!(extended2.take_all_reverts(), extended.reverts);
1214
1215 let taken_reverts = extended.take_n_reverts(0);
1217 assert_eq!(taken_reverts, Reverts::default());
1218 assert_eq!(extended.reverts.len(), 2);
1219
1220 let taken_reverts = extended.take_n_reverts(1);
1222 assert_eq!(taken_reverts, bundle1.reverts);
1223
1224 let taken_reverts = extended.take_n_reverts(1);
1226 assert_eq!(taken_reverts, bundle2.reverts);
1227 }
1228
1229 #[test]
1230 fn prepend_state() {
1231 let address1 = account1();
1232 let address2 = account2();
1233
1234 let account1 = AccountInfo {
1235 nonce: 1,
1236 ..Default::default()
1237 };
1238 let account1_changed = AccountInfo {
1239 nonce: 1,
1240 ..Default::default()
1241 };
1242 let account2 = AccountInfo {
1243 nonce: 1,
1244 ..Default::default()
1245 };
1246
1247 let present_state = BundleState::builder(2..=2)
1248 .state_present_account_info(address1, account1_changed.clone())
1249 .build();
1250 assert_eq!(present_state.reverts.len(), 1);
1251 let previous_state = BundleState::builder(1..=1)
1252 .state_present_account_info(address1, account1)
1253 .state_present_account_info(address2, account2.clone())
1254 .build();
1255 assert_eq!(previous_state.reverts.len(), 1);
1256
1257 let mut test = present_state;
1258
1259 test.prepend_state(previous_state);
1260
1261 assert_eq!(test.state.len(), 2);
1262 assert_eq!(test.reverts.len(), 1);
1264 assert_eq!(
1266 test.state.get(&address1).unwrap().info,
1267 Some(account1_changed)
1268 );
1269 assert_eq!(test.state.get(&address2).unwrap().info, Some(account2));
1271 }
1272
1273 #[test]
1274 fn test_getters() {
1275 let mut builder = BundleBuilder::new(0..=3);
1276
1277 assert!(builder.get_states().is_empty());
1279 builder.get_states_mut().insert(account1());
1280 assert!(builder.get_states().contains(&account1()));
1281
1282 assert!(builder.get_state_original_mut().is_empty());
1284 builder
1285 .get_state_original_mut()
1286 .insert(account1(), AccountInfo::default());
1287 assert!(builder.get_state_original_mut().contains_key(&account1()));
1288
1289 assert!(builder.get_state_present_mut().is_empty());
1291 builder
1292 .get_state_present_mut()
1293 .insert(account1(), AccountInfo::default());
1294 assert!(builder.get_state_present_mut().contains_key(&account1()));
1295
1296 assert!(builder.get_state_storage_mut().is_empty());
1298 builder
1299 .get_state_storage_mut()
1300 .insert(account1(), HashMap::default());
1301 assert!(builder.get_state_storage_mut().contains_key(&account1()));
1302
1303 assert!(builder.get_reverts_mut().is_empty());
1305 builder.get_reverts_mut().insert((0, account1()));
1306 assert!(builder.get_reverts_mut().contains(&(0, account1())));
1307
1308 assert_eq!(builder.get_revert_range_mut().clone(), 0..=3);
1310
1311 assert!(builder.get_revert_account_mut().is_empty());
1313 builder
1314 .get_revert_account_mut()
1315 .insert((0, account1()), Some(None));
1316 assert!(builder
1317 .get_revert_account_mut()
1318 .contains_key(&(0, account1())));
1319
1320 assert!(builder.get_revert_storage_mut().is_empty());
1322 builder
1323 .get_revert_storage_mut()
1324 .insert((0, account1()), vec![(slot1(), U256::from(0))]);
1325 assert!(builder
1326 .get_revert_storage_mut()
1327 .contains_key(&(0, account1())));
1328
1329 assert!(builder.get_contracts_mut().is_empty());
1331 builder
1332 .get_contracts_mut()
1333 .insert(B256::default(), Bytecode::default());
1334 assert!(builder.get_contracts_mut().contains_key(&B256::default()));
1335 }
1336}