@@ -6,17 +6,26 @@ const header = `\
66pragma solidity ^0.8.20;
77
88import {Test} from "forge-std/Test.sol";
9-
9+ import {SymTest} from "halmos-cheatcodes/SymTest.sol";
1010import {SlotDerivation} from "@openzeppelin/contracts/utils/SlotDerivation.sol";
1111` ;
1212
1313const array = `\
1414bytes[] private _array;
1515
16+ function symbolicDeriveArray(uint256 length, uint256 offset) public {
17+ vm.assume(length > 0);
18+ vm.assume(offset < length);
19+ _assertDeriveArray(length, offset);
20+ }
21+
1622function testDeriveArray(uint256 length, uint256 offset) public {
1723 length = bound(length, 1, type(uint256).max);
1824 offset = bound(offset, 0, length - 1);
25+ _assertDeriveArray(length, offset);
26+ }
1927
28+ function _assertDeriveArray(uint256 length, uint256 offset) public {
2029 bytes32 baseSlot;
2130 assembly {
2231 baseSlot := _array.slot
@@ -33,10 +42,10 @@ function testDeriveArray(uint256 length, uint256 offset) public {
3342}
3443` ;
3544
36- const mapping = ( { type, name, isValueType } ) => `\
45+ const mapping = ( { type, name } ) => `\
3746mapping(${ type } => bytes) private _${ type } Mapping;
3847
39- function testDeriveMapping ${ name } (${ type } ${ isValueType ? '' : 'memory' } key) public {
48+ function testSymbolicDeriveMapping ${ name } (${ type } key) public {
4049 bytes32 baseSlot;
4150 assembly {
4251 baseSlot := _${ type } Mapping.slot
@@ -52,10 +61,37 @@ function testDeriveMapping${name}(${type} ${isValueType ? '' : 'memory'} key) pu
5261}
5362` ;
5463
64+ const boundedMapping = ( { type, name } ) => `\
65+ mapping(${ type } => bytes) private _${ type } Mapping;
66+
67+ function testDeriveMapping${ name } (${ type } memory key) public {
68+ _assertDeriveMapping${ name } (key);
69+ }
70+
71+ function symbolicDeriveMapping${ name } () public {
72+ _assertDeriveMapping${ name } (svm.create${ name } (256, "DeriveMapping${ name } Input"));
73+ }
74+
75+ function _assertDeriveMapping${ name } (${ type } memory key) internal {
76+ bytes32 baseSlot;
77+ assembly {
78+ baseSlot := _${ type } Mapping.slot
79+ }
80+
81+ bytes storage derived = _${ type } Mapping[key];
82+ bytes32 derivedSlot;
83+ assembly {
84+ derivedSlot := derived.slot
85+ }
86+
87+ assertEq(baseSlot.deriveMapping(key), derivedSlot);
88+ }
89+ ` ;
90+
5591// GENERATE
5692module . exports = format (
5793 header . trimEnd ( ) ,
58- 'contract SlotDerivationTest is Test {' ,
94+ 'contract SlotDerivationTest is Test, SymTest {' ,
5995 'using SlotDerivation for bytes32;' ,
6096 '' ,
6197 array ,
@@ -68,6 +104,6 @@ module.exports = format(
68104 isValueType : type . isValueType ,
69105 } ) ) ,
70106 ) ,
71- ) . map ( type => mapping ( type ) ) ,
107+ ) . map ( type => ( type . isValueType ? mapping ( type ) : boundedMapping ( type ) ) ) ,
72108 '}' ,
73109) ;
0 commit comments