Skip to main content

tempo_precompiles/storage/types/
vec.rs

1//! Dynamic array (`Vec<T>`) implementation for the storage traits.
2//!
3//! # Storage Layout
4//!
5//! Vec uses Solidity-compatible dynamic array storage:
6//! - **Base slot**: Stores the array length (number of elements)
7//! - **Data slots**: Start at `keccak256(len_slot)`, elements packed efficiently
8//!
9//! ## Multi-Slot Support
10//!
11//! - Supports both single-slot primitives and multi-slot types (structs, arrays)
12//! - Element at index `i` starts at slot `data_start + i * T::SLOTS`
13
14use 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    /// Vec base slot occupies one full storage slot (stores length).
31    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        // Read length from base slot
48        let length = load_checked_len(storage, len_slot)?;
49
50        if length == 0 {
51            return Ok(Self::new());
52        }
53
54        // Pack elements if necessary. Vec elements can't be split across slots.
55        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        // (T5+) Cleanup stale tail, if necessary.
68        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        // Write length to base slot.
76        storage.store(len_slot, U256::from(self.len()))?;
77
78        if self.is_empty() {
79            return Ok(());
80        }
81
82        // Pack elements if necessary. Vec elements can't be split across slots.
83        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    /// Custom delete for Vec: clears both length slot and all data slots.
91    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        // Read length from base slot to determine how many slots to clear
95        let length = load_checked_len(storage, len_slot)?;
96
97        // Clear base slot (length)
98        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/// Type-safe handler for accessing `Vec<T>` in storage.
110///
111/// Provides both full-vector operations (read/write/delete) and individual element access.
112/// The handler is a thin wrapper around a storage slot number and delegates full-vector
113/// operations to `Slot<Vec<T>>`.
114///
115/// # Element Access
116///
117/// Use `at(index)` to get a `Slot<T>` for individual element operations with OOB guarantees.
118/// Use `[index]` for its efficient counterpart without the check.
119/// - For packed elements (T::BYTES ≤ 16): returns a packed `Slot<T>` with byte offsets
120/// - For unpacked elements: returns a full `Slot<T>` for the element's dedicated slot
121///
122/// # Example
123///
124/// ```ignore
125/// let handler = <Vec<u8> as StorableType>::handle(len_slot, LayoutCtx::FULL);
126///
127/// // Full vector operations
128/// let vec = handler.read()?;
129/// handler.write(vec![1, 2, 3])?;
130///
131/// // Individual element operations (at() returns Option, [] panics on OOB)
132/// if let Some(slot) = handler.at(0) {
133///     let elem = slot.read()?;
134///     slot.write(42)?;
135/// }
136/// ```
137///
138/// # Capacity
139///
140/// Vectors have a maximum capacity of `u32::MAX / element_size` to prevent
141/// arithmetic overflow in storage slot calculations.
142#[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    /// Reads the entire vector from storage.
154    #[inline]
155    fn read(&self) -> Result<Vec<T>> {
156        self.as_slot().read()
157    }
158
159    /// Writes the entire vector to storage.
160    #[inline]
161    fn write(&mut self, value: Vec<T>) -> Result<()> {
162        self.as_slot().write(value)
163    }
164
165    /// Deletes the entire vector from storage (clears length and all elements).
166    #[inline]
167    fn delete(&mut self) -> Result<()> {
168        self.as_slot().delete()
169    }
170
171    /// Reads the entire vector from transient storage.
172    #[inline]
173    fn t_read(&self) -> Result<Vec<T>> {
174        self.as_slot().t_read()
175    }
176
177    /// Writes the entire vector to transient storage.
178    #[inline]
179    fn t_write(&mut self, value: Vec<T>) -> Result<()> {
180        self.as_slot().t_write(value)
181    }
182
183    /// Deletes the entire vector from transient storage.
184    #[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    /// Creates a new handler for the vector at the given base slot and address.
195    #[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    /// Maximum valid index for this element type, preventing arithmetic overflow
205    /// in slot address computation (`index * T::SLOTS` or `index * T::BYTES`).
206    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    /// Returns the slot that stores the length of the dynamic array.
215    #[inline]
216    pub fn len_slot(&self) -> ::alloy::primitives::U256 {
217        self.len_slot
218    }
219
220    /// Returns the base storage slot where this array's data is stored.
221    ///
222    /// Single-slot vectors pack all fields into this slot.
223    /// Multi-slot vectors use consecutive slots starting from this base.
224    #[inline]
225    pub fn data_slot(&self) -> ::alloy::primitives::U256 {
226        calc_data_slot(self.len_slot)
227    }
228
229    /// Returns a `Slot` accessor for full-vector operations.
230    #[inline]
231    fn as_slot(&self) -> Slot<Vec<T>> {
232        Slot::new(self.len_slot, self.address)
233    }
234
235    /// Returns the length of the vector.
236    #[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    /// Returns whether the vector is empty.
243    #[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        // Pack small elements into shared slots, use T::SLOTS for multi-slot types
251        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    /// Returns a `Handler` for the element at the given index with bounds checking.
265    ///
266    /// The handler is computed on first access and cached for subsequent accesses.
267    ///
268    /// # Returns
269    /// - If the SLOAD to read the length fails, returns an error.
270    /// - If the index is OOB, returns `Ok(None)`.
271    /// - Otherwise, returns `Ok(Some(&T::Handler))`.
272    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    /// Pushes a new element to the end of the vector.
284    ///
285    /// Automatically increments the length and handles packing for small types.
286    ///
287    /// Returns `Err` if the vector has reached its maximum capacity.
288    #[inline]
289    pub fn push(&self, value: T) -> Result<()>
290    where
291        T: Storable,
292        T::Handler: Handler<T>,
293    {
294        // Read current length
295        let length = self.len()?;
296        if length >= Self::max_index() {
297            return Err(TempoPrecompileError::Fatal("Vec is at max capacity".into()));
298        }
299
300        // Write element at the end. The tail slot is empty by construction.
301        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            // Handlers always use `FULL` ctx. Since the slot we push to is guaranteed empty,
306            // call `T::store` with `INIT` to skip tail-cleanup SLOADs for dynamic types.
307            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        // Increment length
313        let mut length_slot = Slot::<U256>::new(self.len_slot, self.address);
314        length_slot.write(U256::from(length + 1))
315    }
316
317    /// Pops the last element from the vector.
318    ///
319    /// Returns `None` if the vector is empty. Automatically decrements the length
320    /// and zeros out the popped element's storage slot.
321    #[inline]
322    pub fn pop(&self) -> Result<Option<T>>
323    where
324        T: Storable,
325        T::Handler: Handler<T>,
326    {
327        // Read current length
328        let length = self.len()?;
329        if length == 0 {
330            return Ok(None);
331        }
332        let last_index = length - 1;
333
334        // Read the last element
335        let mut elem_slot = Self::compute_handler(self.data_slot(), self.address, last_index);
336        let element = elem_slot.read()?;
337
338        // Zero out the element's storage
339        elem_slot.delete()?;
340
341        // Decrement length
342        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    /// Returns a reference to the cached handler for the given index (unchecked).
356    ///
357    /// **WARNING:** Does not check bounds. Caller must ensure that the index is valid.
358    /// For checked access use `.at(index)` instead.
359    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    /// Returns a mutable reference to the cached handler for the given index (unchecked).
371    ///
372    /// **WARNING:** Does not check bounds. Caller must ensure that the index is valid.
373    /// For checked access use `.at(index)` instead.
374    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/// Loads a raw U256 from storage and interprets it as a length.
382#[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/// Calculate the starting slot for dynamic array data.
392///
393/// For Solidity compatibility, dynamic array data is stored at `keccak256(len_slot)`.
394#[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
399/// Clears storage occupied exclusively by `Vec` elements in the index range `[from, to)`.
400///
401/// Packed elements (`T::BYTES <= 16`) share storage words, so this only zeroes whole packed
402/// slots that contain no element before `from`:
403///
404/// - `from = 0` clears from slot 0. This is the delete path and clears every slot that may contain
405///   any element in `[0, to)`; e.g. for 16-byte elements, `[0, 1)` clears slot 0.
406/// - `from > 0` starts at `calc_packed_slot_count(from, T::BYTES)`, intentionally preserving the
407///   boundary slot that may also contain live elements `< from`; e.g. for 16-byte elements,
408///   `[1, 2)` clears nothing because elements 0 and 1 share slot 0. Shrink callers rely on the
409///   subsequent packed-slot rewrite to clear stale lanes in that boundary slot.
410///
411/// Unpacked elements delegate to `T::delete` per element so nested dynamic storables are
412/// recursively cleared.
413fn 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        // Vec elements can't be split across slots.
424        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
438/// Load packed elements from storage.
439///
440/// Used when `T::BYTES <= 16`, allowing multiple elements per slot.
441fn 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        // How many elements in this slot?
463        let elements_in_this_slot = if slot_idx == slot_count - 1 {
464            // Last slot might be partially filled
465            length - (slot_idx * elements_per_slot)
466        } else {
467            elements_per_slot
468        };
469
470        // Extract each element from this slot
471        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            // Move to next element position
476            current_offset += byte_count;
477            if current_offset >= 32 {
478                current_offset = 0;
479            }
480        }
481
482        // Reset offset for next slot
483        current_offset = 0;
484    }
485
486    Ok(result)
487}
488
489/// Store packed elements to storage.
490///
491/// Packs multiple small elements into each 32-byte slot using bit manipulation.
492fn 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
516/// Build a packed storage slot from multiple elements.
517///
518/// Takes a slice of elements and packs them into a single U256 word.
519fn 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
536/// Load unpacked elements from storage.
537///
538/// Used when elements don't pack efficiently (32 bytes or multi-slot types).
539/// Each element occupies `T::SLOTS` consecutive slots.
540fn 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        // Use T::SLOTS for proper multi-slot element addressing
548        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
555/// Store unpacked elements to storage.
556///
557/// Each element uses `T::SLOTS` consecutive slots.
558fn 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        // Use T::SLOTS for proper multi-slot element addressing
565        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    // -- TEST HELPERS -------------------------------------------------------------
584
585    // Strategy for generating random U256 slot values that won't overflow
586    fn arb_safe_slot() -> impl Strategy<Value = U256> {
587        any::<[u64; 4]>().prop_map(|limbs| {
588            // Ensure we don't overflow by limiting to a reasonable range
589            U256::from_limbs(limbs) % (U256::MAX - U256::from(10000))
590        })
591    }
592
593    // Helper: Generate a single-slot struct for testing
594    #[derive(Debug, Clone, PartialEq, Eq, Storable)]
595    struct TestStruct {
596        a: u128, // 16 bytes (slot 0)
597        b: u128, // 16 bytes (slot 0)
598    }
599
600    // -- SLOT COMPUTATION TESTS ---------------------------------------------------
601    // Tests that verify handlers compute correct slots WITHOUT storage interaction
602
603    #[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        // Verify base slot is stored correctly
610        assert_eq!(handler.len_slot, len_slot);
611
612        // Verify address is stored correctly
613        assert_eq!(*handler.address, *address);
614    }
615
616    #[test]
617    fn test_vec_data_slot_derivation() {
618        let len_slot = U256::random();
619
620        // Verify data slot matches keccak256(len_slot)
621        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        // For packed types (u8: 1 byte), elements pack 32 per slot
640        // Element at index 5 should be in slot 0, offset 5
641        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        // Element at index 35 should be in slot 1, offset 3 (35 % 32 = 3)
650        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        // For unpacked types (U256: 32 bytes), each element uses a full slot
668        // Element at index 0 should be at data_start + 0
669        let elem_slot = &handler[0];
670        assert_eq!(elem_slot.slot(), data_start);
671        assert_eq!(elem_slot.offset(), None); // Full slot, no offset
672
673        // Element at index 5 should be at data_start + 5
674        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        // Same index should always produce same slot
686        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        // Different indices should produce different slot/offset combinations
708        let slot5 = &handler[5];
709        let slot10 = &handler[10];
710
711        // u16 is 2 bytes, so 16 elements per slot
712        // Index 5 is in slot 0, offset 10
713        // Index 10 is in slot 0, offset 20
714        assert_eq!(slot5.slot(), slot10.slot(), "Both should be in same slot");
715        assert_ne!(slot5.offset(), slot10.offset(), "But different offsets");
716
717        // Index 16 should be in different slot
718        let slot16 = &handler[16];
719        assert_ne!(
720            slot5.slot(),
721            slot16.slot(),
722            "Different slot for index >= 16"
723        );
724    }
725
726    // -- STORABLE TRAIT TESTS -----------------------------------------------------
727
728    #[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            // Nested Vec<Vec<u8>>
753            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            // Test 1: Exactly 32 bools (fills exactly 1 slot: 32 * 1 byte = 32 bytes)
771            let data_exact: Vec<bool> = (0..32).map(|i| i % 2 == 0).collect();
772            slot.write(data_exact.clone()).unwrap();
773
774            // Verify length stored in base slot
775            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            // Test 2: 35 bools (requires 2 slots: 32 + 3)
787            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    // -- SLOT-LEVEL VALIDATION TESTS ----------------------------------------------
799
800    #[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            // Store exactly 5 u8 elements (should fit in 1 slot with 27 unused bytes)
809            <Vec<u8>>::handle(len_slot, LayoutCtx::FULL, address)
810                .write(data.clone())
811                .unwrap();
812
813            // Verify length stored in base slot
814            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            // Expected byte layout: 5 u8 elements packed at rightmost positions
829            let expected = gen_word_from(&[
830                "0x32", // elem[4] = 50
831                "0x28", // elem[3] = 40
832                "0x1e", // elem[2] = 30
833                "0x14", // elem[1] = 20
834                "0x0a", // elem[0] = 10
835            ]);
836            assert_eq!(
837                slot_data, expected,
838                "Slot data should match Solidity byte layout"
839            );
840
841            // Also verify each element can be extracted correctly
842            for (i, &expected) in data.iter().enumerate() {
843                let offset = i; // equivalent to: `i * u8::BYTES`
844                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            // Test 1: Exactly 16 u16 elements (fills exactly 1 slot: 16 * 2 bytes = 32 bytes)
862            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", // elem[15] = 1500
872                "0x0578", // elem[14] = 1400
873                "0x0514", // elem[13] = 1300
874                "0x04b0", // elem[12] = 1200
875                "0x044c", // elem[11] = 1100
876                "0x03e8", // elem[10] = 1000
877                "0x0384", // elem[9] = 900
878                "0x0320", // elem[8] = 800
879                "0x02bc", // elem[7] = 700
880                "0x0258", // elem[6] = 600
881                "0x01f4", // elem[5] = 500
882                "0x0190", // elem[4] = 400
883                "0x012c", // elem[3] = 300
884                "0x00c8", // elem[2] = 200
885                "0x0064", // elem[1] = 100
886                "0x0000", // elem[0] = 0
887            ]);
888            assert_eq!(
889                slot0_value, expected_slot0,
890                "Slot 0 should match Solidity byte layout"
891            );
892
893            // Also verify each element can be extracted
894            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            // Test 2: 17 u16 elements (requires 2 slots)
904            let data_overflow: Vec<u16> = (0..17).map(|i| i * 100).collect();
905            vec_slot.write(data_overflow).unwrap();
906
907            // Verify slot 0 still matches (first 16 elements)
908            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            // Verify slot 1 has the 17th element (1600 = 0x0640)
917            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", // elem[16] = 1600
924            ]);
925            assert_eq!(
926                slot1_value, expected_slot1,
927                "Slot 1 should match Solidity byte layout"
928            );
929
930            // Also verify the 17th element can be extracted
931            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            // Store 35 u8 elements (values 1-35):
946            // - Slot 0: 32 elements (full) - elements 1-32
947            // - Slot 1: 3 elements (elements 33-35) + 29 zeros
948            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", // elem[31] = 32
958                "0x1f", // elem[30] = 31
959                "0x1e", // elem[29] = 30
960                "0x1d", // elem[28] = 29
961                "0x1c", // elem[27] = 28
962                "0x1b", // elem[26] = 27
963                "0x1a", // elem[25] = 26
964                "0x19", // elem[24] = 25
965                "0x18", // elem[23] = 24
966                "0x17", // elem[22] = 23
967                "0x16", // elem[21] = 22
968                "0x15", // elem[20] = 21
969                "0x14", // elem[19] = 20
970                "0x13", // elem[18] = 19
971                "0x12", // elem[17] = 18
972                "0x11", // elem[16] = 17
973                "0x10", // elem[15] = 16
974                "0x0f", // elem[14] = 15
975                "0x0e", // elem[13] = 14
976                "0x0d", // elem[12] = 13
977                "0x0c", // elem[11] = 12
978                "0x0b", // elem[10] = 11
979                "0x0a", // elem[9] = 10
980                "0x09", // elem[8] = 9
981                "0x08", // elem[7] = 8
982                "0x07", // elem[6] = 7
983                "0x06", // elem[5] = 6
984                "0x05", // elem[4] = 5
985                "0x04", // elem[3] = 4
986                "0x03", // elem[2] = 3
987                "0x02", // elem[1] = 2
988                "0x01", // elem[0] = 1
989            ]);
990            assert_eq!(
991                slot0_value, expected_slot0,
992                "Slot 0 should match Solidity byte layout"
993            );
994
995            // Verify slot 1 has exactly 3 elements at rightmost positions
996            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", // elem[2] = 35
1003                "0x22", // elem[1] = 34
1004                "0x21", // elem[0] = 33
1005            ]);
1006            assert_eq!(
1007                slot1_value, expected_slot1,
1008                "Slot 1 should match Solidity byte layout"
1009            );
1010
1011            // Also verify each element in slot 1 can be extracted
1012            let slot1_data = [33u8, 34u8, 35u8];
1013            for (i, &expected) in slot1_data.iter().enumerate() {
1014                let offset = i; // equivalent to: `i * u8::BYTES`
1015                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            // Store 3 U256 values (each should occupy its own slot)
1035            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            // Verify each U256 occupies its own sequential slot
1046            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            // Verify there's no data in slot 3 (should be empty)
1055            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            // Store 3 addresses (each 20 bytes, but 32 % 20 != 0, so unpacked)
1070            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            // Verify slot 0: Address(0xAA...) right-aligned with 12-byte padding
1081            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            // Verify slot 1: Address(0xBB...) right-aligned with 12-byte padding
1091            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            // Verify slot 2: Address(0xCC...) right-aligned with 12-byte padding
1102            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            // Also verify addresses can be loaded back
1113            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            // Store Vec<TestStruct> with 3 single-slot structs
1135            // Each TestStruct has two u128 fields (a, b) packed into one 32-byte slot
1136            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            // Verify slot 0: TestStruct { a: 100, b: 1 }
1147            // Note: Solidity packs struct fields right-to-left (declaration order reversed in memory)
1148            // So field b (declared second) goes in bytes 0-15, field a (declared first) goes in bytes 16-31
1149            let slot0_value = U256::handle(data_start, LayoutCtx::FULL, address)
1150                .read()
1151                .unwrap();
1152            let expected_slot0 = gen_word_from(&[
1153                "0x00000000000000000000000000000001", // field b = 1
1154                "0x00000000000000000000000000000064", // field a = 100
1155            ]);
1156            assert_eq!(
1157                slot0_value, expected_slot0,
1158                "Slot 0 should match Solidity byte layout"
1159            );
1160
1161            // Verify slot 1: TestStruct { a: 200, b: 2 }
1162            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", // field b = 2
1168                "0x000000000000000000000000000000C8", // field a = 200
1169            ]);
1170            assert_eq!(
1171                slot1_value, expected_slot1,
1172                "Slot 1 should match Solidity byte layout"
1173            );
1174
1175            // Verify slot 2: TestStruct { a: 300, b: 3 }
1176            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", // field b = 3
1182                "0x0000000000000000000000000000012C", // field a = 300
1183            ]);
1184            assert_eq!(
1185                slot2_value, expected_slot2,
1186                "Slot 2 should match Solidity byte layout"
1187            );
1188
1189            // Verify slot 3 is empty (no 4th element)
1190            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            // Also verify each struct can be loaded back correctly
1197            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        // Test that single-slot structs are stored correctly in Vec
1212        #[derive(Debug, Clone, PartialEq, Eq, Storable)]
1213        struct SmallStruct {
1214            flag1: bool, // offset 0 (1 byte)
1215            flag2: bool, // offset 1 (1 byte)
1216            value: u16,  // offset 2 (2 bytes)
1217        }
1218
1219        let (mut storage, address) = setup_storage();
1220
1221        StorageCtx::enter(&mut storage, || {
1222            let len_slot = U256::from(2550);
1223
1224            // Store 3 SmallStruct elements
1225            // Each struct uses 1 full slot (even though it only occupies 4 bytes)
1226            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            // Verify length stored in base slot
1247            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            // Verify slot 0: first struct (fields packed within the struct)
1255            let slot0_value = U256::handle(data_start, LayoutCtx::FULL, address)
1256                .read()
1257                .unwrap();
1258            let expected_slot0 = gen_word_from(&[
1259                "0x0064", // value = 100 (offset 2-3, 2 bytes)
1260                "0x00",   // flag2 = false (offset 1, 1 byte)
1261                "0x01",   // flag1 = true (offset 0, 1 byte)
1262            ]);
1263            assert_eq!(
1264                slot0_value, expected_slot0,
1265                "Slot 0 should match Solidity layout for struct[0]"
1266            );
1267
1268            // Verify slot 1: second struct
1269            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", // value = 200 (offset 2-3, 2 bytes)
1275                "0x01",   // flag2 = true (offset 1, 1 byte)
1276                "0x00",   // flag1 = false (offset 0, 1 byte)
1277            ]);
1278            assert_eq!(
1279                slot1_value, expected_slot1,
1280                "Slot 1 should match Solidity layout for struct[1]"
1281            );
1282
1283            // Verify slot 2: third struct
1284            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", // value = 300 (offset 2-3, 2 bytes)
1290                "0x01",   // flag2 = true (offset 1, 1 byte)
1291                "0x01",   // flag1 = true (offset 0, 1 byte)
1292            ]);
1293            assert_eq!(
1294                slot2_value, expected_slot2,
1295                "Slot 2 should match Solidity layout for struct[2]"
1296            );
1297
1298            // Verify roundtrip
1299            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            // Store a vec with 3 u8 elements
1312            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            // Verify base slot contains length
1317            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            // Verify data starts at keccak256(len_slot), not len_slot + 1
1323            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            // Verify data slot matches expected Solidity byte layout
1331            let data_slot_value = U256::handle(data_start, LayoutCtx::FULL, address)
1332                .read()
1333                .unwrap();
1334
1335            let expected = gen_word_from(&[
1336                "0xfa", // elem[2] = 250
1337                "0xc8", // elem[1] = 200
1338                "0x64", // elem[0] = 100
1339            ]);
1340            assert_eq!(
1341                data_slot_value, expected,
1342                "Data slot should match Solidity byte layout"
1343            );
1344
1345            // Also verify each element can be extracted
1346            for (i, &expected) in data.iter().enumerate() {
1347                let offset = i; // equivalent to: `i * u8::BYTES`
1348                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            // Store a vec with 5 u8 elements (requires 1 slot)
1366            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            // Verify initial storage
1372            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            // Overwrite with a shorter vec (3 elements)
1378            let data_short = vec![10u8, 20, 30];
1379            vec_slot.write(data_short.clone()).unwrap();
1380
1381            // Verify length updated
1382            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            // Verify new data can be extracted correctly (even though old data might remain)
1388            for (i, &expected) in data_short.iter().enumerate() {
1389                let offset = i; // equivalent to: `i * u8::BYTES`
1390                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            // For full cleanup, delete first, then store
1405            vec_slot.delete().unwrap();
1406            vec_slot.write(data_short.clone()).unwrap();
1407
1408            // Verify slot matches expected Solidity byte layout after delete+store
1409            let slot0_after_delete = U256::handle(data_start, LayoutCtx::FULL, address)
1410                .read()
1411                .unwrap();
1412
1413            let expected = gen_word_from(&[
1414                "0x1e", // elem[2] = 30
1415                "0x14", // elem[1] = 20
1416                "0x0a", // elem[0] = 10
1417            ]);
1418            assert_eq!(
1419                slot0_after_delete, expected,
1420                "Slot should match Solidity byte layout after delete+store"
1421            );
1422
1423            // Also verify each element can still be extracted
1424            for (i, &expected) in data_short.iter().enumerate() {
1425                let offset = i; // equivalent to: `i * u8::BYTES`
1426                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    // TODO(rusowsky): Implement and test multi-slot support
1436    // fn test_multi_slot_array() {
1437    //     #[derive(Storable)]
1438    //     struct MultiSlotStruct {
1439    //         field1: U256, // slot 0
1440    //         field2: U256, // slot 1
1441    //         field3: U256, // slot 2
1442    //     }
1443
1444    //     let (mut storage, address) = setup_storage();
1445    //     // MIGRATION TODO: This test needs to be migrated to StorageCtx::enter pattern
1446
1447    //     let len_slot = U256::from(2700);
1448
1449    //     let data: Vec<MultiSlotStruct> = vec![MultiSlotStruct {
1450    //         field1: U256::ONE,
1451    //         field2: U256::from(2),
1452    //         field3: U256::from(3),
1453    //     }];
1454
1455    //     data.store(storage, len_slot, 0).unwrap();
1456
1457    //     let data_start = calc_data_slot(len_slot);
1458    // }
1459
1460    // -- VEC HANDLER TESTS --------------------------------------------------------
1461    // Tests that verify VecHandler API methods
1462
1463    #[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            // Test write and read
1472            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            // Write some data
1489            handler.write(vec![1, 2, 3, 4, 5]).unwrap();
1490            assert_eq!(handler.read().unwrap().len(), 5);
1491
1492            // Delete
1493            handler.delete().unwrap();
1494
1495            // Verify empty
1496            let loaded = handler.read().unwrap();
1497            assert!(loaded.is_empty(), "Vec should be empty after delete");
1498
1499            // Verify length slot is cleared
1500            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            // Write full vector first
1516            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            // Test reading individual elements via at()
1521            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            // Test writing individual elements via at()
1530            handler[1].write(U256::from(99)).unwrap();
1531
1532            // Verify via read
1533            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            // Test push
1554            handler.push(val1).unwrap();
1555            handler.push(val2).unwrap();
1556            handler.push(val3).unwrap();
1557
1558            assert_eq!(handler.len().unwrap(), 3);
1559
1560            // Test pop
1561            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            // Initial length should be 0
1579            assert_eq!(handler.len().unwrap(), 0);
1580
1581            // Push elements and verify length
1582            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            // Pop and verify length decreases
1592            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            // Push 35 elements (crosses slot boundary: 32 in slot 0, 3 in slot 1)
1606            for i in 0..35 {
1607                handler.push(i as u8).unwrap();
1608            }
1609
1610            assert_eq!(handler.len().unwrap(), 35);
1611
1612            // Verify values
1613            for i in 0..35 {
1614                let val = handler[i].read().unwrap();
1615                assert_eq!(val, i as u8);
1616            }
1617
1618            // Pop all and verify
1619            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            // Empty vec - any index should return None
1637            assert!(handler.at(0)?.is_none());
1638
1639            // Push 2 elements
1640            handler.push(U256::from(10))?;
1641            handler.push(U256::from(20))?;
1642
1643            // Valid indices should return Some and read the correct values
1644            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            // OOB indices should return None
1650            assert!(handler.at(3)?.is_none());
1651
1652            Ok(())
1653        })
1654    }
1655
1656    // -- LENGTH OVERFLOW TESTS -------------------------------------------------
1657
1658    #[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            // PoC value from audit: must be rejected with under_overflow
1667            len_slot.write(U256::from(0x0004000000000000u64))?;
1668            assert_eq!(handler.len(), Err(TempoPrecompileError::under_overflow()));
1669
1670            // Boundary: u32::MAX is accepted
1671            len_slot.write(U256::from(u32::MAX))?;
1672            assert_eq!(handler.len()?, u32::MAX as usize);
1673
1674            // Boundary: u32::MAX + 1 is rejected with under_overflow
1675            len_slot.write(U256::from(u64::from(u32::MAX) + 1))?;
1676            assert_eq!(handler.len(), Err(TempoPrecompileError::under_overflow()));
1677
1678            // Large but valid values below u32::MAX are accepted (no arbitrary cap)
1679            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            // -- packed type (u32: 4 bytes) --
1694            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            // -- unpacked type (U256: 32 bytes) --
1707            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    // -- PROPTEST STRATEGIES ------------------------------------------------------
1724
1725    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    // -- PROPERTY TESTS -----------------------------------------------------------
1785
1786    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            // Store → Load roundtrip
1797            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            // Delete + verify cleanup
1802            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            // Verify data slots are cleared (if length > 0)
1807            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            // Store → Load roundtrip
1831            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            // Delete + verify cleanup
1836            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            // Verify data slots are cleared (if length > 0)
1841            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            // Store → Load roundtrip
1865            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            // Delete + verify cleanup
1870            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            // Verify data slots are cleared (if length > 0)
1875            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            // Store → Load roundtrip
1899            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            // Delete + verify cleanup
1904            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            // Verify data slots are cleared (if length > 0)
1909            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            // Store → Load roundtrip
1933            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            // Delete + verify cleanup
1938            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            // Verify data slots are cleared (if length > 0)
1943            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            // Store → Load roundtrip
1967            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            // Delete + verify cleanup
1972            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            // Verify data slots are cleared (if length > 0)
1977            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            // Store → Load roundtrip
1999            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            // Delete + verify cleanup
2004            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                // Verify data slots are cleared (if length > 0)
2009                // Address is 20 bytes, but 32 % 20 != 0, so they don't pack and each uses one slot
2010                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            // Store data
2031            vec_slot.write(data.clone())?;
2032
2033            // Delete
2034            vec_slot.delete()?;
2035
2036            // Verify empty after delete
2037            let loaded: Vec<u8> = vec_slot.read()?;
2038            prop_assert!(loaded.is_empty(), "Vec not empty after delete");
2039
2040                // Verify data slots are cleared (if length > 0)
2041                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            // Store → Load roundtrip
2065            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            // Delete + verify cleanup
2070            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                // Verify data slots are cleared (if length > 0)
2075                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}