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, 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_eq!(ctx, LayoutCtx::FULL, "Dynamic arrays cannot be packed");
46
47 let length_value = storage.load(len_slot)?;
49 let length = length_value.to::<usize>();
50
51 if length == 0 {
52 return Ok(Self::new());
53 }
54
55 let data_start = calc_data_slot(len_slot);
57 if T::BYTES <= 16 {
58 load_packed_elements(storage, data_start, length, T::BYTES)
59 } else {
60 load_unpacked_elements(storage, data_start, length)
61 }
62 }
63
64 fn store<S: StorageOps>(&self, storage: &mut S, len_slot: U256, ctx: LayoutCtx) -> Result<()> {
65 debug_assert_eq!(ctx, LayoutCtx::FULL, "Dynamic arrays cannot be packed");
66
67 storage.store(len_slot, U256::from(self.len()))?;
69
70 if self.is_empty() {
71 return Ok(());
72 }
73
74 let data_start = calc_data_slot(len_slot);
76 if T::BYTES <= 16 {
77 store_packed_elements(self, storage, data_start, T::BYTES)
78 } else {
79 store_unpacked_elements(self, storage, data_start)
80 }
81 }
82
83 fn delete<S: StorageOps>(storage: &mut S, len_slot: U256, ctx: LayoutCtx) -> Result<()> {
85 debug_assert_eq!(ctx, LayoutCtx::FULL, "Dynamic arrays cannot be packed");
86
87 let length_value = storage.load(len_slot)?;
89 let length = length_value.to::<usize>();
90
91 storage.store(len_slot, U256::ZERO)?;
93
94 if length == 0 {
95 return Ok(());
96 }
97
98 let data_start = calc_data_slot(len_slot);
99 if T::BYTES <= 16 {
100 let slot_count = calc_packed_slot_count(length, T::BYTES);
102 for slot_idx in 0..slot_count {
103 storage.store(data_start + U256::from(slot_idx), U256::ZERO)?;
104 }
105 } else {
106 for elem_idx in 0..length {
108 let elem_slot = data_start + U256::from(elem_idx * T::SLOTS);
109 T::delete(storage, elem_slot, LayoutCtx::FULL)?;
110 }
111 }
112
113 Ok(())
114 }
115}
116
117#[derive(Debug, Clone)]
151pub struct VecHandler<T: Storable> {
152 len_slot: U256,
153 address: Address,
154 cache: HandlerCache<usize, T::Handler>,
155}
156
157impl<T> Handler<Vec<T>> for VecHandler<T>
158where
159 T: Storable,
160{
161 #[inline]
163 fn read(&self) -> Result<Vec<T>> {
164 self.as_slot().read()
165 }
166
167 #[inline]
169 fn write(&mut self, value: Vec<T>) -> Result<()> {
170 self.as_slot().write(value)
171 }
172
173 #[inline]
175 fn delete(&mut self) -> Result<()> {
176 self.as_slot().delete()
177 }
178
179 #[inline]
181 fn t_read(&self) -> Result<Vec<T>> {
182 self.as_slot().t_read()
183 }
184
185 #[inline]
187 fn t_write(&mut self, value: Vec<T>) -> Result<()> {
188 self.as_slot().t_write(value)
189 }
190
191 #[inline]
193 fn t_delete(&mut self) -> Result<()> {
194 self.as_slot().t_delete()
195 }
196}
197
198impl<T> VecHandler<T>
199where
200 T: Storable,
201{
202 #[inline]
204 pub fn new(len_slot: U256, address: Address) -> Self {
205 Self {
206 len_slot,
207 address,
208 cache: HandlerCache::new(),
209 }
210 }
211
212 const fn max_index() -> usize {
214 if T::BYTES <= 16 {
215 u32::MAX as usize / T::BYTES
216 } else {
217 u32::MAX as usize / T::SLOTS
218 }
219 }
220
221 #[inline]
223 pub fn len_slot(&self) -> ::alloy::primitives::U256 {
224 self.len_slot
225 }
226
227 #[inline]
232 pub fn data_slot(&self) -> ::alloy::primitives::U256 {
233 calc_data_slot(self.len_slot)
234 }
235
236 #[inline]
238 fn as_slot(&self) -> Slot<Vec<T>> {
239 Slot::new(self.len_slot, self.address)
240 }
241
242 #[inline]
244 pub fn len(&self) -> Result<usize> {
245 let slot = Slot::<U256>::new(self.len_slot, self.address);
246 Ok(slot.read()?.to::<usize>())
247 }
248
249 #[inline]
251 pub fn is_empty(&self) -> Result<bool> {
252 Ok(self.len()? == 0)
253 }
254
255 #[inline]
256 fn compute_handler(data_start: U256, address: Address, index: usize) -> T::Handler {
257 let (slot, layout_ctx) = if T::BYTES <= 16 {
259 let location = calc_element_loc(index, T::BYTES);
260 (
261 data_start + U256::from(location.offset_slots),
262 LayoutCtx::packed(location.offset_bytes),
263 )
264 } else {
265 (data_start + U256::from(index * T::SLOTS), LayoutCtx::FULL)
266 };
267
268 T::handle(slot, layout_ctx, address)
269 }
270
271 pub fn at(&self, index: usize) -> Result<Option<&T::Handler>> {
280 if index >= self.len()? {
281 return Ok(None);
282 }
283
284 let (data_start, address) = (self.data_slot(), self.address);
285 Ok(Some(self.cache.get_or_insert(&index, || {
286 Self::compute_handler(data_start, address, index)
287 })))
288 }
289
290 #[inline]
296 pub fn push(&self, value: T) -> Result<()>
297 where
298 T: Storable,
299 T::Handler: Handler<T>,
300 {
301 let length = self.len()?;
303 if length >= Self::max_index() {
304 return Err(TempoPrecompileError::Fatal("Vec is at max capacity".into()));
305 }
306
307 let mut elem_slot = Self::compute_handler(self.data_slot(), self.address, length);
309 elem_slot.write(value)?;
310
311 let mut length_slot = Slot::<U256>::new(self.len_slot, self.address);
313 length_slot.write(U256::from(length + 1))
314 }
315
316 #[inline]
321 pub fn pop(&self) -> Result<Option<T>>
322 where
323 T: Storable,
324 T::Handler: Handler<T>,
325 {
326 let length = self.len()?;
328 if length == 0 {
329 return Ok(None);
330 }
331 let last_index = length - 1;
332
333 let mut elem_slot = Self::compute_handler(self.data_slot(), self.address, last_index);
335 let element = elem_slot.read()?;
336
337 elem_slot.delete()?;
339
340 let mut length_slot = Slot::<U256>::new(self.len_slot, self.address);
342 length_slot.write(U256::from(last_index))?;
343
344 Ok(Some(element))
345 }
346}
347
348impl<T> Index<usize> for VecHandler<T>
349where
350 T: Storable,
351{
352 type Output = T::Handler;
353
354 fn index(&self, index: usize) -> &Self::Output {
359 let (data_start, address) = (self.data_slot(), self.address);
360 self.cache
361 .get_or_insert(&index, || Self::compute_handler(data_start, address, index))
362 }
363}
364
365impl<T> IndexMut<usize> for VecHandler<T>
366where
367 T: Storable,
368{
369 fn index_mut(&mut self, index: usize) -> &mut Self::Output {
374 let (data_start, address) = (self.data_slot(), self.address);
375 self.cache
376 .get_or_insert_mut(&index, || Self::compute_handler(data_start, address, index))
377 }
378}
379
380#[inline]
384pub(crate) fn calc_data_slot(len_slot: U256) -> U256 {
385 U256::from_be_bytes(alloy::primitives::keccak256(len_slot.to_be_bytes::<32>()).0)
386}
387
388fn load_packed_elements<T, S>(
392 storage: &S,
393 data_start: U256,
394 length: usize,
395 byte_count: usize,
396) -> Result<Vec<T>>
397where
398 T: Storable,
399 S: StorageOps,
400{
401 debug_assert!(
402 T::BYTES <= 16,
403 "load_packed_elements requires T::BYTES <= 16"
404 );
405 let elements_per_slot = 32 / byte_count;
406 let slot_count = calc_packed_slot_count(length, byte_count);
407
408 let mut result = Vec::with_capacity(length);
409 let mut current_offset = 0;
410
411 for slot_idx in 0..slot_count {
412 let slot_addr = data_start + U256::from(slot_idx);
413 let slot_value = storage.load(slot_addr)?;
414 let slot_packed = PackedSlot(slot_value);
415
416 let elements_in_this_slot = if slot_idx == slot_count - 1 {
418 length - (slot_idx * elements_per_slot)
420 } else {
421 elements_per_slot
422 };
423
424 for _ in 0..elements_in_this_slot {
426 let elem = T::load(&slot_packed, slot_addr, LayoutCtx::packed(current_offset))?;
427 result.push(elem);
428
429 current_offset += byte_count;
431 if current_offset >= 32 {
432 current_offset = 0;
433 }
434 }
435
436 current_offset = 0;
438 }
439
440 Ok(result)
441}
442
443fn store_packed_elements<T, S>(
447 elements: &[T],
448 storage: &mut S,
449 data_start: U256,
450 byte_count: usize,
451) -> Result<()>
452where
453 T: Storable,
454 S: StorageOps,
455{
456 debug_assert!(
457 T::BYTES <= 16,
458 "store_packed_elements requires T::BYTES <= 16"
459 );
460 let elements_per_slot = 32 / byte_count;
461 let slot_count = calc_packed_slot_count(elements.len(), byte_count);
462
463 for slot_idx in 0..slot_count {
464 let slot_addr = data_start + U256::from(slot_idx);
465 let start_elem = slot_idx * elements_per_slot;
466 let end_elem = (start_elem + elements_per_slot).min(elements.len());
467
468 let slot_value = build_packed_slot(&elements[start_elem..end_elem], byte_count)?;
469 storage.store(slot_addr, slot_value)?;
470 }
471
472 Ok(())
473}
474
475fn build_packed_slot<T>(elements: &[T], byte_count: usize) -> Result<U256>
479where
480 T: Storable,
481{
482 debug_assert!(T::BYTES <= 16, "build_packed_slot requires T::BYTES <= 16");
483 let mut slot_value = PackedSlot(U256::ZERO);
484 let mut current_offset = 0;
485
486 for elem in elements {
487 elem.store(
488 &mut slot_value,
489 U256::ZERO,
490 LayoutCtx::packed(current_offset),
491 )?;
492 current_offset += byte_count;
493 }
494
495 Ok(slot_value.0)
496}
497
498fn load_unpacked_elements<T, S>(storage: &S, data_start: U256, length: usize) -> Result<Vec<T>>
503where
504 T: Storable,
505 S: StorageOps,
506{
507 let mut result = Vec::with_capacity(length);
508 for index in 0..length {
509 let elem_slot = data_start + U256::from(index * T::SLOTS);
511 let elem = T::load(storage, elem_slot, LayoutCtx::FULL)?;
512 result.push(elem);
513 }
514 Ok(result)
515}
516
517fn store_unpacked_elements<T, S>(elements: &[T], storage: &mut S, data_start: U256) -> Result<()>
521where
522 T: Storable,
523 S: StorageOps,
524{
525 for (elem_idx, elem) in elements.iter().enumerate() {
526 let elem_slot = data_start + U256::from(elem_idx * T::SLOTS);
528 elem.store(storage, elem_slot, LayoutCtx::FULL)?;
529 }
530
531 Ok(())
532}
533
534#[cfg(test)]
535mod tests {
536 use super::*;
537 use crate::{
538 storage::{Handler, StorageCtx},
539 test_util::{gen_word_from, setup_storage},
540 };
541 use alloy::primitives::Address;
542 use proptest::prelude::*;
543 use tempo_precompiles_macros::Storable;
544
545 fn arb_safe_slot() -> impl Strategy<Value = U256> {
549 any::<[u64; 4]>().prop_map(|limbs| {
550 U256::from_limbs(limbs) % (U256::MAX - U256::from(10000))
552 })
553 }
554
555 #[derive(Debug, Clone, PartialEq, Eq, Storable)]
557 struct TestStruct {
558 a: u128, b: u128, }
561
562 #[test]
566 fn test_vec_handler_slot_computation() {
567 let len_slot = U256::random();
568 let address = Address::random();
569 let handler = VecHandler::<u8>::new(len_slot, address);
570
571 assert_eq!(handler.len_slot, len_slot);
573
574 assert_eq!(*handler.address, *address);
576 }
577
578 #[test]
579 fn test_vec_data_slot_derivation() {
580 let len_slot = U256::random();
581
582 let data_slot = calc_data_slot(len_slot);
584 let expected =
585 U256::from_be_bytes(alloy::primitives::keccak256(len_slot.to_be_bytes::<32>()).0);
586
587 assert_eq!(
588 data_slot, expected,
589 "Data slot should be keccak256(len_slot)"
590 );
591 }
592
593 #[test]
594 fn test_vec_at_element_slot_packed() {
595 let len_slot = U256::random();
596 let address = Address::random();
597 let handler = VecHandler::<u8>::new(len_slot, address);
598
599 let data_start = calc_data_slot(len_slot);
600
601 let elem_slot = &handler[5];
604 let expected_loc = calc_element_loc(5, u8::BYTES);
605 assert_eq!(
606 elem_slot.slot(),
607 data_start + U256::from(expected_loc.offset_slots)
608 );
609 assert_eq!(elem_slot.offset(), Some(expected_loc.offset_bytes));
610
611 let elem_slot = &handler[35];
613 let expected_loc = calc_element_loc(35, u8::BYTES);
614 assert_eq!(
615 elem_slot.slot(),
616 data_start + U256::from(expected_loc.offset_slots)
617 );
618 assert_eq!(elem_slot.offset(), Some(expected_loc.offset_bytes));
619 }
620
621 #[test]
622 fn test_vec_at_element_slot_unpacked() {
623 let len_slot = U256::random();
624 let address = Address::random();
625 let handler = VecHandler::<U256>::new(len_slot, address);
626
627 let data_start = calc_data_slot(len_slot);
628
629 let elem_slot = &handler[0];
632 assert_eq!(elem_slot.slot(), data_start);
633 assert_eq!(elem_slot.offset(), None); let elem_slot = &handler[5];
637 assert_eq!(elem_slot.slot(), data_start + U256::from(5));
638 assert_eq!(elem_slot.offset(), None);
639 }
640
641 #[test]
642 fn test_vec_at_determinism() {
643 let len_slot = U256::random();
644 let address = Address::random();
645 let handler = VecHandler::<u16>::new(len_slot, address);
646
647 let slot1 = &handler[10];
649 let slot2 = &handler[10];
650
651 assert_eq!(
652 slot1.slot(),
653 slot2.slot(),
654 "Same index should produce same slot"
655 );
656 assert_eq!(
657 slot1.offset(),
658 slot2.offset(),
659 "Same index should produce same offset"
660 );
661 }
662
663 #[test]
664 fn test_vec_at_different_indices() {
665 let len_slot = U256::random();
666 let address = Address::random();
667 let handler = VecHandler::<u16>::new(len_slot, address);
668
669 let slot5 = &handler[5];
671 let slot10 = &handler[10];
672
673 assert_eq!(slot5.slot(), slot10.slot(), "Both should be in same slot");
677 assert_ne!(slot5.offset(), slot10.offset(), "But different offsets");
678
679 let slot16 = &handler[16];
681 assert_ne!(
682 slot5.slot(),
683 slot16.slot(),
684 "Different slot for index >= 16"
685 );
686 }
687
688 #[test]
691 fn test_vec_empty() {
692 let (mut storage, address) = setup_storage();
693
694 StorageCtx::enter(&mut storage, || {
695 let len_slot = U256::random();
696
697 let data: Vec<u8> = vec![];
698 let mut slot = Slot::<Vec<u8>>::new(len_slot, address);
699 slot.write(data.clone()).unwrap();
700
701 let loaded: Vec<u8> = slot.read().unwrap();
702 assert_eq!(loaded, data, "Empty vec roundtrip failed");
703 assert!(loaded.is_empty(), "Loaded vec should be empty");
704 });
705 }
706
707 #[test]
708 fn test_vec_nested() {
709 let (mut storage, address) = setup_storage();
710
711 StorageCtx::enter(&mut storage, || {
712 let len_slot = U256::random();
713
714 let data = vec![vec![1u8, 2, 3], vec![4, 5], vec![6, 7, 8, 9]];
716 let mut slot = Slot::<Vec<Vec<u8>>>::new(len_slot, address);
717 slot.write(data.clone()).unwrap();
718
719 let loaded: Vec<Vec<u8>> = slot.read().unwrap();
720 assert_eq!(loaded, data, "Nested Vec<Vec<u8>> roundtrip failed");
721 });
722 }
723
724 #[test]
725 fn test_vec_bool_packing() {
726 let (mut storage, address) = setup_storage();
727
728 StorageCtx::enter(&mut storage, || {
729 let len_slot = U256::random();
730 let mut slot = Slot::<Vec<bool>>::new(len_slot, address);
731
732 let data_exact: Vec<bool> = (0..32).map(|i| i % 2 == 0).collect();
734 slot.write(data_exact.clone()).unwrap();
735
736 let length_value = U256::handle(len_slot, LayoutCtx::FULL, address)
738 .read()
739 .unwrap();
740 assert_eq!(length_value, U256::from(32), "Length not stored correctly");
741
742 let loaded: Vec<bool> = slot.read().unwrap();
743 assert_eq!(
744 loaded, data_exact,
745 "Vec<bool> with 32 elements failed roundtrip"
746 );
747
748 let data_overflow: Vec<bool> = (0..35).map(|i| i % 3 == 0).collect();
750 slot.write(data_overflow.clone()).unwrap();
751
752 let loaded: Vec<bool> = slot.read().unwrap();
753 assert_eq!(
754 loaded, data_overflow,
755 "Vec<bool> with 35 elements failed roundtrip"
756 );
757 });
758 }
759
760 #[test]
763 fn test_vec_u8_explicit_slot_packing() {
764 let (mut storage, address) = setup_storage();
765
766 StorageCtx::enter(&mut storage, || {
767 let len_slot = U256::from(2000);
768 let data = vec![10u8, 20, 30, 40, 50];
769
770 <Vec<u8>>::handle(len_slot, LayoutCtx::FULL, address)
772 .write(data.clone())
773 .unwrap();
774
775 let length = U256::handle(len_slot, LayoutCtx::FULL, address)
777 .read()
778 .unwrap();
779 assert_eq!(
780 length,
781 U256::from(data.len()),
782 "Length not stored correctly"
783 );
784
785 let data_start = calc_data_slot(len_slot);
786 let slot_data = U256::handle(data_start, LayoutCtx::FULL, address)
787 .read()
788 .unwrap();
789
790 let expected = gen_word_from(&[
792 "0x32", "0x28", "0x1e", "0x14", "0x0a", ]);
798 assert_eq!(
799 slot_data, expected,
800 "Slot data should match Solidity byte layout"
801 );
802
803 for (i, &expected) in data.iter().enumerate() {
805 let offset = i; let actual =
807 Slot::<u8>::new_with_ctx(data_start, LayoutCtx::packed(offset), address)
808 .read()
809 .unwrap();
810 assert_eq!(actual, expected, "mismatch: elem[{i}] at offset {offset}");
811 }
812 });
813 }
814
815 #[test]
816 fn test_vec_u16_slot_boundary() {
817 let (mut storage, address) = setup_storage();
818
819 StorageCtx::enter(&mut storage, || {
820 let len_slot = U256::from(2100);
821 let mut vec_slot = Slot::<Vec<u16>>::new(len_slot, address);
822
823 let data_exact: Vec<u16> = (0..16).map(|i| i * 100).collect();
825 vec_slot.write(data_exact.clone()).unwrap();
826
827 let data_start = calc_data_slot(len_slot);
828 let slot0_value = U256::handle(data_start, LayoutCtx::FULL, address)
829 .read()
830 .unwrap();
831
832 let expected_slot0 = gen_word_from(&[
833 "0x05dc", "0x0578", "0x0514", "0x04b0", "0x044c", "0x03e8", "0x0384", "0x0320", "0x02bc", "0x0258", "0x01f4", "0x0190", "0x012c", "0x00c8", "0x0064", "0x0000", ]);
850 assert_eq!(
851 slot0_value, expected_slot0,
852 "Slot 0 should match Solidity byte layout"
853 );
854
855 for (i, &expected) in data_exact.iter().enumerate() {
857 let offset = i * u16::BYTES;
858 let actual =
859 Slot::<u16>::new_with_ctx(data_start, LayoutCtx::packed(offset), address)
860 .read()
861 .unwrap();
862 assert_eq!(actual, expected, "mismatch: elem[{i}] at offset {offset}");
863 }
864
865 let data_overflow: Vec<u16> = (0..17).map(|i| i * 100).collect();
867 vec_slot.write(data_overflow).unwrap();
868
869 let slot0_value = U256::handle(data_start, LayoutCtx::FULL, address)
871 .read()
872 .unwrap();
873 assert_eq!(
874 slot0_value, expected_slot0,
875 "Slot 0 should still match after overflow"
876 );
877
878 let slot1_addr = data_start + U256::ONE;
880 let slot1_value = U256::handle(slot1_addr, LayoutCtx::FULL, address)
881 .read()
882 .unwrap();
883
884 let expected_slot1 = gen_word_from(&[
885 "0x0640", ]);
887 assert_eq!(
888 slot1_value, expected_slot1,
889 "Slot 1 should match Solidity byte layout"
890 );
891
892 let actual = Slot::<u16>::new_with_ctx(slot1_addr, LayoutCtx::packed(0), address)
894 .read()
895 .unwrap();
896 assert_eq!(actual, 1600u16, "mismatch: slot1_elem[0] at offset 0");
897 });
898 }
899
900 #[test]
901 fn test_vec_u8_partial_slot_fill() {
902 let (mut storage, address) = setup_storage();
903
904 StorageCtx::enter(&mut storage, || {
905 let len_slot = U256::from(2200);
906
907 let data: Vec<u8> = (0..35).map(|i| (i + 1) as u8).collect();
911 let mut vec_slot = Slot::<Vec<u8>>::new(len_slot, address);
912 vec_slot.write(data).unwrap();
913 let data_start = calc_data_slot(len_slot);
914 let slot0_value = U256::handle(data_start, LayoutCtx::FULL, address)
915 .read()
916 .unwrap();
917
918 let expected_slot0 = gen_word_from(&[
919 "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", ]);
952 assert_eq!(
953 slot0_value, expected_slot0,
954 "Slot 0 should match Solidity byte layout"
955 );
956
957 let slot1_addr = data_start + U256::ONE;
959 let slot1_value = U256::handle(slot1_addr, LayoutCtx::FULL, address)
960 .read()
961 .unwrap();
962
963 let expected_slot1 = gen_word_from(&[
964 "0x23", "0x22", "0x21", ]);
968 assert_eq!(
969 slot1_value, expected_slot1,
970 "Slot 1 should match Solidity byte layout"
971 );
972
973 let slot1_data = [33u8, 34u8, 35u8];
975 for (i, &expected) in slot1_data.iter().enumerate() {
976 let offset = i; let actual =
978 Slot::<u8>::new_with_ctx(slot1_addr, LayoutCtx::packed(offset), address)
979 .read()
980 .unwrap();
981 assert_eq!(
982 actual, expected,
983 "mismatch: slot1_elem[{i}] at offset {offset}"
984 );
985 }
986 });
987 }
988
989 #[test]
990 fn test_vec_u256_individual_slots() {
991 let (mut storage, address) = setup_storage();
992
993 StorageCtx::enter(&mut storage, || {
994 let len_slot = U256::from(2300);
995
996 let data = vec![
998 U256::from(0x1111111111111111u64),
999 U256::from(0x2222222222222222u64),
1000 U256::from(0x3333333333333333u64),
1001 ];
1002 let mut vec_slot = Slot::<Vec<U256>>::new(len_slot, address);
1003 vec_slot.write(data.clone()).unwrap();
1004
1005 let data_start = calc_data_slot(len_slot);
1006
1007 for (i, &expected) in data.iter().enumerate() {
1009 let stored_value =
1010 U256::handle(data_start + U256::from(i), LayoutCtx::FULL, address)
1011 .read()
1012 .unwrap();
1013 assert_eq!(stored_value, expected, "incorrect U256 element {i}");
1014 }
1015
1016 let no_slot_value = U256::handle(data_start + U256::from(3), LayoutCtx::FULL, address)
1018 .read()
1019 .unwrap();
1020 assert_eq!(no_slot_value, U256::ZERO, "Slot 3 should be empty");
1021 });
1022 }
1023
1024 #[test]
1025 fn test_vec_address_unpacked_slots() {
1026 let (mut storage, address) = setup_storage();
1027
1028 StorageCtx::enter(&mut storage, || {
1029 let len_slot = U256::from(2400);
1030
1031 let data = vec![
1033 Address::repeat_byte(0xAA),
1034 Address::repeat_byte(0xBB),
1035 Address::repeat_byte(0xCC),
1036 ];
1037 let mut vec_slot = Slot::<Vec<Address>>::new(len_slot, address);
1038 vec_slot.write(data.clone()).unwrap();
1039
1040 let data_start = calc_data_slot(len_slot);
1041
1042 let slot0_value = U256::handle(data_start, LayoutCtx::FULL, address)
1044 .read()
1045 .unwrap();
1046 let expected_slot0 = gen_word_from(&["0xAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"]);
1047 assert_eq!(
1048 slot0_value, expected_slot0,
1049 "Slot 0 should match Solidity byte layout"
1050 );
1051
1052 let slot1_addr = data_start + U256::ONE;
1054 let slot1_value = U256::handle(slot1_addr, LayoutCtx::FULL, address)
1055 .read()
1056 .unwrap();
1057 let expected_slot1 = gen_word_from(&["0xBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB"]);
1058 assert_eq!(
1059 slot1_value, expected_slot1,
1060 "Slot 1 should match Solidity byte layout"
1061 );
1062
1063 let slot2_addr = data_start + U256::from(2);
1065 let slot2_value = U256::handle(slot2_addr, LayoutCtx::FULL, address)
1066 .read()
1067 .unwrap();
1068 let expected_slot2 = gen_word_from(&["0xCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC"]);
1069 assert_eq!(
1070 slot2_value, expected_slot2,
1071 "Slot 2 should match Solidity byte layout"
1072 );
1073
1074 for (i, &expected_addr) in data.iter().enumerate() {
1076 let slot_addr = data_start + U256::from(i);
1077 let stored_value = U256::handle(slot_addr, LayoutCtx::FULL, address)
1078 .read()
1079 .unwrap();
1080 let expected_u256 = U256::from_be_slice(expected_addr.as_slice());
1081 assert_eq!(
1082 stored_value, expected_u256,
1083 "Address element {i} should match"
1084 );
1085 }
1086 });
1087 }
1088
1089 #[test]
1090 fn test_vec_struct_slot_allocation() {
1091 let (mut storage, address) = setup_storage();
1092
1093 StorageCtx::enter(&mut storage, || {
1094 let len_slot = U256::from(2500);
1095
1096 let data = vec![
1099 TestStruct { a: 100, b: 1 },
1100 TestStruct { a: 200, b: 2 },
1101 TestStruct { a: 300, b: 3 },
1102 ];
1103 let mut vec_slot = Slot::<Vec<TestStruct>>::new(len_slot, address);
1104 vec_slot.write(data.clone()).unwrap();
1105
1106 let data_start = calc_data_slot(len_slot);
1107
1108 let slot0_value = U256::handle(data_start, LayoutCtx::FULL, address)
1112 .read()
1113 .unwrap();
1114 let expected_slot0 = gen_word_from(&[
1115 "0x00000000000000000000000000000001", "0x00000000000000000000000000000064", ]);
1118 assert_eq!(
1119 slot0_value, expected_slot0,
1120 "Slot 0 should match Solidity byte layout"
1121 );
1122
1123 let slot1_addr = data_start + U256::ONE;
1125 let slot1_value = U256::handle(slot1_addr, LayoutCtx::FULL, address)
1126 .read()
1127 .unwrap();
1128 let expected_slot1 = gen_word_from(&[
1129 "0x00000000000000000000000000000002", "0x000000000000000000000000000000C8", ]);
1132 assert_eq!(
1133 slot1_value, expected_slot1,
1134 "Slot 1 should match Solidity byte layout"
1135 );
1136
1137 let slot2_addr = data_start + U256::from(2);
1139 let slot2_value = U256::handle(slot2_addr, LayoutCtx::FULL, address)
1140 .read()
1141 .unwrap();
1142 let expected_slot2 = gen_word_from(&[
1143 "0x00000000000000000000000000000003", "0x0000000000000000000000000000012C", ]);
1146 assert_eq!(
1147 slot2_value, expected_slot2,
1148 "Slot 2 should match Solidity byte layout"
1149 );
1150
1151 let slot3_addr = data_start + U256::from(3);
1153 let slot3_value = U256::handle(slot3_addr, LayoutCtx::FULL, address)
1154 .read()
1155 .unwrap();
1156 assert_eq!(slot3_value, U256::ZERO, "Slot 3 should be empty");
1157
1158 for (i, expected_struct) in data.iter().enumerate() {
1160 let struct_slot_addr = data_start + U256::from(i);
1161 let struct_slot = Slot::<TestStruct>::new(struct_slot_addr, address);
1162 let loaded_struct = struct_slot.read().unwrap();
1163 assert_eq!(
1164 loaded_struct, *expected_struct,
1165 "TestStruct at slot {i} should match"
1166 );
1167 }
1168 });
1169 }
1170
1171 #[test]
1172 fn test_vec_small_struct_storage() {
1173 #[derive(Debug, Clone, PartialEq, Eq, Storable)]
1175 struct SmallStruct {
1176 flag1: bool, flag2: bool, value: u16, }
1180
1181 let (mut storage, address) = setup_storage();
1182
1183 StorageCtx::enter(&mut storage, || {
1184 let len_slot = U256::from(2550);
1185
1186 let data = vec![
1189 SmallStruct {
1190 flag1: true,
1191 flag2: false,
1192 value: 100,
1193 },
1194 SmallStruct {
1195 flag1: false,
1196 flag2: true,
1197 value: 200,
1198 },
1199 SmallStruct {
1200 flag1: true,
1201 flag2: true,
1202 value: 300,
1203 },
1204 ];
1205 let mut vec_slot = Slot::<Vec<SmallStruct>>::new(len_slot, address);
1206 vec_slot.write(data.clone()).unwrap();
1207
1208 let length_value = U256::handle(len_slot, LayoutCtx::FULL, address)
1210 .read()
1211 .unwrap();
1212 assert_eq!(length_value, U256::from(3), "Length not stored correctly");
1213
1214 let data_start = calc_data_slot(len_slot);
1215
1216 let slot0_value = U256::handle(data_start, LayoutCtx::FULL, address)
1218 .read()
1219 .unwrap();
1220 let expected_slot0 = gen_word_from(&[
1221 "0x0064", "0x00", "0x01", ]);
1225 assert_eq!(
1226 slot0_value, expected_slot0,
1227 "Slot 0 should match Solidity layout for struct[0]"
1228 );
1229
1230 let slot1_addr = data_start + U256::ONE;
1232 let slot1_value = U256::handle(slot1_addr, LayoutCtx::FULL, address)
1233 .read()
1234 .unwrap();
1235 let expected_slot1 = gen_word_from(&[
1236 "0x00c8", "0x01", "0x00", ]);
1240 assert_eq!(
1241 slot1_value, expected_slot1,
1242 "Slot 1 should match Solidity layout for struct[1]"
1243 );
1244
1245 let slot2_addr = data_start + U256::from(2);
1247 let slot2_value = U256::handle(slot2_addr, LayoutCtx::FULL, address)
1248 .read()
1249 .unwrap();
1250 let expected_slot2 = gen_word_from(&[
1251 "0x012c", "0x01", "0x01", ]);
1255 assert_eq!(
1256 slot2_value, expected_slot2,
1257 "Slot 2 should match Solidity layout for struct[2]"
1258 );
1259
1260 let loaded: Vec<SmallStruct> = vec_slot.read().unwrap();
1262 assert_eq!(loaded, data, "Vec<SmallStruct> roundtrip failed");
1263 });
1264 }
1265
1266 #[test]
1267 fn test_vec_length_slot_isolation() {
1268 let (mut storage, address) = setup_storage();
1269
1270 StorageCtx::enter(&mut storage, || {
1271 let len_slot = U256::from(2600);
1272
1273 let data = vec![100u8, 200, 250];
1275 let mut vec_slot = Slot::<Vec<u8>>::new(len_slot, address);
1276 vec_slot.write(data.clone()).unwrap();
1277
1278 let length_value = U256::handle(len_slot, LayoutCtx::FULL, address)
1280 .read()
1281 .unwrap();
1282 assert_eq!(length_value, U256::from(3), "Length slot incorrect");
1283
1284 let data_start = calc_data_slot(len_slot);
1286 assert_ne!(
1287 data_start,
1288 len_slot + U256::ONE,
1289 "Data should not start immediately after base slot"
1290 );
1291
1292 let data_slot_value = U256::handle(data_start, LayoutCtx::FULL, address)
1294 .read()
1295 .unwrap();
1296
1297 let expected = gen_word_from(&[
1298 "0xfa", "0xc8", "0x64", ]);
1302 assert_eq!(
1303 data_slot_value, expected,
1304 "Data slot should match Solidity byte layout"
1305 );
1306
1307 for (i, &expected) in data.iter().enumerate() {
1309 let offset = i; let actual =
1311 Slot::<u8>::new_with_ctx(data_start, LayoutCtx::packed(offset), address)
1312 .read()
1313 .unwrap();
1314 assert_eq!(actual, expected, "mismatch: elem[{i}] at offset {offset}");
1315 }
1316 });
1317 }
1318
1319 #[test]
1320 fn test_vec_overwrite_cleanup() {
1321 let (mut storage, address) = setup_storage();
1322
1323 StorageCtx::enter(&mut storage, || {
1324 let len_slot = U256::from(2700);
1325 let mut vec_slot = Slot::<Vec<u8>>::new(len_slot, address);
1326
1327 let data_long = vec![1u8, 2, 3, 4, 5];
1329 vec_slot.write(data_long).unwrap();
1330
1331 let data_start = calc_data_slot(len_slot);
1332
1333 let slot0_before = U256::handle(data_start, LayoutCtx::FULL, address)
1335 .read()
1336 .unwrap();
1337 assert_ne!(slot0_before, U256::ZERO, "Initial data should be stored");
1338
1339 let data_short = vec![10u8, 20, 30];
1341 vec_slot.write(data_short.clone()).unwrap();
1342
1343 let length_value = U256::handle(len_slot, LayoutCtx::FULL, address)
1345 .read()
1346 .unwrap();
1347 assert_eq!(length_value, U256::from(3), "Length should be updated");
1348
1349 for (i, &expected) in data_short.iter().enumerate() {
1351 let offset = i; let actual =
1353 Slot::<u8>::new_with_ctx(data_start, LayoutCtx::packed(offset), address)
1354 .read()
1355 .unwrap();
1356 assert_eq!(
1357 actual, expected,
1358 "mismatch: new_elem[{i}] at offset {offset}"
1359 );
1360 }
1361
1362 let loaded: Vec<u8> = vec_slot.read().unwrap();
1363 assert_eq!(loaded, data_short, "Loaded vec should match short version");
1364 assert_eq!(loaded.len(), 3, "Length should be 3");
1365
1366 vec_slot.delete().unwrap();
1368 vec_slot.write(data_short.clone()).unwrap();
1369
1370 let slot0_after_delete = U256::handle(data_start, LayoutCtx::FULL, address)
1372 .read()
1373 .unwrap();
1374
1375 let expected = gen_word_from(&[
1376 "0x1e", "0x14", "0x0a", ]);
1380 assert_eq!(
1381 slot0_after_delete, expected,
1382 "Slot should match Solidity byte layout after delete+store"
1383 );
1384
1385 for (i, &expected) in data_short.iter().enumerate() {
1387 let offset = i; let actual =
1389 Slot::<u8>::new_with_ctx(data_start, LayoutCtx::packed(offset), address)
1390 .read()
1391 .unwrap();
1392 assert_eq!(actual, expected, "mismatch: elem[{i}] at offset {offset}");
1393 }
1394 });
1395 }
1396
1397 #[test]
1426 fn test_vec_handler_read_write() {
1427 let (mut storage, address) = setup_storage();
1428
1429 StorageCtx::enter(&mut storage, || {
1430 let len_slot = U256::random();
1431 let mut handler = VecHandler::<U256>::new(len_slot, address);
1432
1433 let data = vec![U256::random(), U256::random(), U256::random()];
1435 handler.write(data.clone()).unwrap();
1436
1437 let loaded = handler.read().unwrap();
1438 assert_eq!(loaded, data, "Vec read/write roundtrip failed");
1439 });
1440 }
1441
1442 #[test]
1443 fn test_vec_handler_delete() {
1444 let (mut storage, address) = setup_storage();
1445
1446 StorageCtx::enter(&mut storage, || {
1447 let len_slot = U256::random();
1448 let mut handler = VecHandler::<u8>::new(len_slot, address);
1449
1450 handler.write(vec![1, 2, 3, 4, 5]).unwrap();
1452 assert_eq!(handler.read().unwrap().len(), 5);
1453
1454 handler.delete().unwrap();
1456
1457 let loaded = handler.read().unwrap();
1459 assert!(loaded.is_empty(), "Vec should be empty after delete");
1460
1461 let length = U256::handle(len_slot, LayoutCtx::FULL, address)
1463 .read()
1464 .unwrap();
1465 assert_eq!(length, U256::ZERO, "Length slot should be zero");
1466 });
1467 }
1468
1469 #[test]
1470 fn test_vec_handler_at_read_write() {
1471 let (mut storage, address) = setup_storage();
1472
1473 StorageCtx::enter(&mut storage, || {
1474 let len_slot = U256::random();
1475 let mut handler = VecHandler::<U256>::new(len_slot, address);
1476
1477 let data = vec![U256::from(10), U256::from(20), U256::from(30)];
1479 let mut vec_slot = Slot::<Vec<U256>>::new(len_slot, address);
1480 vec_slot.write(data).unwrap();
1481
1482 let elem0 = handler[0].read().unwrap();
1484 let elem1 = handler[1].read().unwrap();
1485 let elem2 = handler[2].read().unwrap();
1486
1487 assert_eq!(elem0, U256::from(10));
1488 assert_eq!(elem1, U256::from(20));
1489 assert_eq!(elem2, U256::from(30));
1490
1491 handler[1].write(U256::from(99)).unwrap();
1493
1494 let updated = handler.read().unwrap();
1496 assert_eq!(
1497 updated,
1498 vec![U256::from(10), U256::from(99), U256::from(30)]
1499 );
1500 });
1501 }
1502
1503 #[test]
1504 fn test_vec_handler_push_pop() {
1505 let (mut storage, address) = setup_storage();
1506
1507 StorageCtx::enter(&mut storage, || {
1508 let len_slot = U256::random();
1509 let handler = VecHandler::<U256>::new(len_slot, address);
1510
1511 let val1 = U256::random();
1512 let val2 = U256::random();
1513 let val3 = U256::random();
1514
1515 handler.push(val1).unwrap();
1517 handler.push(val2).unwrap();
1518 handler.push(val3).unwrap();
1519
1520 assert_eq!(handler.len().unwrap(), 3);
1521
1522 assert_eq!(handler.pop().unwrap(), Some(val3));
1524 assert_eq!(handler.pop().unwrap(), Some(val2));
1525 assert_eq!(handler.pop().unwrap(), Some(val1));
1526 assert_eq!(handler.pop().unwrap(), None);
1527
1528 assert_eq!(handler.len().unwrap(), 0);
1529 });
1530 }
1531
1532 #[test]
1533 fn test_vec_handler_len() {
1534 let (mut storage, address) = setup_storage();
1535
1536 StorageCtx::enter(&mut storage, || {
1537 let len_slot = U256::random();
1538 let handler = VecHandler::<Address>::new(len_slot, address);
1539
1540 assert_eq!(handler.len().unwrap(), 0);
1542
1543 handler.push(Address::random()).unwrap();
1545 assert_eq!(handler.len().unwrap(), 1);
1546
1547 handler.push(Address::random()).unwrap();
1548 assert_eq!(handler.len().unwrap(), 2);
1549
1550 handler.push(Address::random()).unwrap();
1551 assert_eq!(handler.len().unwrap(), 3);
1552
1553 handler.pop().unwrap();
1555 assert_eq!(handler.len().unwrap(), 2);
1556 });
1557 }
1558
1559 #[test]
1560 fn test_vec_handler_push_pop_packed_types() {
1561 let (mut storage, address) = setup_storage();
1562
1563 StorageCtx::enter(&mut storage, || {
1564 let len_slot = U256::random();
1565 let handler = VecHandler::<u8>::new(len_slot, address);
1566
1567 for i in 0..35 {
1569 handler.push(i as u8).unwrap();
1570 }
1571
1572 assert_eq!(handler.len().unwrap(), 35);
1573
1574 for i in 0..35 {
1576 let val = handler[i].read().unwrap();
1577 assert_eq!(val, i as u8);
1578 }
1579
1580 for i in (0..35).rev() {
1582 let popped = handler.pop().unwrap();
1583 assert_eq!(popped, Some(i as u8));
1584 }
1585
1586 assert_eq!(handler.len().unwrap(), 0);
1587 });
1588 }
1589
1590 #[test]
1591 fn test_vec_handler_at_oob_check() -> eyre::Result<()> {
1592 let (mut storage, address) = setup_storage();
1593
1594 StorageCtx::enter(&mut storage, || {
1595 let len_slot = U256::random();
1596 let handler = VecHandler::<U256>::new(len_slot, address);
1597
1598 assert!(handler.at(0)?.is_none());
1600
1601 handler.push(U256::from(10))?;
1603 handler.push(U256::from(20))?;
1604
1605 assert!(handler.at(0)?.is_some());
1607 assert!(handler.at(1)?.is_some());
1608 assert_eq!(handler.at(0)?.unwrap().read()?, U256::from(10));
1609 assert_eq!(handler.at(1)?.unwrap().read()?, U256::from(20));
1610
1611 assert!(handler.at(3)?.is_none());
1613
1614 Ok(())
1615 })
1616 }
1617
1618 #[test]
1619 fn test_vec_push_at_max_capacity() -> eyre::Result<()> {
1620 let (mut storage, address) = setup_storage();
1621
1622 StorageCtx::enter(&mut storage, || {
1623 let mut len_slot = Slot::<U256>::new(U256::ZERO, address);
1624
1625 let handler = VecHandler::<u32>::new(U256::ZERO, address);
1627 let max_index = u32::MAX as usize / u32::BYTES;
1628
1629 len_slot.write(U256::from(max_index - 1))?;
1631
1632 handler.push(1)?;
1634 assert_eq!(handler.len()?, max_index);
1635
1636 let elem = handler.at(max_index - 1)?;
1638 assert_eq!(elem.unwrap().read()?, 1);
1639
1640 let result = handler.push(1);
1642 assert!(result.is_err());
1643
1644 let handler = VecHandler::<U256>::new(U256::ZERO, address);
1646 let max_index = u32::MAX as usize;
1647 let value = U256::random();
1648
1649 len_slot.write(U256::from(max_index - 1))?;
1651
1652 handler.push(value)?;
1654 assert_eq!(handler.len()?, max_index);
1655
1656 let elem = handler.at(max_index - 1)?;
1658 assert!(elem.is_some());
1659 assert_eq!(elem.unwrap().read()?, value);
1660
1661 let result = handler.push(value);
1663 assert!(result.is_err());
1664
1665 Ok(())
1666 })
1667 }
1668
1669 prop_compose! {
1672 fn arb_u8_vec(max_len: usize) (vec in prop::collection::vec(any::<u8>(), 0..=max_len)) -> Vec<u8> {
1673 vec
1674 }
1675 }
1676
1677 prop_compose! {
1678 fn arb_u16_vec(max_len: usize) (vec in prop::collection::vec(any::<u16>(), 0..=max_len)) -> Vec<u16> {
1679 vec
1680 }
1681 }
1682
1683 prop_compose! {
1684 fn arb_u32_vec(max_len: usize) (vec in prop::collection::vec(any::<u32>(), 0..=max_len)) -> Vec<u32> {
1685 vec
1686 }
1687 }
1688
1689 prop_compose! {
1690 fn arb_u64_vec(max_len: usize) (vec in prop::collection::vec(any::<u64>(), 0..=max_len)) -> Vec<u64> {
1691 vec
1692 }
1693 }
1694
1695 prop_compose! {
1696 fn arb_u128_vec(max_len: usize) (vec in prop::collection::vec(any::<u128>(), 0..=max_len)) -> Vec<u128> {
1697 vec
1698 }
1699 }
1700
1701 prop_compose! {
1702 fn arb_u256_vec(max_len: usize) (vec in prop::collection::vec(any::<u64>(), 0..=max_len)) -> Vec<U256> {
1703 vec.into_iter().map(U256::from).collect()
1704 }
1705 }
1706
1707 prop_compose! {
1708 fn arb_address_vec(max_len: usize) (vec in prop::collection::vec(any::<[u8; 20]>(), 0..=max_len)) -> Vec<Address> {
1709 vec.into_iter().map(Address::from).collect()
1710 }
1711 }
1712
1713 prop_compose! {
1714 fn arb_test_struct() (a in any::<u64>(), b in any::<u64>()) -> TestStruct {
1715 TestStruct {
1716 a: a as u128,
1717 b: b as u128,
1718 }
1719 }
1720 }
1721
1722 prop_compose! {
1723 fn arb_test_struct_vec(max_len: usize)
1724 (vec in prop::collection::vec(arb_test_struct(), 0..=max_len))
1725 -> Vec<TestStruct> {
1726 vec
1727 }
1728 }
1729
1730 proptest! {
1733 #![proptest_config(ProptestConfig::with_cases(500))]
1734 #[test]
1735 fn proptest_vec_u8_roundtrip(data in arb_u8_vec(100), len_slot in arb_safe_slot()) {
1736 let (mut storage, address) = setup_storage();
1737
1738 StorageCtx::enter(&mut storage, || {
1739 let data_len = data.len();
1740 let mut vec_slot = Slot::<Vec<u8>>::new(len_slot, address);
1741
1742 vec_slot.write(data.clone())?;
1744 let loaded: Vec<u8> = vec_slot.read()?;
1745 prop_assert_eq!(&loaded, &data, "Vec<u8> roundtrip failed");
1746
1747 vec_slot.delete()?;
1749 let after_delete: Vec<u8> = vec_slot.read()?;
1750 prop_assert!(after_delete.is_empty(), "Vec not empty after delete");
1751
1752 if data_len > 0 {
1754 let data_start = calc_data_slot(len_slot);
1755 let byte_count = u8::BYTES;
1756 let slot_count = calc_packed_slot_count(data_len, byte_count);
1757
1758 for i in 0..slot_count {
1759 let slot_value = U256::handle(data_start + U256::from(i), LayoutCtx::FULL, address).read()?;
1760 prop_assert_eq!(slot_value, U256::ZERO, "Data slot {} not cleared", i);
1761 }
1762 }
1763
1764 Ok(())
1765 }).unwrap();
1766 }
1767
1768 #[test]
1769 fn proptest_vec_u16_roundtrip(data in arb_u16_vec(100), len_slot in arb_safe_slot()) {
1770 let (mut storage, address) = setup_storage();
1771
1772 StorageCtx::enter(&mut storage, || {
1773 let data_len = data.len();
1774 let mut vec_slot = Slot::<Vec<u16>>::new(len_slot, address);
1775
1776 vec_slot.write(data.clone())?;
1778 let loaded: Vec<u16> = vec_slot.read()?;
1779 prop_assert_eq!(&loaded, &data, "Vec<u16> roundtrip failed");
1780
1781 vec_slot.delete()?;
1783 let after_delete: Vec<u16> = vec_slot.read()?;
1784 prop_assert!(after_delete.is_empty(), "Vec not empty after delete");
1785
1786 if data_len > 0 {
1788 let data_start = calc_data_slot(len_slot);
1789 let byte_count = u16::BYTES;
1790 let slot_count = calc_packed_slot_count(data_len, byte_count);
1791
1792 for i in 0..slot_count {
1793 let slot_value = U256::handle(data_start + U256::from(i), LayoutCtx::FULL, address).read()?;
1794 prop_assert_eq!(slot_value, U256::ZERO, "Data slot {} not cleared", i);
1795 }
1796 }
1797
1798 Ok(())
1799 }).unwrap();
1800 }
1801
1802 #[test]
1803 fn proptest_vec_u32_roundtrip(data in arb_u32_vec(100), len_slot in arb_safe_slot()) {
1804 let (mut storage, address) = setup_storage();
1805
1806 StorageCtx::enter(&mut storage, || {
1807 let data_len = data.len();
1808 let mut vec_slot = Slot::<Vec<u32>>::new(len_slot, address);
1809
1810 vec_slot.write(data.clone())?;
1812 let loaded: Vec<u32> = vec_slot.read()?;
1813 prop_assert_eq!(&loaded, &data, "Vec<u32> roundtrip failed");
1814
1815 vec_slot.delete()?;
1817 let after_delete: Vec<u32> = vec_slot.read()?;
1818 prop_assert!(after_delete.is_empty(), "Vec not empty after delete");
1819
1820 if data_len > 0 {
1822 let data_start = calc_data_slot(len_slot);
1823 let byte_count = u32::BYTES;
1824 let slot_count = calc_packed_slot_count(data_len, byte_count);
1825
1826 for i in 0..slot_count {
1827 let slot_value = U256::handle(data_start + U256::from(i), LayoutCtx::FULL, address).read()?;
1828 prop_assert_eq!(slot_value, U256::ZERO, "Data slot {} not cleared", i);
1829 }
1830 }
1831
1832 Ok(())
1833 }).unwrap();
1834 }
1835
1836 #[test]
1837 fn proptest_vec_u64_roundtrip(data in arb_u64_vec(100), len_slot in arb_safe_slot()) {
1838 let (mut storage, address) = setup_storage();
1839
1840 StorageCtx::enter(&mut storage, || {
1841 let data_len = data.len();
1842 let mut vec_slot = Slot::<Vec<u64>>::new(len_slot, address);
1843
1844 vec_slot.write(data.clone())?;
1846 let loaded: Vec<u64> = vec_slot.read()?;
1847 prop_assert_eq!(&loaded, &data, "Vec<u64> roundtrip failed");
1848
1849 vec_slot.delete()?;
1851 let after_delete: Vec<u64> = vec_slot.read()?;
1852 prop_assert!(after_delete.is_empty(), "Vec not empty after delete");
1853
1854 if data_len > 0 {
1856 let data_start = calc_data_slot(len_slot);
1857 let byte_count = u64::BYTES;
1858 let slot_count = calc_packed_slot_count(data_len, byte_count);
1859
1860 for i in 0..slot_count {
1861 let slot_value = U256::handle(data_start + U256::from(i), LayoutCtx::FULL, address).read()?;
1862 prop_assert_eq!(slot_value, U256::ZERO, "Data slot {} not cleared", i);
1863 }
1864 }
1865
1866 Ok(())
1867 }).unwrap();
1868 }
1869
1870 #[test]
1871 fn proptest_vec_u128_roundtrip(data in arb_u128_vec(50), len_slot in arb_safe_slot()) {
1872 let (mut storage, address) = setup_storage();
1873
1874 StorageCtx::enter(&mut storage, || {
1875 let data_len = data.len();
1876 let mut vec_slot = Slot::<Vec<u128>>::new(len_slot, address);
1877
1878 vec_slot.write(data.clone())?;
1880 let loaded: Vec<u128> = vec_slot.read()?;
1881 prop_assert_eq!(&loaded, &data, "Vec<u128> roundtrip failed");
1882
1883 vec_slot.delete()?;
1885 let after_delete: Vec<u128> = vec_slot.read()?;
1886 prop_assert!(after_delete.is_empty(), "Vec not empty after delete");
1887
1888 if data_len > 0 {
1890 let data_start = calc_data_slot(len_slot);
1891 let byte_count = u128::BYTES;
1892 let slot_count = calc_packed_slot_count(data_len, byte_count);
1893
1894 for i in 0..slot_count {
1895 let slot_value = U256::handle(data_start + U256::from(i), LayoutCtx::FULL, address).read()?;
1896 prop_assert_eq!(slot_value, U256::ZERO, "Data slot {} not cleared", i);
1897 }
1898 }
1899
1900 Ok(())
1901 }).unwrap();
1902 }
1903
1904 #[test]
1905 fn proptest_vec_u256_roundtrip(data in arb_u256_vec(50), len_slot in arb_safe_slot()) {
1906 let (mut storage, address) = setup_storage();
1907
1908 StorageCtx::enter(&mut storage, || {
1909 let data_len = data.len();
1910 let mut vec_slot = Slot::<Vec<U256>>::new(len_slot, address);
1911
1912 vec_slot.write(data.clone())?;
1914 let loaded: Vec<U256> = vec_slot.read()?;
1915 prop_assert_eq!(&loaded, &data, "Vec<U256> roundtrip failed");
1916
1917 vec_slot.delete()?;
1919 let after_delete: Vec<U256> = vec_slot.read()?;
1920 prop_assert!(after_delete.is_empty(), "Vec not empty after delete");
1921
1922 if data_len > 0 {
1924 let data_start = calc_data_slot(len_slot);
1925
1926 for i in 0..data_len {
1927 let slot_value = U256::handle(data_start + U256::from(i), LayoutCtx::FULL, address).read()?;
1928 prop_assert_eq!(slot_value, U256::ZERO, "Data slot {} not cleared", i);
1929 }
1930 }
1931
1932 Ok(())
1933 }).unwrap();
1934 }
1935
1936 #[test]
1937 fn proptest_vec_address_roundtrip(data in arb_address_vec(50), len_slot in arb_safe_slot()) {
1938 let (mut storage, address) = setup_storage();
1939
1940 StorageCtx::enter(&mut storage, || {
1941 let data_len = data.len();
1942 let mut vec_slot = Slot::<Vec<Address>>::new(len_slot, address);
1943
1944 vec_slot.write(data.clone())?;
1946 let loaded: Vec<Address> = vec_slot.read()?;
1947 prop_assert_eq!(&loaded, &data, "Vec<Address> roundtrip failed");
1948
1949 vec_slot.delete()?;
1951 let after_delete: Vec<Address> = vec_slot.read()?;
1952 prop_assert!(after_delete.is_empty(), "Vec not empty after delete");
1953
1954 if data_len > 0 {
1957 let data_start = calc_data_slot(len_slot);
1958
1959 for i in 0..data_len {
1960 let slot_value = U256::handle(data_start + U256::from(i), LayoutCtx::FULL, address).read()?;
1961 prop_assert_eq!(slot_value, U256::ZERO, "Data slot {} not cleared", i);
1962 }
1963 }
1964
1965 Ok(())
1966 }).unwrap();
1967 }
1968
1969 #[test]
1970 fn proptest_vec_delete(data in arb_u8_vec(100), len_slot in arb_safe_slot()) {
1971 let (mut storage, address) = setup_storage();
1972
1973 StorageCtx::enter(&mut storage, || {
1974 let mut vec_slot = Slot::<Vec<u8>>::new(len_slot, address);
1975
1976 vec_slot.write(data.clone())?;
1978
1979 vec_slot.delete()?;
1981
1982 let loaded: Vec<u8> = vec_slot.read()?;
1984 prop_assert!(loaded.is_empty(), "Vec not empty after delete");
1985
1986 if !data.is_empty() {
1988 let data_start = calc_data_slot(len_slot);
1989 let byte_count = u8::BYTES;
1990 let slot_count = calc_packed_slot_count(data.len(), byte_count);
1991
1992 for i in 0..slot_count {
1993 let slot_value = U256::handle(data_start + U256::from(i), LayoutCtx::FULL, address).read()?;
1994 prop_assert_eq!(slot_value, U256::ZERO, "Data slot {} not cleared", i);
1995 }
1996 }
1997
1998 Ok(())
1999 }).unwrap();
2000 }
2001
2002 #[test]
2003 fn proptest_vec_struct_roundtrip(data in arb_test_struct_vec(50), len_slot in arb_safe_slot()) {
2004 let (mut storage, address) = setup_storage();
2005
2006 StorageCtx::enter(&mut storage, || {
2007 let data_len = data.len();
2008 let mut vec_slot = Slot::<Vec<TestStruct>>::new(len_slot, address);
2009
2010 vec_slot.write(data.clone())?;
2012 let loaded: Vec<TestStruct> = vec_slot.read()?;
2013 prop_assert_eq!(&loaded, &data, "Vec<TestStruct> roundtrip failed");
2014
2015 vec_slot.delete()?;
2017 let after_delete: Vec<TestStruct> = vec_slot.read()?;
2018 prop_assert!(after_delete.is_empty(), "Vec not empty after delete");
2019
2020 if data_len > 0 {
2022 let data_start = calc_data_slot(len_slot);
2023
2024 for i in 0..data_len {
2025 let slot_value = U256::handle(data_start + U256::from(i), LayoutCtx::FULL, address).read()?;
2026 prop_assert_eq!(slot_value, U256::ZERO, "Data slot {} not cleared", i);
2027 }
2028 }
2029
2030 Ok(())
2031 }).unwrap();
2032 }
2033 }
2034}