1use alloy::primitives::{Address, U256};
6use revm::interpreter::instructions::utility::{IntoAddress, IntoU256};
7use tempo_precompiles_macros;
8
9use crate::storage::types::*;
10
11tempo_precompiles_macros::storable_rust_ints!();
13tempo_precompiles_macros::storable_alloy_ints!();
15tempo_precompiles_macros::storable_alloy_bytes!();
17
18impl StorableType for bool {
21 const LAYOUT: Layout = Layout::Bytes(1);
22
23 type Handler = Slot<Self>;
24
25 fn handle(slot: U256, ctx: LayoutCtx, address: Address) -> Self::Handler {
26 Slot::new_with_ctx(slot, ctx, address)
27 }
28}
29
30impl super::sealed::OnlyPrimitives for bool {}
31impl Packable for bool {}
32impl FromWord for bool {
33 #[inline]
34 fn to_word(&self) -> U256 {
35 if *self { U256::ONE } else { U256::ZERO }
36 }
37
38 #[inline]
39 fn from_word(word: U256) -> crate::error::Result<Self> {
40 Ok(!word.is_zero())
41 }
42}
43
44impl StorageKey for bool {
45 #[inline]
46 fn as_storage_bytes(&self) -> impl AsRef<[u8]> {
47 if *self { [1u8] } else { [0u8] }
48 }
49}
50
51impl StorableType for Address {
52 const LAYOUT: Layout = Layout::Bytes(20);
53 type Handler = Slot<Self>;
54
55 fn handle(slot: U256, ctx: LayoutCtx, address: Address) -> Self::Handler {
56 Slot::new_with_ctx(slot, ctx, address)
57 }
58}
59
60impl super::sealed::OnlyPrimitives for Address {}
61impl Packable for Address {}
62impl FromWord for Address {
63 #[inline]
64 fn to_word(&self) -> U256 {
65 self.into_u256()
66 }
67
68 #[inline]
69 fn from_word(word: U256) -> crate::error::Result<Self> {
70 Ok(word.into_address())
71 }
72}
73
74impl StorageKey for Address {
75 #[inline]
76 fn as_storage_bytes(&self) -> impl AsRef<[u8]> {
77 self.as_slice()
78 }
79}
80
81#[cfg(test)]
82mod tests {
83 use super::*;
84 use crate::{
85 storage::{Handler, PrecompileStorageProvider, StorageCtx},
86 test_util::{gen_word_from, setup_storage},
87 };
88 use proptest::prelude::*;
89
90 fn arb_safe_slot() -> impl Strategy<Value = U256> {
92 any::<[u64; 4]>().prop_map(|limbs| {
93 U256::from_limbs(limbs) % (U256::MAX - U256::from(10000))
95 })
96 }
97
98 fn arb_address() -> impl Strategy<Value = Address> {
100 any::<[u8; 20]>().prop_map(Address::from)
101 }
102
103 tempo_precompiles_macros::gen_storable_tests!();
110 proptest! {
111 #![proptest_config(ProptestConfig::with_cases(500))]
112
113 #[test]
114 fn test_address(addr in arb_address(), base_slot in arb_safe_slot()) {
115 let (mut storage, address) = setup_storage();
116 StorageCtx::enter(&mut storage, || {
117 let mut slot = Address::handle(base_slot, LayoutCtx::FULL, address);
118
119 slot.write(addr).unwrap();
121 let loaded = slot.read().unwrap();
122 assert_eq!(addr, loaded, "Address roundtrip failed");
123
124 slot.delete().unwrap();
126 let after_delete = slot.read().unwrap();
127 assert_eq!(after_delete, Address::ZERO, "Address not zero after delete");
128
129 let word = addr.to_word();
131 let recovered = <Address as FromWord>::from_word(word).unwrap();
132 assert_eq!(addr, recovered, "Address EVM word roundtrip failed");
133 });
134 }
135
136 #[test]
137 fn test_bool_values(b in any::<bool>(), base_slot in arb_safe_slot()) {
138 let (mut storage, address) = setup_storage();
139 StorageCtx::enter(&mut storage, || {
140 let mut slot = bool::handle(base_slot, LayoutCtx::FULL, address);
141
142 slot.write(b).unwrap();
144 let loaded = slot.read().unwrap();
145 assert_eq!(b, loaded, "Bool roundtrip failed for value: {b}");
146
147 slot.delete().unwrap();
149 let after_delete = slot.read().unwrap();
150 assert!(!after_delete, "Bool not false after delete");
151
152 let word = b.to_word();
154 let recovered = <bool as FromWord>::from_word(word).unwrap();
155 assert_eq!(b, recovered, "Bool EVM word roundtrip failed");
156 });
157 }
158 }
159
160 #[test]
163 fn test_unsigned_word_byte_representation() {
164 assert_eq!(0u8.to_word(), gen_word_from(&["0x00"]));
166 assert_eq!(1u8.to_word(), gen_word_from(&["0x01"]));
167 assert_eq!(255u8.to_word(), gen_word_from(&["0xFF"]));
168 assert!(u8::from_word(gen_word_from(&["0x0100"])).is_err()); assert_eq!(0u16.to_word(), gen_word_from(&["0x0000"]));
172 assert_eq!(256u16.to_word(), gen_word_from(&["0x0100"]));
173 assert_eq!(u16::MAX.to_word(), gen_word_from(&["0xFFFF"]));
174 assert!(u16::from_word(gen_word_from(&["0x010000"])).is_err()); assert_eq!(0u32.to_word(), gen_word_from(&["0x00000000"]));
178 assert_eq!(0x12345678u32.to_word(), gen_word_from(&["0x12345678"]));
179 assert_eq!(u32::MAX.to_word(), gen_word_from(&["0xFFFFFFFF"]));
180
181 assert_eq!(0u64.to_word(), gen_word_from(&["0x0000000000000000"]));
183 assert_eq!(
184 0x123456789ABCDEFu64.to_word(),
185 gen_word_from(&["0x0123456789ABCDEF"])
186 );
187 assert_eq!(u64::MAX.to_word(), gen_word_from(&["0xFFFFFFFFFFFFFFFF"]));
188
189 assert_eq!(
191 0u128.to_word(),
192 gen_word_from(&["0x00000000000000000000000000000000"])
193 );
194 assert_eq!(
195 u128::MAX.to_word(),
196 gen_word_from(&["0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"])
197 );
198 }
199
200 #[test]
201 fn test_signed_word_byte_representation() {
202 assert_eq!(0i8.to_word(), gen_word_from(&["0x00"]));
204 assert_eq!(1i8.to_word(), gen_word_from(&["0x01"]));
205 assert_eq!((-1i8).to_word(), gen_word_from(&["0xFF"]));
206 assert_eq!((-2i8).to_word(), gen_word_from(&["0xFE"]));
207 assert_eq!(127i8.to_word(), gen_word_from(&["0x7F"])); assert_eq!((-128i8).to_word(), gen_word_from(&["0x80"])); assert!(i8::from_word(gen_word_from(&["0x0100"])).is_err()); assert_eq!(0i16.to_word(), gen_word_from(&["0x0000"]));
213 assert_eq!(1i16.to_word(), gen_word_from(&["0x0001"]));
214 assert_eq!((-1i16).to_word(), gen_word_from(&["0xFFFF"]));
215 assert_eq!((-2i16).to_word(), gen_word_from(&["0xFFFE"]));
216 assert_eq!(i16::MAX.to_word(), gen_word_from(&["0x7FFF"]));
217 assert_eq!(i16::MIN.to_word(), gen_word_from(&["0x8000"]));
218 assert!(i16::from_word(gen_word_from(&["0x010000"])).is_err()); assert_eq!(0i32.to_word(), gen_word_from(&["0x00000000"]));
222 assert_eq!(i32::MAX.to_word(), gen_word_from(&["0x7FFFFFFF"]));
223 assert_eq!((-1i32).to_word(), gen_word_from(&["0xFFFFFFFF"]));
224 assert_eq!(i32::MIN.to_word(), gen_word_from(&["0x80000000"]));
225
226 assert_eq!(0i64.to_word(), gen_word_from(&["0x0000000000000000"]));
228 assert_eq!(i64::MAX.to_word(), gen_word_from(&["0x7FFFFFFFFFFFFFFF"]));
229 assert_eq!((-1i64).to_word(), gen_word_from(&["0xFFFFFFFFFFFFFFFF"]));
230 assert_eq!(i64::MIN.to_word(), gen_word_from(&["0x8000000000000000"]));
231
232 assert_eq!(
234 0i128.to_word(),
235 gen_word_from(&["0x00000000000000000000000000000000"])
236 );
237 assert_eq!(
238 i128::MAX.to_word(),
239 gen_word_from(&["0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"])
240 );
241 assert_eq!(
242 (-1i128).to_word(),
243 gen_word_from(&["0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"])
244 );
245 assert_eq!(
246 i128::MIN.to_word(),
247 gen_word_from(&["0x80000000000000000000000000000000"])
248 );
249 }
250
251 #[test]
254 fn test_u8_at_various_offsets() {
255 let (mut storage, address) = setup_storage();
256 let base_slot = U256::from(100);
257
258 let val0: u8 = 0x42;
260 StorageCtx::enter(&mut storage, || {
261 let mut slot0 = u8::handle(base_slot, LayoutCtx::packed(0), address);
262 slot0.write(val0).unwrap();
263
264 let read_val = slot0.read().unwrap();
266 assert_eq!(read_val, val0);
267 });
268
269 let loaded_slot = storage.sload(address, base_slot).unwrap();
271 let expected = gen_word_from(&["0x42"]);
272 assert_eq!(loaded_slot, expected);
273
274 storage.sstore(address, base_slot, U256::ZERO).unwrap();
276
277 StorageCtx::enter(&mut storage, || {
279 let slot0 = u8::handle(base_slot, LayoutCtx::packed(0), address);
280 let cleared_val = slot0.read().unwrap();
281 assert_eq!(cleared_val, 0u8);
282 });
283
284 let val15: u8 = 0xAB;
286 StorageCtx::enter(&mut storage, || {
287 let mut slot15 = u8::handle(base_slot + U256::ONE, LayoutCtx::packed(15), address);
288 slot15.write(val15).unwrap();
289
290 let read_val = slot15.read().unwrap();
292 assert_eq!(read_val, val15);
293 });
294
295 let loaded_slot = storage.sload(address, base_slot + U256::ONE).unwrap();
297 let expected = gen_word_from(&[
298 "0xAB", "0x000000000000000000000000000000", ]);
301 assert_eq!(loaded_slot, expected);
302
303 storage
305 .sstore(address, base_slot + U256::ONE, U256::ZERO)
306 .unwrap();
307
308 StorageCtx::enter(&mut storage, || {
310 let slot15 = u8::handle(base_slot + U256::ONE, LayoutCtx::packed(15), address);
311 let cleared_val = slot15.read().unwrap();
312 assert_eq!(cleared_val, 0u8);
313 });
314
315 let val31: u8 = 0xFF;
317 StorageCtx::enter(&mut storage, || {
318 let mut slot31 = u8::handle(base_slot + U256::from(2), LayoutCtx::packed(31), address);
319 slot31.write(val31).unwrap();
320
321 let read_val = slot31.read().unwrap();
323 assert_eq!(read_val, val31);
324 });
325
326 let loaded_slot = storage.sload(address, base_slot + U256::from(2)).unwrap();
328 let expected = gen_word_from(&[
329 "0xFF", "0x00000000000000000000000000000000000000000000000000000000000000", ]);
332 assert_eq!(loaded_slot, expected);
333
334 storage
336 .sstore(address, base_slot + U256::from(2), U256::ZERO)
337 .unwrap();
338
339 StorageCtx::enter(&mut storage, || {
341 let slot31 = u8::handle(base_slot + U256::from(2), LayoutCtx::packed(31), address);
342 let cleared_val = slot31.read().unwrap();
343 assert_eq!(cleared_val, 0u8);
344 });
345 }
346
347 #[test]
348 fn test_u16_at_various_offsets() {
349 let (mut storage, address) = setup_storage();
350 let base_slot = U256::from(200);
351
352 let val0: u16 = 0x1234;
354 StorageCtx::enter(&mut storage, || {
355 let mut slot0 = u16::handle(base_slot, LayoutCtx::packed(0), address);
356 slot0.write(val0).unwrap();
357
358 let read_val = slot0.read().unwrap();
360 assert_eq!(read_val, val0);
361 });
362
363 let loaded_slot = storage.sload(address, base_slot).unwrap();
365 let expected = gen_word_from(&["0x1234"]);
366 assert_eq!(loaded_slot, expected);
367
368 storage.sstore(address, base_slot, U256::ZERO).unwrap();
370
371 StorageCtx::enter(&mut storage, || {
373 let slot0 = u16::handle(base_slot, LayoutCtx::packed(0), address);
374 let cleared_val = slot0.read().unwrap();
375 assert_eq!(cleared_val, 0u16);
376 });
377
378 let val15: u16 = 0xABCD;
380 StorageCtx::enter(&mut storage, || {
381 let mut slot15 = u16::handle(base_slot + U256::ONE, LayoutCtx::packed(15), address);
382 slot15.write(val15).unwrap();
383
384 let read_val = slot15.read().unwrap();
386 assert_eq!(read_val, val15);
387 });
388
389 let loaded_slot = storage.sload(address, base_slot + U256::ONE).unwrap();
391 let expected = gen_word_from(&[
392 "0xABCD", "0x000000000000000000000000000000", ]);
395 assert_eq!(loaded_slot, expected);
396
397 storage
399 .sstore(address, base_slot + U256::ONE, U256::ZERO)
400 .unwrap();
401
402 StorageCtx::enter(&mut storage, || {
404 let slot15 = u16::handle(base_slot + U256::ONE, LayoutCtx::packed(15), address);
405 let cleared_val = slot15.read().unwrap();
406 assert_eq!(cleared_val, 0u16);
407 });
408
409 let val30: u16 = 0xFFEE;
411 StorageCtx::enter(&mut storage, || {
412 let mut slot30 = u16::handle(base_slot + U256::from(2), LayoutCtx::packed(30), address);
413 slot30.write(val30).unwrap();
414
415 let read_val = slot30.read().unwrap();
417 assert_eq!(read_val, val30);
418 });
419
420 let loaded_slot = storage.sload(address, base_slot + U256::from(2)).unwrap();
422 let expected = gen_word_from(&[
423 "0xFFEE", "0x000000000000000000000000000000000000000000000000000000000000", ]);
426 assert_eq!(loaded_slot, expected);
427
428 storage
430 .sstore(address, base_slot + U256::from(2), U256::ZERO)
431 .unwrap();
432
433 StorageCtx::enter(&mut storage, || {
435 let slot30 = u16::handle(base_slot + U256::from(2), LayoutCtx::packed(30), address);
436 let cleared_val = slot30.read().unwrap();
437 assert_eq!(cleared_val, 0u16);
438 });
439 }
440
441 #[test]
442 fn test_u32_at_various_offsets() {
443 let (mut storage, address) = setup_storage();
444 let base_slot = U256::from(300);
445
446 let val0: u32 = 0x12345678;
448 StorageCtx::enter(&mut storage, || {
449 let mut slot0 = u32::handle(base_slot, LayoutCtx::packed(0), address);
450 slot0.write(val0).unwrap();
451
452 let read_val = slot0.read().unwrap();
454 assert_eq!(read_val, val0);
455 });
456
457 let loaded_slot = storage.sload(address, base_slot).unwrap();
459 let expected = gen_word_from(&["0x12345678"]);
460 assert_eq!(loaded_slot, expected);
461
462 storage.sstore(address, base_slot, U256::ZERO).unwrap();
464
465 StorageCtx::enter(&mut storage, || {
467 let slot0 = u32::handle(base_slot, LayoutCtx::packed(0), address);
468 let cleared_val = slot0.read().unwrap();
469 assert_eq!(cleared_val, 0u32);
470 });
471
472 let val14: u32 = 0xABCDEF01;
474 StorageCtx::enter(&mut storage, || {
475 let mut slot14 = u32::handle(base_slot + U256::ONE, LayoutCtx::packed(14), address);
476 slot14.write(val14).unwrap();
477
478 let read_val = slot14.read().unwrap();
480 assert_eq!(read_val, val14);
481 });
482
483 let loaded_slot = storage.sload(address, base_slot + U256::ONE).unwrap();
485 let expected = gen_word_from(&[
486 "0xABCDEF01", "0x0000000000000000000000000000", ]);
489 assert_eq!(loaded_slot, expected);
490
491 storage
493 .sstore(address, base_slot + U256::ONE, U256::ZERO)
494 .unwrap();
495
496 StorageCtx::enter(&mut storage, || {
498 let slot14 = u32::handle(base_slot + U256::ONE, LayoutCtx::packed(14), address);
499 let cleared_val = slot14.read().unwrap();
500 assert_eq!(cleared_val, 0u32);
501 });
502
503 let val28: u32 = 0xFFEEDDCC;
505 StorageCtx::enter(&mut storage, || {
506 let mut slot28 = u32::handle(base_slot + U256::from(2), LayoutCtx::packed(28), address);
507 slot28.write(val28).unwrap();
508
509 let read_val = slot28.read().unwrap();
511 assert_eq!(read_val, val28);
512 });
513
514 let loaded_slot = storage.sload(address, base_slot + U256::from(2)).unwrap();
516 let expected = gen_word_from(&[
517 "0xFFEEDDCC", "0x00000000000000000000000000000000000000000000000000000000", ]);
520 assert_eq!(loaded_slot, expected);
521
522 storage
524 .sstore(address, base_slot + U256::from(2), U256::ZERO)
525 .unwrap();
526
527 StorageCtx::enter(&mut storage, || {
529 let slot28 = u32::handle(base_slot + U256::from(2), LayoutCtx::packed(28), address);
530 let cleared_val = slot28.read().unwrap();
531 assert_eq!(cleared_val, 0u32);
532 });
533 }
534
535 #[test]
536 fn test_u64_at_various_offsets() {
537 let (mut storage, address) = setup_storage();
538 let base_slot = U256::from(400);
539
540 let val0: u64 = 0x123456789ABCDEF0;
542 StorageCtx::enter(&mut storage, || {
543 let mut slot0 = u64::handle(base_slot, LayoutCtx::packed(0), address);
544 slot0.write(val0).unwrap();
545
546 let read_val = slot0.read().unwrap();
548 assert_eq!(read_val, val0);
549 });
550
551 let loaded_slot = storage.sload(address, base_slot).unwrap();
553 let expected = gen_word_from(&["0x123456789ABCDEF0"]);
554 assert_eq!(loaded_slot, expected);
555
556 storage.sstore(address, base_slot, U256::ZERO).unwrap();
558
559 StorageCtx::enter(&mut storage, || {
561 let slot0 = u64::handle(base_slot, LayoutCtx::packed(0), address);
562 let cleared_val = slot0.read().unwrap();
563 assert_eq!(cleared_val, 0u64);
564 });
565
566 let val12: u64 = 0xFEDCBA9876543210;
568 StorageCtx::enter(&mut storage, || {
569 let mut slot12 = u64::handle(base_slot + U256::ONE, LayoutCtx::packed(12), address);
570 slot12.write(val12).unwrap();
571
572 let read_val = slot12.read().unwrap();
574 assert_eq!(read_val, val12);
575 });
576
577 let loaded_slot = storage.sload(address, base_slot + U256::ONE).unwrap();
579 let expected = gen_word_from(&[
580 "0xFEDCBA9876543210", "0x000000000000000000000000", ]);
583 assert_eq!(loaded_slot, expected);
584
585 storage
587 .sstore(address, base_slot + U256::ONE, U256::ZERO)
588 .unwrap();
589
590 StorageCtx::enter(&mut storage, || {
592 let slot12 = u64::handle(base_slot + U256::ONE, LayoutCtx::packed(12), address);
593 let cleared_val = slot12.read().unwrap();
594 assert_eq!(cleared_val, 0u64);
595 });
596
597 let val24: u64 = 0xAAAABBBBCCCCDDDD;
599 StorageCtx::enter(&mut storage, || {
600 let mut slot24 = u64::handle(base_slot + U256::from(2), LayoutCtx::packed(24), address);
601 slot24.write(val24).unwrap();
602
603 let read_val = slot24.read().unwrap();
605 assert_eq!(read_val, val24);
606 });
607
608 let loaded_slot = storage.sload(address, base_slot + U256::from(2)).unwrap();
610 let expected = gen_word_from(&[
611 "0xAAAABBBBCCCCDDDD", "0x000000000000000000000000000000000000000000000000", ]);
614 assert_eq!(loaded_slot, expected);
615
616 storage
618 .sstore(address, base_slot + U256::from(2), U256::ZERO)
619 .unwrap();
620
621 StorageCtx::enter(&mut storage, || {
623 let slot24 = u64::handle(base_slot + U256::from(2), LayoutCtx::packed(24), address);
624 let cleared_val = slot24.read().unwrap();
625 assert_eq!(cleared_val, 0u64);
626 });
627 }
628
629 #[test]
630 fn test_u128_at_various_offsets() {
631 let (mut storage, address) = setup_storage();
632 let base_slot = U256::from(500);
633
634 let val0: u128 = 0x123456789ABCDEF0_FEDCBA9876543210;
636 StorageCtx::enter(&mut storage, || {
637 let mut slot0 = u128::handle(base_slot, LayoutCtx::packed(0), address);
638 slot0.write(val0).unwrap();
639
640 let read_val = slot0.read().unwrap();
642 assert_eq!(read_val, val0);
643 });
644
645 let loaded_slot = storage.sload(address, base_slot).unwrap();
647 let expected = gen_word_from(&["0x123456789ABCDEF0FEDCBA9876543210"]);
648 assert_eq!(loaded_slot, expected);
649
650 storage.sstore(address, base_slot, U256::ZERO).unwrap();
652
653 StorageCtx::enter(&mut storage, || {
655 let slot0 = u128::handle(base_slot, LayoutCtx::packed(0), address);
656 let cleared_val = slot0.read().unwrap();
657 assert_eq!(cleared_val, 0u128);
658 });
659
660 let val16: u128 = 0xAAAABBBBCCCCDDDD_1111222233334444;
662 StorageCtx::enter(&mut storage, || {
663 let mut slot16 = u128::handle(base_slot + U256::ONE, LayoutCtx::packed(16), address);
664 slot16.write(val16).unwrap();
665
666 let read_val = slot16.read().unwrap();
668 assert_eq!(read_val, val16);
669 });
670
671 let loaded_slot = storage.sload(address, base_slot + U256::ONE).unwrap();
673 let expected = gen_word_from(&[
674 "0xAAAABBBBCCCCDDDD1111222233334444", "0x00000000000000000000000000000000", ]);
677 assert_eq!(loaded_slot, expected);
678
679 storage
681 .sstore(address, base_slot + U256::ONE, U256::ZERO)
682 .unwrap();
683
684 StorageCtx::enter(&mut storage, || {
686 let slot16 = u128::handle(base_slot + U256::ONE, LayoutCtx::packed(16), address);
687 let cleared_val = slot16.read().unwrap();
688 assert_eq!(cleared_val, 0u128);
689 });
690 }
691
692 #[test]
693 fn test_address_at_various_offsets() {
694 let (mut storage, address) = setup_storage();
695 let base_slot = U256::from(600);
696
697 let addr0 = Address::from([0x12; 20]);
699 StorageCtx::enter(&mut storage, || {
700 let mut slot0 = Address::handle(base_slot, LayoutCtx::packed(0), address);
701 slot0.write(addr0).unwrap();
702
703 let read_val = slot0.read().unwrap();
705 assert_eq!(read_val, addr0);
706 });
707
708 let loaded_slot = storage.sload(address, base_slot).unwrap();
710 let expected = gen_word_from(&["0x1212121212121212121212121212121212121212"]);
711 assert_eq!(loaded_slot, expected);
712
713 storage.sstore(address, base_slot, U256::ZERO).unwrap();
715
716 StorageCtx::enter(&mut storage, || {
718 let slot0 = Address::handle(base_slot, LayoutCtx::packed(0), address);
719 let cleared_val = slot0.read().unwrap();
720 assert_eq!(cleared_val, Address::ZERO);
721 });
722
723 let addr12 = Address::from([0xAB; 20]);
725 StorageCtx::enter(&mut storage, || {
726 let mut slot12 = Address::handle(base_slot + U256::ONE, LayoutCtx::packed(12), address);
727 slot12.write(addr12).unwrap();
728
729 let read_val = slot12.read().unwrap();
731 assert_eq!(read_val, addr12);
732 });
733
734 let loaded_slot = storage.sload(address, base_slot + U256::ONE).unwrap();
736 let expected = gen_word_from(&[
737 "0xABABABABABABABABABABABABABABABABABABABAB", "0x000000000000000000000000", ]);
740 assert_eq!(loaded_slot, expected);
741
742 storage
744 .sstore(address, base_slot + U256::ONE, U256::ZERO)
745 .unwrap();
746
747 StorageCtx::enter(&mut storage, || {
749 let slot12 = Address::handle(base_slot + U256::ONE, LayoutCtx::packed(12), address);
750 let cleared_val = slot12.read().unwrap();
751 assert_eq!(cleared_val, Address::ZERO);
752 });
753 }
754
755 #[test]
756 fn test_bool_at_various_offsets() {
757 let (mut storage, address) = setup_storage();
758 let base_slot = U256::from(700);
759
760 let val0 = true;
762 StorageCtx::enter(&mut storage, || {
763 let mut slot0 = bool::handle(base_slot, LayoutCtx::packed(0), address);
764 slot0.write(val0).unwrap();
765
766 let read_val = slot0.read().unwrap();
768 assert_eq!(read_val, val0);
769 });
770
771 let loaded_slot = storage.sload(address, base_slot).unwrap();
773 let expected = gen_word_from(&["0x01"]);
774 assert_eq!(loaded_slot, expected);
775
776 storage.sstore(address, base_slot, U256::ZERO).unwrap();
778
779 StorageCtx::enter(&mut storage, || {
781 let slot0 = bool::handle(base_slot, LayoutCtx::packed(0), address);
782 let cleared_val = slot0.read().unwrap();
783 assert!(!cleared_val);
784 });
785
786 let val31 = false;
788 StorageCtx::enter(&mut storage, || {
789 let mut slot31 = bool::handle(base_slot + U256::ONE, LayoutCtx::packed(31), address);
790 slot31.write(val31).unwrap();
791
792 let read_val = slot31.read().unwrap();
794 assert_eq!(read_val, val31);
795 });
796
797 let loaded_slot = storage.sload(address, base_slot + U256::ONE).unwrap();
799 let expected = gen_word_from(&[
800 "0x00", "0x00000000000000000000000000000000000000000000000000000000000000", ]);
803 assert_eq!(loaded_slot, expected);
804
805 storage
807 .sstore(address, base_slot + U256::ONE, U256::ZERO)
808 .unwrap();
809
810 StorageCtx::enter(&mut storage, || {
812 let slot31 = bool::handle(base_slot + U256::ONE, LayoutCtx::packed(31), address);
813 let cleared_val = slot31.read().unwrap();
814 assert!(!cleared_val);
815 });
816 }
817
818 #[test]
819 fn test_u256_fills_entire_slot() {
820 let (mut storage, address) = setup_storage();
821 let base_slot = U256::from(800);
822
823 let val = U256::from(0x123456789ABCDEFu64);
825 StorageCtx::enter(&mut storage, || {
826 let mut slot = Slot::<U256>::new(base_slot, address);
827 slot.write(val).unwrap();
828 });
829
830 let loaded_slot = storage.sload(address, base_slot).unwrap();
831 assert_eq!(loaded_slot, val, "U256 should match slot contents exactly");
832
833 StorageCtx::enter(&mut storage, || {
835 let slot = Slot::<U256>::new(base_slot, address);
836 let recovered = slot.read().unwrap();
837 assert_eq!(recovered, val, "U256 load failed");
838 });
839 }
840
841 #[test]
842 fn test_primitive_delete_clears_slot() {
843 let (mut storage, address) = setup_storage();
844 let base_slot = U256::from(900);
845
846 let val: u64 = 0x123456789ABCDEF0;
848 StorageCtx::enter(&mut storage, || {
849 let mut slot = Slot::<u64>::new(base_slot, address);
850 slot.write(val).unwrap();
851 });
852
853 let slot_before = storage.sload(address, base_slot).unwrap();
855 assert_ne!(
856 slot_before,
857 U256::ZERO,
858 "Slot should be non-zero before delete"
859 );
860
861 StorageCtx::enter(&mut storage, || {
863 let mut slot = Slot::<u64>::new(base_slot, address);
864 slot.delete().unwrap();
865 });
866
867 let slot_after = storage.sload(address, base_slot).unwrap();
869 assert_eq!(slot_after, U256::ZERO, "Slot should be zero after delete");
870
871 StorageCtx::enter(&mut storage, || {
873 let slot = Slot::<u64>::new(base_slot, address);
874 let loaded = slot.read().unwrap();
875 assert_eq!(loaded, 0u64, "Loaded value should be 0 after delete");
876 });
877 }
878}