1use alloy::primitives::{Address, U256};
15use std::ops::{Index, IndexMut};
16
17use crate::{
18 error::{Result, TempoPrecompileError},
19 storage::{
20 Handler, Layout, LayoutCtx, Storable, StorableType, StorageCtx, StorageOps,
21 packing::{PackedSlot, calc_element_loc, calc_packed_slot_count},
22 types::{HandlerCache, Slot},
23 },
24};
25
26impl<T> StorableType for Vec<T>
27where
28 T: Storable,
29{
30 const LAYOUT: Layout = Layout::Slots(1);
32 const IS_DYNAMIC: bool = true;
33 type Handler = VecHandler<T>;
34
35 fn handle(slot: U256, _ctx: LayoutCtx, address: Address) -> Self::Handler {
36 VecHandler::new(slot, address)
37 }
38}
39
40impl<T> Storable for Vec<T>
41where
42 T: Storable,
43{
44 fn load<S: StorageOps>(storage: &S, len_slot: U256, ctx: LayoutCtx) -> Result<Self> {
45 debug_assert!(ctx.is_full(), "Dynamic arrays cannot be packed");
46
47 let length = load_checked_len(storage, len_slot)?;
49
50 if length == 0 {
51 return Ok(Self::new());
52 }
53
54 let data_start = calc_data_slot(len_slot);
56 if T::BYTES <= 16 {
57 load_packed_elements(storage, data_start, length, T::BYTES)
58 } else {
59 load_unpacked_elements(storage, data_start, length)
60 }
61 }
62
63 fn store<S: StorageOps>(&self, storage: &mut S, len_slot: U256, ctx: LayoutCtx) -> Result<()> {
64 debug_assert!(ctx.is_full(), "Dynamic arrays cannot be packed");
65 let data_start = calc_data_slot(len_slot);
66
67 if !ctx.skip_tail_cleanup() && StorageCtx.spec().is_t5() {
69 let (prev_len, new_len) = (load_checked_len(storage, len_slot)?, self.len());
70 if prev_len > new_len {
71 clear_elements::<T, S>(storage, data_start, new_len, prev_len)?;
72 }
73 }
74
75 storage.store(len_slot, U256::from(self.len()))?;
77
78 if self.is_empty() {
79 return Ok(());
80 }
81
82 if T::BYTES <= 16 {
84 store_packed_elements(self, storage, data_start)
85 } else {
86 store_unpacked_elements(self, storage, data_start)
87 }
88 }
89
90 fn delete<S: StorageOps>(storage: &mut S, len_slot: U256, ctx: LayoutCtx) -> Result<()> {
92 debug_assert!(ctx.is_full(), "Dynamic arrays cannot be packed");
93
94 let length = load_checked_len(storage, len_slot)?;
96
97 storage.store(len_slot, U256::ZERO)?;
99
100 if length == 0 {
101 return Ok(());
102 }
103
104 let data_start = calc_data_slot(len_slot);
105 clear_elements::<T, S>(storage, data_start, 0, length)
106 }
107}
108
109#[derive(Debug, Clone)]
143pub struct VecHandler<T: Storable> {
144 len_slot: U256,
145 address: Address,
146 cache: HandlerCache<usize, T::Handler>,
147}
148
149impl<T> Handler<Vec<T>> for VecHandler<T>
150where
151 T: Storable,
152{
153 #[inline]
155 fn read(&self) -> Result<Vec<T>> {
156 self.as_slot().read()
157 }
158
159 #[inline]
161 fn write(&mut self, value: Vec<T>) -> Result<()> {
162 self.as_slot().write(value)
163 }
164
165 #[inline]
167 fn delete(&mut self) -> Result<()> {
168 self.as_slot().delete()
169 }
170
171 #[inline]
173 fn t_read(&self) -> Result<Vec<T>> {
174 self.as_slot().t_read()
175 }
176
177 #[inline]
179 fn t_write(&mut self, value: Vec<T>) -> Result<()> {
180 self.as_slot().t_write(value)
181 }
182
183 #[inline]
185 fn t_delete(&mut self) -> Result<()> {
186 self.as_slot().t_delete()
187 }
188}
189
190impl<T> VecHandler<T>
191where
192 T: Storable,
193{
194 #[inline]
196 pub fn new(len_slot: U256, address: Address) -> Self {
197 Self {
198 len_slot,
199 address,
200 cache: HandlerCache::new(),
201 }
202 }
203
204 const fn max_index() -> usize {
207 if T::BYTES <= 16 {
208 u32::MAX as usize / T::BYTES
209 } else {
210 u32::MAX as usize / T::SLOTS
211 }
212 }
213
214 #[inline]
216 pub fn len_slot(&self) -> ::alloy::primitives::U256 {
217 self.len_slot
218 }
219
220 #[inline]
225 pub fn data_slot(&self) -> ::alloy::primitives::U256 {
226 calc_data_slot(self.len_slot)
227 }
228
229 #[inline]
231 fn as_slot(&self) -> Slot<Vec<T>> {
232 Slot::new(self.len_slot, self.address)
233 }
234
235 #[inline]
237 pub fn len(&self) -> Result<usize> {
238 let slot = Slot::<U256>::new(self.len_slot, self.address);
239 load_checked_len(&slot, self.len_slot)
240 }
241
242 #[inline]
244 pub fn is_empty(&self) -> Result<bool> {
245 Ok(self.len()? == 0)
246 }
247
248 #[inline]
249 fn compute_handler(data_start: U256, address: Address, index: usize) -> T::Handler {
250 let (slot, layout_ctx) = if T::BYTES <= 16 {
252 let location = calc_element_loc(index, T::BYTES);
253 (
254 data_start + U256::from(location.offset_slots),
255 LayoutCtx::packed(location.offset_bytes),
256 )
257 } else {
258 (data_start + U256::from(index * T::SLOTS), LayoutCtx::FULL)
259 };
260
261 T::handle(slot, layout_ctx, address)
262 }
263
264 pub fn at(&self, index: usize) -> Result<Option<&T::Handler>> {
273 if index >= self.len()? {
274 return Ok(None);
275 }
276
277 let (data_start, address) = (self.data_slot(), self.address);
278 Ok(Some(self.cache.get_or_insert(&index, || {
279 Self::compute_handler(data_start, address, index)
280 })))
281 }
282
283 #[inline]
289 pub fn push(&self, value: T) -> Result<()>
290 where
291 T: Storable,
292 T::Handler: Handler<T>,
293 {
294 let length = self.len()?;
296 if length >= Self::max_index() {
297 return Err(TempoPrecompileError::Fatal("Vec is at max capacity".into()));
298 }
299
300 if T::BYTES <= 16 {
302 let mut elem_slot = Self::compute_handler(self.data_slot(), self.address, length);
303 elem_slot.write(value)?;
304 } else {
305 let elem_slot = self.data_slot() + U256::from(length * T::SLOTS);
308 let mut storage = Slot::<T>::new(elem_slot, self.address);
309 value.store(&mut storage, elem_slot, LayoutCtx::INIT)?;
310 }
311
312 let mut length_slot = Slot::<U256>::new(self.len_slot, self.address);
314 length_slot.write(U256::from(length + 1))
315 }
316
317 #[inline]
322 pub fn pop(&self) -> Result<Option<T>>
323 where
324 T: Storable,
325 T::Handler: Handler<T>,
326 {
327 let length = self.len()?;
329 if length == 0 {
330 return Ok(None);
331 }
332 let last_index = length - 1;
333
334 let mut elem_slot = Self::compute_handler(self.data_slot(), self.address, last_index);
336 let element = elem_slot.read()?;
337
338 elem_slot.delete()?;
340
341 let mut length_slot = Slot::<U256>::new(self.len_slot, self.address);
343 length_slot.write(U256::from(last_index))?;
344
345 Ok(Some(element))
346 }
347}
348
349impl<T> Index<usize> for VecHandler<T>
350where
351 T: Storable,
352{
353 type Output = T::Handler;
354
355 fn index(&self, index: usize) -> &Self::Output {
360 let (data_start, address) = (self.data_slot(), self.address);
361 self.cache
362 .get_or_insert(&index, || Self::compute_handler(data_start, address, index))
363 }
364}
365
366impl<T> IndexMut<usize> for VecHandler<T>
367where
368 T: Storable,
369{
370 fn index_mut(&mut self, index: usize) -> &mut Self::Output {
375 let (data_start, address) = (self.data_slot(), self.address);
376 self.cache
377 .get_or_insert_mut(&index, || Self::compute_handler(data_start, address, index))
378 }
379}
380
381#[inline]
383fn load_checked_len<S: StorageOps>(storage: &S, slot: U256) -> Result<usize> {
384 let raw = storage.load(slot)?;
385 if raw > U256::from(u32::MAX) {
386 return Err(TempoPrecompileError::under_overflow());
387 }
388 Ok(raw.to::<usize>())
389}
390
391#[inline]
395pub(crate) fn calc_data_slot(len_slot: U256) -> U256 {
396 U256::from_be_bytes(alloy::primitives::keccak256(len_slot.to_be_bytes::<32>()).0)
397}
398
399fn clear_elements<T: Storable, S: StorageOps>(
414 storage: &mut S,
415 data_start: U256,
416 from: usize,
417 to: usize,
418) -> Result<()> {
419 if from >= to {
420 return Ok(());
421 }
422 if T::BYTES <= 16 {
423 let from_slots = calc_packed_slot_count(from, T::BYTES);
425 let to_slots = calc_packed_slot_count(to, T::BYTES);
426 for slot_idx in from_slots..to_slots {
427 storage.store(data_start + U256::from(slot_idx), U256::ZERO)?;
428 }
429 } else {
430 for elem_idx in from..to {
431 let elem_slot = data_start + U256::from(elem_idx * T::SLOTS);
432 T::delete(storage, elem_slot, LayoutCtx::FULL)?;
433 }
434 }
435 Ok(())
436}
437
438fn load_packed_elements<T: Storable, S: StorageOps>(
442 storage: &S,
443 data_start: U256,
444 length: usize,
445 byte_count: usize,
446) -> Result<Vec<T>> {
447 debug_assert!(
448 T::BYTES <= 16,
449 "load_packed_elements requires T::BYTES <= 16"
450 );
451 let elements_per_slot = 32 / byte_count;
452 let slot_count = calc_packed_slot_count(length, byte_count);
453
454 let mut result = Vec::new();
455 let mut current_offset = 0;
456
457 for slot_idx in 0..slot_count {
458 let slot_addr = data_start + U256::from(slot_idx);
459 let slot_value = storage.load(slot_addr)?;
460 let slot_packed = PackedSlot(slot_value);
461
462 let elements_in_this_slot = if slot_idx == slot_count - 1 {
464 length - (slot_idx * elements_per_slot)
466 } else {
467 elements_per_slot
468 };
469
470 for _ in 0..elements_in_this_slot {
472 let elem = T::load(&slot_packed, slot_addr, LayoutCtx::packed(current_offset))?;
473 result.push(elem);
474
475 current_offset += byte_count;
477 if current_offset >= 32 {
478 current_offset = 0;
479 }
480 }
481
482 current_offset = 0;
484 }
485
486 Ok(result)
487}
488
489fn store_packed_elements<T: Storable, S: StorageOps>(
493 elements: &[T],
494 storage: &mut S,
495 data_start: U256,
496) -> Result<()> {
497 debug_assert!(
498 T::BYTES <= 16,
499 "store_packed_elements requires T::BYTES <= 16"
500 );
501 let elements_per_slot = 32 / T::BYTES;
502 let slot_count = calc_packed_slot_count(elements.len(), T::BYTES);
503
504 for slot_idx in 0..slot_count {
505 let slot_addr = data_start + U256::from(slot_idx);
506 let start_elem = slot_idx * elements_per_slot;
507 let end_elem = (start_elem + elements_per_slot).min(elements.len());
508
509 let slot_value = build_packed_slot(&elements[start_elem..end_elem], T::BYTES)?;
510 storage.store(slot_addr, slot_value)?;
511 }
512
513 Ok(())
514}
515
516fn build_packed_slot<T: Storable>(elements: &[T], byte_count: usize) -> Result<U256> {
520 debug_assert!(T::BYTES <= 16, "build_packed_slot requires T::BYTES <= 16");
521 let mut slot_value = PackedSlot(U256::ZERO);
522 let mut current_offset = 0;
523
524 for elem in elements {
525 elem.store(
526 &mut slot_value,
527 U256::ZERO,
528 LayoutCtx::packed(current_offset),
529 )?;
530 current_offset += byte_count;
531 }
532
533 Ok(slot_value.0)
534}
535
536fn load_unpacked_elements<T: Storable, S: StorageOps>(
541 storage: &S,
542 data_start: U256,
543 length: usize,
544) -> Result<Vec<T>> {
545 let mut result = Vec::new();
546 for index in 0..length {
547 let elem_slot = data_start + U256::from(index * T::SLOTS);
549 let elem = T::load(storage, elem_slot, LayoutCtx::FULL)?;
550 result.push(elem);
551 }
552 Ok(result)
553}
554
555fn store_unpacked_elements<T: Storable, S: StorageOps>(
559 elements: &[T],
560 storage: &mut S,
561 data_start: U256,
562) -> Result<()> {
563 for (elem_idx, elem) in elements.iter().enumerate() {
564 let elem_slot = data_start + U256::from(elem_idx * T::SLOTS);
566 elem.store(storage, elem_slot, LayoutCtx::FULL)?;
567 }
568
569 Ok(())
570}
571
572#[cfg(test)]
573mod tests {
574 use super::*;
575 use crate::{
576 storage::{Handler, StorageCtx},
577 test_util::{gen_word_from, setup_storage},
578 };
579 use alloy::primitives::Address;
580 use proptest::prelude::*;
581 use tempo_precompiles_macros::Storable;
582
583 fn arb_safe_slot() -> impl Strategy<Value = U256> {
587 any::<[u64; 4]>().prop_map(|limbs| {
588 U256::from_limbs(limbs) % (U256::MAX - U256::from(10000))
590 })
591 }
592
593 #[derive(Debug, Clone, PartialEq, Eq, Storable)]
595 struct TestStruct {
596 a: u128, b: u128, }
599
600 #[test]
604 fn test_vec_handler_slot_computation() {
605 let len_slot = U256::random();
606 let address = Address::random();
607 let handler = VecHandler::<u8>::new(len_slot, address);
608
609 assert_eq!(handler.len_slot, len_slot);
611
612 assert_eq!(*handler.address, *address);
614 }
615
616 #[test]
617 fn test_vec_data_slot_derivation() {
618 let len_slot = U256::random();
619
620 let data_slot = calc_data_slot(len_slot);
622 let expected =
623 U256::from_be_bytes(alloy::primitives::keccak256(len_slot.to_be_bytes::<32>()).0);
624
625 assert_eq!(
626 data_slot, expected,
627 "Data slot should be keccak256(len_slot)"
628 );
629 }
630
631 #[test]
632 fn test_vec_at_element_slot_packed() {
633 let len_slot = U256::random();
634 let address = Address::random();
635 let handler = VecHandler::<u8>::new(len_slot, address);
636
637 let data_start = calc_data_slot(len_slot);
638
639 let elem_slot = &handler[5];
642 let expected_loc = calc_element_loc(5, u8::BYTES);
643 assert_eq!(
644 elem_slot.slot(),
645 data_start + U256::from(expected_loc.offset_slots)
646 );
647 assert_eq!(elem_slot.offset(), Some(expected_loc.offset_bytes));
648
649 let elem_slot = &handler[35];
651 let expected_loc = calc_element_loc(35, u8::BYTES);
652 assert_eq!(
653 elem_slot.slot(),
654 data_start + U256::from(expected_loc.offset_slots)
655 );
656 assert_eq!(elem_slot.offset(), Some(expected_loc.offset_bytes));
657 }
658
659 #[test]
660 fn test_vec_at_element_slot_unpacked() {
661 let len_slot = U256::random();
662 let address = Address::random();
663 let handler = VecHandler::<U256>::new(len_slot, address);
664
665 let data_start = calc_data_slot(len_slot);
666
667 let elem_slot = &handler[0];
670 assert_eq!(elem_slot.slot(), data_start);
671 assert_eq!(elem_slot.offset(), None); let elem_slot = &handler[5];
675 assert_eq!(elem_slot.slot(), data_start + U256::from(5));
676 assert_eq!(elem_slot.offset(), None);
677 }
678
679 #[test]
680 fn test_vec_at_determinism() {
681 let len_slot = U256::random();
682 let address = Address::random();
683 let handler = VecHandler::<u16>::new(len_slot, address);
684
685 let slot1 = &handler[10];
687 let slot2 = &handler[10];
688
689 assert_eq!(
690 slot1.slot(),
691 slot2.slot(),
692 "Same index should produce same slot"
693 );
694 assert_eq!(
695 slot1.offset(),
696 slot2.offset(),
697 "Same index should produce same offset"
698 );
699 }
700
701 #[test]
702 fn test_vec_at_different_indices() {
703 let len_slot = U256::random();
704 let address = Address::random();
705 let handler = VecHandler::<u16>::new(len_slot, address);
706
707 let slot5 = &handler[5];
709 let slot10 = &handler[10];
710
711 assert_eq!(slot5.slot(), slot10.slot(), "Both should be in same slot");
715 assert_ne!(slot5.offset(), slot10.offset(), "But different offsets");
716
717 let slot16 = &handler[16];
719 assert_ne!(
720 slot5.slot(),
721 slot16.slot(),
722 "Different slot for index >= 16"
723 );
724 }
725
726 #[test]
729 fn test_vec_empty() {
730 let (mut storage, address) = setup_storage();
731
732 StorageCtx::enter(&mut storage, || {
733 let len_slot = U256::random();
734
735 let data: Vec<u8> = vec![];
736 let mut slot = Slot::<Vec<u8>>::new(len_slot, address);
737 slot.write(data.clone()).unwrap();
738
739 let loaded: Vec<u8> = slot.read().unwrap();
740 assert_eq!(loaded, data, "Empty vec roundtrip failed");
741 assert!(loaded.is_empty(), "Loaded vec should be empty");
742 });
743 }
744
745 #[test]
746 fn test_vec_nested() {
747 let (mut storage, address) = setup_storage();
748
749 StorageCtx::enter(&mut storage, || {
750 let len_slot = U256::random();
751
752 let data = vec![vec![1u8, 2, 3], vec![4, 5], vec![6, 7, 8, 9]];
754 let mut slot = Slot::<Vec<Vec<u8>>>::new(len_slot, address);
755 slot.write(data.clone()).unwrap();
756
757 let loaded: Vec<Vec<u8>> = slot.read().unwrap();
758 assert_eq!(loaded, data, "Nested Vec<Vec<u8>> roundtrip failed");
759 });
760 }
761
762 #[test]
763 fn test_vec_bool_packing() {
764 let (mut storage, address) = setup_storage();
765
766 StorageCtx::enter(&mut storage, || {
767 let len_slot = U256::random();
768 let mut slot = Slot::<Vec<bool>>::new(len_slot, address);
769
770 let data_exact: Vec<bool> = (0..32).map(|i| i % 2 == 0).collect();
772 slot.write(data_exact.clone()).unwrap();
773
774 let length_value = U256::handle(len_slot, LayoutCtx::FULL, address)
776 .read()
777 .unwrap();
778 assert_eq!(length_value, U256::from(32), "Length not stored correctly");
779
780 let loaded: Vec<bool> = slot.read().unwrap();
781 assert_eq!(
782 loaded, data_exact,
783 "Vec<bool> with 32 elements failed roundtrip"
784 );
785
786 let data_overflow: Vec<bool> = (0..35).map(|i| i % 3 == 0).collect();
788 slot.write(data_overflow.clone()).unwrap();
789
790 let loaded: Vec<bool> = slot.read().unwrap();
791 assert_eq!(
792 loaded, data_overflow,
793 "Vec<bool> with 35 elements failed roundtrip"
794 );
795 });
796 }
797
798 #[test]
801 fn test_vec_u8_explicit_slot_packing() {
802 let (mut storage, address) = setup_storage();
803
804 StorageCtx::enter(&mut storage, || {
805 let len_slot = U256::from(2000);
806 let data = vec![10u8, 20, 30, 40, 50];
807
808 <Vec<u8>>::handle(len_slot, LayoutCtx::FULL, address)
810 .write(data.clone())
811 .unwrap();
812
813 let length = U256::handle(len_slot, LayoutCtx::FULL, address)
815 .read()
816 .unwrap();
817 assert_eq!(
818 length,
819 U256::from(data.len()),
820 "Length not stored correctly"
821 );
822
823 let data_start = calc_data_slot(len_slot);
824 let slot_data = U256::handle(data_start, LayoutCtx::FULL, address)
825 .read()
826 .unwrap();
827
828 let expected = gen_word_from(&[
830 "0x32", "0x28", "0x1e", "0x14", "0x0a", ]);
836 assert_eq!(
837 slot_data, expected,
838 "Slot data should match Solidity byte layout"
839 );
840
841 for (i, &expected) in data.iter().enumerate() {
843 let offset = i; let actual =
845 Slot::<u8>::new_with_ctx(data_start, LayoutCtx::packed(offset), address)
846 .read()
847 .unwrap();
848 assert_eq!(actual, expected, "mismatch: elem[{i}] at offset {offset}");
849 }
850 });
851 }
852
853 #[test]
854 fn test_vec_u16_slot_boundary() {
855 let (mut storage, address) = setup_storage();
856
857 StorageCtx::enter(&mut storage, || {
858 let len_slot = U256::from(2100);
859 let mut vec_slot = Slot::<Vec<u16>>::new(len_slot, address);
860
861 let data_exact: Vec<u16> = (0..16).map(|i| i * 100).collect();
863 vec_slot.write(data_exact.clone()).unwrap();
864
865 let data_start = calc_data_slot(len_slot);
866 let slot0_value = U256::handle(data_start, LayoutCtx::FULL, address)
867 .read()
868 .unwrap();
869
870 let expected_slot0 = gen_word_from(&[
871 "0x05dc", "0x0578", "0x0514", "0x04b0", "0x044c", "0x03e8", "0x0384", "0x0320", "0x02bc", "0x0258", "0x01f4", "0x0190", "0x012c", "0x00c8", "0x0064", "0x0000", ]);
888 assert_eq!(
889 slot0_value, expected_slot0,
890 "Slot 0 should match Solidity byte layout"
891 );
892
893 for (i, &expected) in data_exact.iter().enumerate() {
895 let offset = i * u16::BYTES;
896 let actual =
897 Slot::<u16>::new_with_ctx(data_start, LayoutCtx::packed(offset), address)
898 .read()
899 .unwrap();
900 assert_eq!(actual, expected, "mismatch: elem[{i}] at offset {offset}");
901 }
902
903 let data_overflow: Vec<u16> = (0..17).map(|i| i * 100).collect();
905 vec_slot.write(data_overflow).unwrap();
906
907 let slot0_value = U256::handle(data_start, LayoutCtx::FULL, address)
909 .read()
910 .unwrap();
911 assert_eq!(
912 slot0_value, expected_slot0,
913 "Slot 0 should still match after overflow"
914 );
915
916 let slot1_addr = data_start + U256::ONE;
918 let slot1_value = U256::handle(slot1_addr, LayoutCtx::FULL, address)
919 .read()
920 .unwrap();
921
922 let expected_slot1 = gen_word_from(&[
923 "0x0640", ]);
925 assert_eq!(
926 slot1_value, expected_slot1,
927 "Slot 1 should match Solidity byte layout"
928 );
929
930 let actual = Slot::<u16>::new_with_ctx(slot1_addr, LayoutCtx::packed(0), address)
932 .read()
933 .unwrap();
934 assert_eq!(actual, 1600u16, "mismatch: slot1_elem[0] at offset 0");
935 });
936 }
937
938 #[test]
939 fn test_vec_u8_partial_slot_fill() {
940 let (mut storage, address) = setup_storage();
941
942 StorageCtx::enter(&mut storage, || {
943 let len_slot = U256::from(2200);
944
945 let data: Vec<u8> = (0..35).map(|i| (i + 1) as u8).collect();
949 let mut vec_slot = Slot::<Vec<u8>>::new(len_slot, address);
950 vec_slot.write(data).unwrap();
951 let data_start = calc_data_slot(len_slot);
952 let slot0_value = U256::handle(data_start, LayoutCtx::FULL, address)
953 .read()
954 .unwrap();
955
956 let expected_slot0 = gen_word_from(&[
957 "0x20", "0x1f", "0x1e", "0x1d", "0x1c", "0x1b", "0x1a", "0x19", "0x18", "0x17", "0x16", "0x15", "0x14", "0x13", "0x12", "0x11", "0x10", "0x0f", "0x0e", "0x0d", "0x0c", "0x0b", "0x0a", "0x09", "0x08", "0x07", "0x06", "0x05", "0x04", "0x03", "0x02", "0x01", ]);
990 assert_eq!(
991 slot0_value, expected_slot0,
992 "Slot 0 should match Solidity byte layout"
993 );
994
995 let slot1_addr = data_start + U256::ONE;
997 let slot1_value = U256::handle(slot1_addr, LayoutCtx::FULL, address)
998 .read()
999 .unwrap();
1000
1001 let expected_slot1 = gen_word_from(&[
1002 "0x23", "0x22", "0x21", ]);
1006 assert_eq!(
1007 slot1_value, expected_slot1,
1008 "Slot 1 should match Solidity byte layout"
1009 );
1010
1011 let slot1_data = [33u8, 34u8, 35u8];
1013 for (i, &expected) in slot1_data.iter().enumerate() {
1014 let offset = i; let actual =
1016 Slot::<u8>::new_with_ctx(slot1_addr, LayoutCtx::packed(offset), address)
1017 .read()
1018 .unwrap();
1019 assert_eq!(
1020 actual, expected,
1021 "mismatch: slot1_elem[{i}] at offset {offset}"
1022 );
1023 }
1024 });
1025 }
1026
1027 #[test]
1028 fn test_vec_u256_individual_slots() {
1029 let (mut storage, address) = setup_storage();
1030
1031 StorageCtx::enter(&mut storage, || {
1032 let len_slot = U256::from(2300);
1033
1034 let data = vec![
1036 U256::from(0x1111111111111111u64),
1037 U256::from(0x2222222222222222u64),
1038 U256::from(0x3333333333333333u64),
1039 ];
1040 let mut vec_slot = Slot::<Vec<U256>>::new(len_slot, address);
1041 vec_slot.write(data.clone()).unwrap();
1042
1043 let data_start = calc_data_slot(len_slot);
1044
1045 for (i, &expected) in data.iter().enumerate() {
1047 let stored_value =
1048 U256::handle(data_start + U256::from(i), LayoutCtx::FULL, address)
1049 .read()
1050 .unwrap();
1051 assert_eq!(stored_value, expected, "incorrect U256 element {i}");
1052 }
1053
1054 let no_slot_value = U256::handle(data_start + U256::from(3), LayoutCtx::FULL, address)
1056 .read()
1057 .unwrap();
1058 assert_eq!(no_slot_value, U256::ZERO, "Slot 3 should be empty");
1059 });
1060 }
1061
1062 #[test]
1063 fn test_vec_address_unpacked_slots() {
1064 let (mut storage, address) = setup_storage();
1065
1066 StorageCtx::enter(&mut storage, || {
1067 let len_slot = U256::from(2400);
1068
1069 let data = vec![
1071 Address::repeat_byte(0xAA),
1072 Address::repeat_byte(0xBB),
1073 Address::repeat_byte(0xCC),
1074 ];
1075 let mut vec_slot = Slot::<Vec<Address>>::new(len_slot, address);
1076 vec_slot.write(data.clone()).unwrap();
1077
1078 let data_start = calc_data_slot(len_slot);
1079
1080 let slot0_value = U256::handle(data_start, LayoutCtx::FULL, address)
1082 .read()
1083 .unwrap();
1084 let expected_slot0 = gen_word_from(&["0xAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"]);
1085 assert_eq!(
1086 slot0_value, expected_slot0,
1087 "Slot 0 should match Solidity byte layout"
1088 );
1089
1090 let slot1_addr = data_start + U256::ONE;
1092 let slot1_value = U256::handle(slot1_addr, LayoutCtx::FULL, address)
1093 .read()
1094 .unwrap();
1095 let expected_slot1 = gen_word_from(&["0xBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB"]);
1096 assert_eq!(
1097 slot1_value, expected_slot1,
1098 "Slot 1 should match Solidity byte layout"
1099 );
1100
1101 let slot2_addr = data_start + U256::from(2);
1103 let slot2_value = U256::handle(slot2_addr, LayoutCtx::FULL, address)
1104 .read()
1105 .unwrap();
1106 let expected_slot2 = gen_word_from(&["0xCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC"]);
1107 assert_eq!(
1108 slot2_value, expected_slot2,
1109 "Slot 2 should match Solidity byte layout"
1110 );
1111
1112 for (i, &expected_addr) in data.iter().enumerate() {
1114 let slot_addr = data_start + U256::from(i);
1115 let stored_value = U256::handle(slot_addr, LayoutCtx::FULL, address)
1116 .read()
1117 .unwrap();
1118 let expected_u256 = U256::from_be_slice(expected_addr.as_slice());
1119 assert_eq!(
1120 stored_value, expected_u256,
1121 "Address element {i} should match"
1122 );
1123 }
1124 });
1125 }
1126
1127 #[test]
1128 fn test_vec_struct_slot_allocation() {
1129 let (mut storage, address) = setup_storage();
1130
1131 StorageCtx::enter(&mut storage, || {
1132 let len_slot = U256::from(2500);
1133
1134 let data = vec![
1137 TestStruct { a: 100, b: 1 },
1138 TestStruct { a: 200, b: 2 },
1139 TestStruct { a: 300, b: 3 },
1140 ];
1141 let mut vec_slot = Slot::<Vec<TestStruct>>::new(len_slot, address);
1142 vec_slot.write(data.clone()).unwrap();
1143
1144 let data_start = calc_data_slot(len_slot);
1145
1146 let slot0_value = U256::handle(data_start, LayoutCtx::FULL, address)
1150 .read()
1151 .unwrap();
1152 let expected_slot0 = gen_word_from(&[
1153 "0x00000000000000000000000000000001", "0x00000000000000000000000000000064", ]);
1156 assert_eq!(
1157 slot0_value, expected_slot0,
1158 "Slot 0 should match Solidity byte layout"
1159 );
1160
1161 let slot1_addr = data_start + U256::ONE;
1163 let slot1_value = U256::handle(slot1_addr, LayoutCtx::FULL, address)
1164 .read()
1165 .unwrap();
1166 let expected_slot1 = gen_word_from(&[
1167 "0x00000000000000000000000000000002", "0x000000000000000000000000000000C8", ]);
1170 assert_eq!(
1171 slot1_value, expected_slot1,
1172 "Slot 1 should match Solidity byte layout"
1173 );
1174
1175 let slot2_addr = data_start + U256::from(2);
1177 let slot2_value = U256::handle(slot2_addr, LayoutCtx::FULL, address)
1178 .read()
1179 .unwrap();
1180 let expected_slot2 = gen_word_from(&[
1181 "0x00000000000000000000000000000003", "0x0000000000000000000000000000012C", ]);
1184 assert_eq!(
1185 slot2_value, expected_slot2,
1186 "Slot 2 should match Solidity byte layout"
1187 );
1188
1189 let slot3_addr = data_start + U256::from(3);
1191 let slot3_value = U256::handle(slot3_addr, LayoutCtx::FULL, address)
1192 .read()
1193 .unwrap();
1194 assert_eq!(slot3_value, U256::ZERO, "Slot 3 should be empty");
1195
1196 for (i, expected_struct) in data.iter().enumerate() {
1198 let struct_slot_addr = data_start + U256::from(i);
1199 let struct_slot = Slot::<TestStruct>::new(struct_slot_addr, address);
1200 let loaded_struct = struct_slot.read().unwrap();
1201 assert_eq!(
1202 loaded_struct, *expected_struct,
1203 "TestStruct at slot {i} should match"
1204 );
1205 }
1206 });
1207 }
1208
1209 #[test]
1210 fn test_vec_small_struct_storage() {
1211 #[derive(Debug, Clone, PartialEq, Eq, Storable)]
1213 struct SmallStruct {
1214 flag1: bool, flag2: bool, value: u16, }
1218
1219 let (mut storage, address) = setup_storage();
1220
1221 StorageCtx::enter(&mut storage, || {
1222 let len_slot = U256::from(2550);
1223
1224 let data = vec![
1227 SmallStruct {
1228 flag1: true,
1229 flag2: false,
1230 value: 100,
1231 },
1232 SmallStruct {
1233 flag1: false,
1234 flag2: true,
1235 value: 200,
1236 },
1237 SmallStruct {
1238 flag1: true,
1239 flag2: true,
1240 value: 300,
1241 },
1242 ];
1243 let mut vec_slot = Slot::<Vec<SmallStruct>>::new(len_slot, address);
1244 vec_slot.write(data.clone()).unwrap();
1245
1246 let length_value = U256::handle(len_slot, LayoutCtx::FULL, address)
1248 .read()
1249 .unwrap();
1250 assert_eq!(length_value, U256::from(3), "Length not stored correctly");
1251
1252 let data_start = calc_data_slot(len_slot);
1253
1254 let slot0_value = U256::handle(data_start, LayoutCtx::FULL, address)
1256 .read()
1257 .unwrap();
1258 let expected_slot0 = gen_word_from(&[
1259 "0x0064", "0x00", "0x01", ]);
1263 assert_eq!(
1264 slot0_value, expected_slot0,
1265 "Slot 0 should match Solidity layout for struct[0]"
1266 );
1267
1268 let slot1_addr = data_start + U256::ONE;
1270 let slot1_value = U256::handle(slot1_addr, LayoutCtx::FULL, address)
1271 .read()
1272 .unwrap();
1273 let expected_slot1 = gen_word_from(&[
1274 "0x00c8", "0x01", "0x00", ]);
1278 assert_eq!(
1279 slot1_value, expected_slot1,
1280 "Slot 1 should match Solidity layout for struct[1]"
1281 );
1282
1283 let slot2_addr = data_start + U256::from(2);
1285 let slot2_value = U256::handle(slot2_addr, LayoutCtx::FULL, address)
1286 .read()
1287 .unwrap();
1288 let expected_slot2 = gen_word_from(&[
1289 "0x012c", "0x01", "0x01", ]);
1293 assert_eq!(
1294 slot2_value, expected_slot2,
1295 "Slot 2 should match Solidity layout for struct[2]"
1296 );
1297
1298 let loaded: Vec<SmallStruct> = vec_slot.read().unwrap();
1300 assert_eq!(loaded, data, "Vec<SmallStruct> roundtrip failed");
1301 });
1302 }
1303
1304 #[test]
1305 fn test_vec_length_slot_isolation() {
1306 let (mut storage, address) = setup_storage();
1307
1308 StorageCtx::enter(&mut storage, || {
1309 let len_slot = U256::from(2600);
1310
1311 let data = vec![100u8, 200, 250];
1313 let mut vec_slot = Slot::<Vec<u8>>::new(len_slot, address);
1314 vec_slot.write(data.clone()).unwrap();
1315
1316 let length_value = U256::handle(len_slot, LayoutCtx::FULL, address)
1318 .read()
1319 .unwrap();
1320 assert_eq!(length_value, U256::from(3), "Length slot incorrect");
1321
1322 let data_start = calc_data_slot(len_slot);
1324 assert_ne!(
1325 data_start,
1326 len_slot + U256::ONE,
1327 "Data should not start immediately after base slot"
1328 );
1329
1330 let data_slot_value = U256::handle(data_start, LayoutCtx::FULL, address)
1332 .read()
1333 .unwrap();
1334
1335 let expected = gen_word_from(&[
1336 "0xfa", "0xc8", "0x64", ]);
1340 assert_eq!(
1341 data_slot_value, expected,
1342 "Data slot should match Solidity byte layout"
1343 );
1344
1345 for (i, &expected) in data.iter().enumerate() {
1347 let offset = i; let actual =
1349 Slot::<u8>::new_with_ctx(data_start, LayoutCtx::packed(offset), address)
1350 .read()
1351 .unwrap();
1352 assert_eq!(actual, expected, "mismatch: elem[{i}] at offset {offset}");
1353 }
1354 });
1355 }
1356
1357 #[test]
1358 fn test_vec_overwrite_cleanup() {
1359 let (mut storage, address) = setup_storage();
1360
1361 StorageCtx::enter(&mut storage, || {
1362 let len_slot = U256::from(2700);
1363 let mut vec_slot = Slot::<Vec<u8>>::new(len_slot, address);
1364
1365 let data_long = vec![1u8, 2, 3, 4, 5];
1367 vec_slot.write(data_long).unwrap();
1368
1369 let data_start = calc_data_slot(len_slot);
1370
1371 let slot0_before = U256::handle(data_start, LayoutCtx::FULL, address)
1373 .read()
1374 .unwrap();
1375 assert_ne!(slot0_before, U256::ZERO, "Initial data should be stored");
1376
1377 let data_short = vec![10u8, 20, 30];
1379 vec_slot.write(data_short.clone()).unwrap();
1380
1381 let length_value = U256::handle(len_slot, LayoutCtx::FULL, address)
1383 .read()
1384 .unwrap();
1385 assert_eq!(length_value, U256::from(3), "Length should be updated");
1386
1387 for (i, &expected) in data_short.iter().enumerate() {
1389 let offset = i; let actual =
1391 Slot::<u8>::new_with_ctx(data_start, LayoutCtx::packed(offset), address)
1392 .read()
1393 .unwrap();
1394 assert_eq!(
1395 actual, expected,
1396 "mismatch: new_elem[{i}] at offset {offset}"
1397 );
1398 }
1399
1400 let loaded: Vec<u8> = vec_slot.read().unwrap();
1401 assert_eq!(loaded, data_short, "Loaded vec should match short version");
1402 assert_eq!(loaded.len(), 3, "Length should be 3");
1403
1404 vec_slot.delete().unwrap();
1406 vec_slot.write(data_short.clone()).unwrap();
1407
1408 let slot0_after_delete = U256::handle(data_start, LayoutCtx::FULL, address)
1410 .read()
1411 .unwrap();
1412
1413 let expected = gen_word_from(&[
1414 "0x1e", "0x14", "0x0a", ]);
1418 assert_eq!(
1419 slot0_after_delete, expected,
1420 "Slot should match Solidity byte layout after delete+store"
1421 );
1422
1423 for (i, &expected) in data_short.iter().enumerate() {
1425 let offset = i; let actual =
1427 Slot::<u8>::new_with_ctx(data_start, LayoutCtx::packed(offset), address)
1428 .read()
1429 .unwrap();
1430 assert_eq!(actual, expected, "mismatch: elem[{i}] at offset {offset}");
1431 }
1432 });
1433 }
1434
1435 #[test]
1464 fn test_vec_handler_read_write() {
1465 let (mut storage, address) = setup_storage();
1466
1467 StorageCtx::enter(&mut storage, || {
1468 let len_slot = U256::random();
1469 let mut handler = VecHandler::<U256>::new(len_slot, address);
1470
1471 let data = vec![U256::random(), U256::random(), U256::random()];
1473 handler.write(data.clone()).unwrap();
1474
1475 let loaded = handler.read().unwrap();
1476 assert_eq!(loaded, data, "Vec read/write roundtrip failed");
1477 });
1478 }
1479
1480 #[test]
1481 fn test_vec_handler_delete() {
1482 let (mut storage, address) = setup_storage();
1483
1484 StorageCtx::enter(&mut storage, || {
1485 let len_slot = U256::random();
1486 let mut handler = VecHandler::<u8>::new(len_slot, address);
1487
1488 handler.write(vec![1, 2, 3, 4, 5]).unwrap();
1490 assert_eq!(handler.read().unwrap().len(), 5);
1491
1492 handler.delete().unwrap();
1494
1495 let loaded = handler.read().unwrap();
1497 assert!(loaded.is_empty(), "Vec should be empty after delete");
1498
1499 let length = U256::handle(len_slot, LayoutCtx::FULL, address)
1501 .read()
1502 .unwrap();
1503 assert_eq!(length, U256::ZERO, "Length slot should be zero");
1504 });
1505 }
1506
1507 #[test]
1508 fn test_vec_handler_at_read_write() {
1509 let (mut storage, address) = setup_storage();
1510
1511 StorageCtx::enter(&mut storage, || {
1512 let len_slot = U256::random();
1513 let mut handler = VecHandler::<U256>::new(len_slot, address);
1514
1515 let data = vec![U256::from(10), U256::from(20), U256::from(30)];
1517 let mut vec_slot = Slot::<Vec<U256>>::new(len_slot, address);
1518 vec_slot.write(data).unwrap();
1519
1520 let elem0 = handler[0].read().unwrap();
1522 let elem1 = handler[1].read().unwrap();
1523 let elem2 = handler[2].read().unwrap();
1524
1525 assert_eq!(elem0, U256::from(10));
1526 assert_eq!(elem1, U256::from(20));
1527 assert_eq!(elem2, U256::from(30));
1528
1529 handler[1].write(U256::from(99)).unwrap();
1531
1532 let updated = handler.read().unwrap();
1534 assert_eq!(
1535 updated,
1536 vec![U256::from(10), U256::from(99), U256::from(30)]
1537 );
1538 });
1539 }
1540
1541 #[test]
1542 fn test_vec_handler_push_pop() {
1543 let (mut storage, address) = setup_storage();
1544
1545 StorageCtx::enter(&mut storage, || {
1546 let len_slot = U256::random();
1547 let handler = VecHandler::<U256>::new(len_slot, address);
1548
1549 let val1 = U256::random();
1550 let val2 = U256::random();
1551 let val3 = U256::random();
1552
1553 handler.push(val1).unwrap();
1555 handler.push(val2).unwrap();
1556 handler.push(val3).unwrap();
1557
1558 assert_eq!(handler.len().unwrap(), 3);
1559
1560 assert_eq!(handler.pop().unwrap(), Some(val3));
1562 assert_eq!(handler.pop().unwrap(), Some(val2));
1563 assert_eq!(handler.pop().unwrap(), Some(val1));
1564 assert_eq!(handler.pop().unwrap(), None);
1565
1566 assert_eq!(handler.len().unwrap(), 0);
1567 });
1568 }
1569
1570 #[test]
1571 fn test_vec_handler_len() {
1572 let (mut storage, address) = setup_storage();
1573
1574 StorageCtx::enter(&mut storage, || {
1575 let len_slot = U256::random();
1576 let handler = VecHandler::<Address>::new(len_slot, address);
1577
1578 assert_eq!(handler.len().unwrap(), 0);
1580
1581 handler.push(Address::random()).unwrap();
1583 assert_eq!(handler.len().unwrap(), 1);
1584
1585 handler.push(Address::random()).unwrap();
1586 assert_eq!(handler.len().unwrap(), 2);
1587
1588 handler.push(Address::random()).unwrap();
1589 assert_eq!(handler.len().unwrap(), 3);
1590
1591 handler.pop().unwrap();
1593 assert_eq!(handler.len().unwrap(), 2);
1594 });
1595 }
1596
1597 #[test]
1598 fn test_vec_handler_push_pop_packed_types() {
1599 let (mut storage, address) = setup_storage();
1600
1601 StorageCtx::enter(&mut storage, || {
1602 let len_slot = U256::random();
1603 let handler = VecHandler::<u8>::new(len_slot, address);
1604
1605 for i in 0..35 {
1607 handler.push(i as u8).unwrap();
1608 }
1609
1610 assert_eq!(handler.len().unwrap(), 35);
1611
1612 for i in 0..35 {
1614 let val = handler[i].read().unwrap();
1615 assert_eq!(val, i as u8);
1616 }
1617
1618 for i in (0..35).rev() {
1620 let popped = handler.pop().unwrap();
1621 assert_eq!(popped, Some(i as u8));
1622 }
1623
1624 assert_eq!(handler.len().unwrap(), 0);
1625 });
1626 }
1627
1628 #[test]
1629 fn test_vec_handler_at_oob_check() -> eyre::Result<()> {
1630 let (mut storage, address) = setup_storage();
1631
1632 StorageCtx::enter(&mut storage, || {
1633 let len_slot = U256::random();
1634 let handler = VecHandler::<U256>::new(len_slot, address);
1635
1636 assert!(handler.at(0)?.is_none());
1638
1639 handler.push(U256::from(10))?;
1641 handler.push(U256::from(20))?;
1642
1643 assert!(handler.at(0)?.is_some());
1645 assert!(handler.at(1)?.is_some());
1646 assert_eq!(handler.at(0)?.unwrap().read()?, U256::from(10));
1647 assert_eq!(handler.at(1)?.unwrap().read()?, U256::from(20));
1648
1649 assert!(handler.at(3)?.is_none());
1651
1652 Ok(())
1653 })
1654 }
1655
1656 #[test]
1659 fn test_vec_length_overflow() -> eyre::Result<()> {
1660 let (mut storage, address) = setup_storage();
1661
1662 StorageCtx::enter(&mut storage, || {
1663 let mut len_slot = Slot::<U256>::new(U256::ZERO, address);
1664 let handler = VecHandler::<u32>::new(U256::ZERO, address);
1665
1666 len_slot.write(U256::from(0x0004000000000000u64))?;
1668 assert_eq!(handler.len(), Err(TempoPrecompileError::under_overflow()));
1669
1670 len_slot.write(U256::from(u32::MAX))?;
1672 assert_eq!(handler.len()?, u32::MAX as usize);
1673
1674 len_slot.write(U256::from(u64::from(u32::MAX) + 1))?;
1676 assert_eq!(handler.len(), Err(TempoPrecompileError::under_overflow()));
1677
1678 len_slot.write(U256::from(100_000u64))?;
1680 assert_eq!(handler.len()?, 100_000);
1681
1682 Ok(())
1683 })
1684 }
1685
1686 #[test]
1687 fn test_vec_push_at_max_index() -> eyre::Result<()> {
1688 let (mut storage, address) = setup_storage();
1689
1690 StorageCtx::enter(&mut storage, || {
1691 let mut len_slot = Slot::<U256>::new(U256::ZERO, address);
1692
1693 let handler = VecHandler::<u32>::new(U256::ZERO, address);
1695 let max_index = u32::MAX as usize / u32::BYTES;
1696
1697 len_slot.write(U256::from(max_index - 1))?;
1698 handler.push(1)?;
1699 assert_eq!(handler.len()?, max_index);
1700
1701 let elem = handler.at(max_index - 1)?;
1702 assert_eq!(elem.map(|e| e.read()).transpose()?, Some(1));
1703
1704 assert!(handler.push(1).is_err());
1705
1706 let handler = VecHandler::<U256>::new(U256::ZERO, address);
1708 let max_index = u32::MAX as usize;
1709 let value = U256::random();
1710
1711 len_slot.write(U256::from(max_index - 1))?;
1712 handler.push(value)?;
1713 assert_eq!(handler.len()?, max_index);
1714
1715 let elem = handler.at(max_index - 1)?;
1716 assert_eq!(elem.map(|e| e.read()).transpose()?, Some(value));
1717 assert!(handler.push(value).is_err());
1718
1719 Ok(())
1720 })
1721 }
1722
1723 prop_compose! {
1726 fn arb_u8_vec(max_len: usize) (vec in prop::collection::vec(any::<u8>(), 0..=max_len)) -> Vec<u8> {
1727 vec
1728 }
1729 }
1730
1731 prop_compose! {
1732 fn arb_u16_vec(max_len: usize) (vec in prop::collection::vec(any::<u16>(), 0..=max_len)) -> Vec<u16> {
1733 vec
1734 }
1735 }
1736
1737 prop_compose! {
1738 fn arb_u32_vec(max_len: usize) (vec in prop::collection::vec(any::<u32>(), 0..=max_len)) -> Vec<u32> {
1739 vec
1740 }
1741 }
1742
1743 prop_compose! {
1744 fn arb_u64_vec(max_len: usize) (vec in prop::collection::vec(any::<u64>(), 0..=max_len)) -> Vec<u64> {
1745 vec
1746 }
1747 }
1748
1749 prop_compose! {
1750 fn arb_u128_vec(max_len: usize) (vec in prop::collection::vec(any::<u128>(), 0..=max_len)) -> Vec<u128> {
1751 vec
1752 }
1753 }
1754
1755 prop_compose! {
1756 fn arb_u256_vec(max_len: usize) (vec in prop::collection::vec(any::<u64>(), 0..=max_len)) -> Vec<U256> {
1757 vec.into_iter().map(U256::from).collect()
1758 }
1759 }
1760
1761 prop_compose! {
1762 fn arb_address_vec(max_len: usize) (vec in prop::collection::vec(any::<[u8; 20]>(), 0..=max_len)) -> Vec<Address> {
1763 vec.into_iter().map(Address::from).collect()
1764 }
1765 }
1766
1767 prop_compose! {
1768 fn arb_test_struct() (a in any::<u64>(), b in any::<u64>()) -> TestStruct {
1769 TestStruct {
1770 a: u128::from(a),
1771 b: u128::from(b),
1772 }
1773 }
1774 }
1775
1776 prop_compose! {
1777 fn arb_test_struct_vec(max_len: usize)
1778 (vec in prop::collection::vec(arb_test_struct(), 0..=max_len))
1779 -> Vec<TestStruct> {
1780 vec
1781 }
1782 }
1783
1784 proptest! {
1787 #![proptest_config(ProptestConfig::with_cases(500))]
1788 #[test]
1789 fn proptest_vec_u8_roundtrip(data in arb_u8_vec(100), len_slot in arb_safe_slot()) {
1790 let (mut storage, address) = setup_storage();
1791
1792 StorageCtx::enter(&mut storage, || {
1793 let data_len = data.len();
1794 let mut vec_slot = Slot::<Vec<u8>>::new(len_slot, address);
1795
1796 vec_slot.write(data.clone())?;
1798 let loaded: Vec<u8> = vec_slot.read()?;
1799 prop_assert_eq!(&loaded, &data, "Vec<u8> roundtrip failed");
1800
1801 vec_slot.delete()?;
1803 let after_delete: Vec<u8> = vec_slot.read()?;
1804 prop_assert!(after_delete.is_empty(), "Vec not empty after delete");
1805
1806 if data_len > 0 {
1808 let data_start = calc_data_slot(len_slot);
1809 let byte_count = u8::BYTES;
1810 let slot_count = calc_packed_slot_count(data_len, byte_count);
1811
1812 for i in 0..slot_count {
1813 let slot_value = U256::handle(data_start + U256::from(i), LayoutCtx::FULL, address).read()?;
1814 prop_assert_eq!(slot_value, U256::ZERO, "Data slot {} not cleared", i);
1815 }
1816 }
1817
1818 Ok(())
1819 }).unwrap();
1820 }
1821
1822 #[test]
1823 fn proptest_vec_u16_roundtrip(data in arb_u16_vec(100), len_slot in arb_safe_slot()) {
1824 let (mut storage, address) = setup_storage();
1825
1826 StorageCtx::enter(&mut storage, || {
1827 let data_len = data.len();
1828 let mut vec_slot = Slot::<Vec<u16>>::new(len_slot, address);
1829
1830 vec_slot.write(data.clone())?;
1832 let loaded: Vec<u16> = vec_slot.read()?;
1833 prop_assert_eq!(&loaded, &data, "Vec<u16> roundtrip failed");
1834
1835 vec_slot.delete()?;
1837 let after_delete: Vec<u16> = vec_slot.read()?;
1838 prop_assert!(after_delete.is_empty(), "Vec not empty after delete");
1839
1840 if data_len > 0 {
1842 let data_start = calc_data_slot(len_slot);
1843 let byte_count = u16::BYTES;
1844 let slot_count = calc_packed_slot_count(data_len, byte_count);
1845
1846 for i in 0..slot_count {
1847 let slot_value = U256::handle(data_start + U256::from(i), LayoutCtx::FULL, address).read()?;
1848 prop_assert_eq!(slot_value, U256::ZERO, "Data slot {} not cleared", i);
1849 }
1850 }
1851
1852 Ok(())
1853 }).unwrap();
1854 }
1855
1856 #[test]
1857 fn proptest_vec_u32_roundtrip(data in arb_u32_vec(100), len_slot in arb_safe_slot()) {
1858 let (mut storage, address) = setup_storage();
1859
1860 StorageCtx::enter(&mut storage, || {
1861 let data_len = data.len();
1862 let mut vec_slot = Slot::<Vec<u32>>::new(len_slot, address);
1863
1864 vec_slot.write(data.clone())?;
1866 let loaded: Vec<u32> = vec_slot.read()?;
1867 prop_assert_eq!(&loaded, &data, "Vec<u32> roundtrip failed");
1868
1869 vec_slot.delete()?;
1871 let after_delete: Vec<u32> = vec_slot.read()?;
1872 prop_assert!(after_delete.is_empty(), "Vec not empty after delete");
1873
1874 if data_len > 0 {
1876 let data_start = calc_data_slot(len_slot);
1877 let byte_count = u32::BYTES;
1878 let slot_count = calc_packed_slot_count(data_len, byte_count);
1879
1880 for i in 0..slot_count {
1881 let slot_value = U256::handle(data_start + U256::from(i), LayoutCtx::FULL, address).read()?;
1882 prop_assert_eq!(slot_value, U256::ZERO, "Data slot {} not cleared", i);
1883 }
1884 }
1885
1886 Ok(())
1887 }).unwrap();
1888 }
1889
1890 #[test]
1891 fn proptest_vec_u64_roundtrip(data in arb_u64_vec(100), len_slot in arb_safe_slot()) {
1892 let (mut storage, address) = setup_storage();
1893
1894 StorageCtx::enter(&mut storage, || {
1895 let data_len = data.len();
1896 let mut vec_slot = Slot::<Vec<u64>>::new(len_slot, address);
1897
1898 vec_slot.write(data.clone())?;
1900 let loaded: Vec<u64> = vec_slot.read()?;
1901 prop_assert_eq!(&loaded, &data, "Vec<u64> roundtrip failed");
1902
1903 vec_slot.delete()?;
1905 let after_delete: Vec<u64> = vec_slot.read()?;
1906 prop_assert!(after_delete.is_empty(), "Vec not empty after delete");
1907
1908 if data_len > 0 {
1910 let data_start = calc_data_slot(len_slot);
1911 let byte_count = u64::BYTES;
1912 let slot_count = calc_packed_slot_count(data_len, byte_count);
1913
1914 for i in 0..slot_count {
1915 let slot_value = U256::handle(data_start + U256::from(i), LayoutCtx::FULL, address).read()?;
1916 prop_assert_eq!(slot_value, U256::ZERO, "Data slot {} not cleared", i);
1917 }
1918 }
1919
1920 Ok(())
1921 }).unwrap();
1922 }
1923
1924 #[test]
1925 fn proptest_vec_u128_roundtrip(data in arb_u128_vec(50), len_slot in arb_safe_slot()) {
1926 let (mut storage, address) = setup_storage();
1927
1928 StorageCtx::enter(&mut storage, || {
1929 let data_len = data.len();
1930 let mut vec_slot = Slot::<Vec<u128>>::new(len_slot, address);
1931
1932 vec_slot.write(data.clone())?;
1934 let loaded: Vec<u128> = vec_slot.read()?;
1935 prop_assert_eq!(&loaded, &data, "Vec<u128> roundtrip failed");
1936
1937 vec_slot.delete()?;
1939 let after_delete: Vec<u128> = vec_slot.read()?;
1940 prop_assert!(after_delete.is_empty(), "Vec not empty after delete");
1941
1942 if data_len > 0 {
1944 let data_start = calc_data_slot(len_slot);
1945 let byte_count = u128::BYTES;
1946 let slot_count = calc_packed_slot_count(data_len, byte_count);
1947
1948 for i in 0..slot_count {
1949 let slot_value = U256::handle(data_start + U256::from(i), LayoutCtx::FULL, address).read()?;
1950 prop_assert_eq!(slot_value, U256::ZERO, "Data slot {} not cleared", i);
1951 }
1952 }
1953
1954 Ok(())
1955 }).unwrap();
1956 }
1957
1958 #[test]
1959 fn proptest_vec_u256_roundtrip(data in arb_u256_vec(50), len_slot in arb_safe_slot()) {
1960 let (mut storage, address) = setup_storage();
1961
1962 StorageCtx::enter(&mut storage, || {
1963 let data_len = data.len();
1964 let mut vec_slot = Slot::<Vec<U256>>::new(len_slot, address);
1965
1966 vec_slot.write(data.clone())?;
1968 let loaded: Vec<U256> = vec_slot.read()?;
1969 prop_assert_eq!(&loaded, &data, "Vec<U256> roundtrip failed");
1970
1971 vec_slot.delete()?;
1973 let after_delete: Vec<U256> = vec_slot.read()?;
1974 prop_assert!(after_delete.is_empty(), "Vec not empty after delete");
1975
1976 if data_len > 0 {
1978 let data_start = calc_data_slot(len_slot);
1979
1980 for i in 0..data_len {
1981 let slot_value = U256::handle(data_start + U256::from(i), LayoutCtx::FULL, address).read()?;
1982 prop_assert_eq!(slot_value, U256::ZERO, "Data slot {} not cleared", i);
1983 }
1984 }
1985
1986 Ok(())
1987 }).unwrap();
1988 }
1989
1990 #[test]
1991 fn proptest_vec_address_roundtrip(data in arb_address_vec(50), len_slot in arb_safe_slot()) {
1992 let (mut storage, address) = setup_storage();
1993
1994 StorageCtx::enter(&mut storage, || {
1995 let data_len = data.len();
1996 let mut vec_slot = Slot::<Vec<Address>>::new(len_slot, address);
1997
1998 vec_slot.write(data.clone())?;
2000 let loaded: Vec<Address> = vec_slot.read()?;
2001 prop_assert_eq!(&loaded, &data, "Vec<Address> roundtrip failed");
2002
2003 vec_slot.delete()?;
2005 let after_delete: Vec<Address> = vec_slot.read()?;
2006 prop_assert!(after_delete.is_empty(), "Vec not empty after delete");
2007
2008 if data_len > 0 {
2011 let data_start = calc_data_slot(len_slot);
2012
2013 for i in 0..data_len {
2014 let slot_value = U256::handle(data_start + U256::from(i), LayoutCtx::FULL, address).read()?;
2015 prop_assert_eq!(slot_value, U256::ZERO, "Data slot {} not cleared", i);
2016 }
2017 }
2018
2019 Ok(())
2020 }).unwrap();
2021 }
2022
2023 #[test]
2024 fn proptest_vec_delete(data in arb_u8_vec(100), len_slot in arb_safe_slot()) {
2025 let (mut storage, address) = setup_storage();
2026
2027 StorageCtx::enter(&mut storage, || {
2028 let mut vec_slot = Slot::<Vec<u8>>::new(len_slot, address);
2029
2030 vec_slot.write(data.clone())?;
2032
2033 vec_slot.delete()?;
2035
2036 let loaded: Vec<u8> = vec_slot.read()?;
2038 prop_assert!(loaded.is_empty(), "Vec not empty after delete");
2039
2040 if !data.is_empty() {
2042 let data_start = calc_data_slot(len_slot);
2043 let byte_count = u8::BYTES;
2044 let slot_count = calc_packed_slot_count(data.len(), byte_count);
2045
2046 for i in 0..slot_count {
2047 let slot_value = U256::handle(data_start + U256::from(i), LayoutCtx::FULL, address).read()?;
2048 prop_assert_eq!(slot_value, U256::ZERO, "Data slot {} not cleared", i);
2049 }
2050 }
2051
2052 Ok(())
2053 }).unwrap();
2054 }
2055
2056 #[test]
2057 fn proptest_vec_struct_roundtrip(data in arb_test_struct_vec(50), len_slot in arb_safe_slot()) {
2058 let (mut storage, address) = setup_storage();
2059
2060 StorageCtx::enter(&mut storage, || {
2061 let data_len = data.len();
2062 let mut vec_slot = Slot::<Vec<TestStruct>>::new(len_slot, address);
2063
2064 vec_slot.write(data.clone())?;
2066 let loaded: Vec<TestStruct> = vec_slot.read()?;
2067 prop_assert_eq!(&loaded, &data, "Vec<TestStruct> roundtrip failed");
2068
2069 vec_slot.delete()?;
2071 let after_delete: Vec<TestStruct> = vec_slot.read()?;
2072 prop_assert!(after_delete.is_empty(), "Vec not empty after delete");
2073
2074 if data_len > 0 {
2076 let data_start = calc_data_slot(len_slot);
2077
2078 for i in 0..data_len {
2079 let slot_value = U256::handle(data_start + U256::from(i), LayoutCtx::FULL, address).read()?;
2080 prop_assert_eq!(slot_value, U256::ZERO, "Data slot {} not cleared", i);
2081 }
2082 }
2083
2084 Ok(())
2085 }).unwrap();
2086 }
2087 }
2088}