1+ // SPDX-License-Identifier: CC0-1.0
2+
3+ /**
4+ * @title Consolidated Dynamic Storage - Basic Example
5+ * @author Cameron Warnick github.com/wisecameron, x.com/wisecameroneth
6+ * @notice Barebones CDS implementation - does not include optimization or safety checks.
7+ */
8+ pragma solidity ^ 0.8.0 ;
9+
10+ contract CDSMinimal
11+ {
12+ constructor (){}
13+
14+ uint256 storageSpaces;
15+ uint256 constant MEMBERS_LIM = 1000 ;
16+ uint256 constant ENTRIES_LIM = 5000000000 ;
17+
18+ /**
19+ * @notice Minimal, unoptimized example of init_create to demonstrate core logic.
20+ * Safety checks (e.g., input validation, bounds checking) are omitted for simplicity.
21+ * Production implementations must add these checks to ensure robustness.
22+ * This implementation follows the spec precisely.
23+ */
24+ function init_create (
25+ uint256 [] memory types ,
26+ uint256 [] memory sizes
27+ ) external
28+ {
29+ uint256 bitCount;
30+ uint256 safeIndex;
31+ uint256 stringIndex;
32+ uint256 len = sizes.length ;
33+
34+ storageSpaces += 1 ;
35+ uint256 ROOT_SLOT = _get_root_slot (storageSpaces - 1 );
36+
37+ for (uint256 i = 0 ; i < len; i++ )
38+ {
39+ //validate size given type (omitted)
40+ uint256 valType = types[i];
41+ uint256 valSize = sizes[i];
42+
43+ if (valType < 6 )
44+ {
45+ //calculate bitCount for the new entry
46+ uint256 bitCountAsPage = (bitCount / 256 );
47+ uint256 bitCountAsPageInBits = (bitCountAsPage * 256 );
48+ uint256 bitCountOverflow = (bitCount + valSize) - bitCountAsPageInBits;
49+
50+ if (bitCountOverflow > 256 ) bitCount = (bitCountAsPage + 1 ) * 256 ;
51+
52+ uint256 packedValue;
53+ assembly
54+ {
55+ //pack {bitCount, sizes, types}
56+ packedValue := or (
57+ or (
58+ shl (128 , bitCount),
59+ shl (64 , valSize)
60+ ),
61+ valType
62+ )
63+
64+ sstore (add (ROOT_SLOT, add (1 , i)), packedValue)
65+
66+ //bitCount := bitCount + size
67+ bitCount := add (bitCount, valSize)
68+
69+ //set safeIndex to this
70+ safeIndex := i
71+ }
72+ }
73+ else
74+ {
75+ uint256 packedValue;
76+
77+ assembly
78+ {
79+ //create packedValue {stringIndex, 6}
80+ packedValue := or (
81+ shl (128 , stringIndex),
82+ 6
83+ )
84+
85+ //store the packed value in the member data of the storage space
86+ sstore (add (ROOT_SLOT, add (1 , i)), packedValue)
87+
88+ //increment stringIndex
89+ stringIndex := add (stringIndex, 1 )
90+ }
91+
92+ }
93+ }
94+
95+ //pack storage space data: {members, entries, stringIndex, safeIndex}
96+ uint256 storageSpaceMemberState;
97+
98+ assembly
99+ {
100+ storageSpaceMemberState := or (
101+ or (
102+ shl (192 , len),
103+ shl (64 , stringIndex)
104+ ),
105+ safeIndex
106+ )
107+
108+ sstore (ROOT_SLOT, storageSpaceMemberState)
109+ }
110+ }
111+
112+ /**
113+ * @notice Minimal, unoptimized example of insert_new_member to demonstrate core logic.
114+ * Safety checks (e.g., input validation, bounds checking) are omitted for simplicity.
115+ * Production implementations must add these checks to ensure robustness.
116+ * This implementation follows the spec precisely.
117+ */
118+ function insert_new_member (
119+ uint256 valType ,
120+ uint256 valSize ,
121+ uint256 storageSpace
122+ ) external
123+ {
124+ //verify type and size (omitted)
125+
126+ //retrieve memberData
127+ uint256 packedStorageSpaceStateData;
128+ uint256 membersCount;
129+
130+ uint256 ROOT_SLOT = _get_root_slot (storageSpace);
131+
132+ assembly
133+ {
134+ packedStorageSpaceStateData := sload (ROOT_SLOT)
135+ membersCount := shr (192 , packedStorageSpaceStateData)
136+ }
137+
138+ if (valType < 6 )
139+ {
140+ uint256 bitCount;
141+ uint256 prevSize;
142+ uint256 safeIndex;
143+
144+ assembly
145+ {
146+ //get safeIndex
147+ safeIndex := shr (192 , shl (192 , packedStorageSpaceStateData))
148+
149+ //get bitCount, verify size (omitted)
150+ let previousStoredValueMemberData := sload (add (ROOT_SLOT, add (1 , safeIndex)))
151+
152+ bitCount := shr (128 , previousStoredValueMemberData)
153+ prevSize := shr (64 , and (
154+ previousStoredValueMemberData,
155+ 0x00000000000000000000000000000000FFFFFFFFFFFFFFFF0000000000000000
156+ )
157+ )
158+ }
159+
160+ //get storage page, verify we will not overflow
161+ bitCount += prevSize;
162+ uint256 bitCountAsPage = (bitCount / 256 );
163+ uint256 bitCountAsPageInBits = (bitCountAsPage * 256 );
164+ uint256 bitCountOverflow = (bitCount + valSize) - bitCountAsPageInBits;
165+
166+ //if overflow, push to next page (update bitCount to head of next page)
167+ if (bitCountOverflow > 256 ) bitCount = (bitCountAsPage + 1 ) * 256 ;
168+
169+ assembly
170+ {
171+ //pack memberData
172+ let packedMemberData := or (
173+ or (
174+ shl (128 , bitCount),
175+ shl (64 , valSize)
176+ ),
177+ valType
178+ )
179+
180+ //store packedMemberData
181+ sstore (add (ROOT_SLOT, add (1 , membersCount)), packedMemberData)
182+
183+ //update safeIndex, members in state data for storage space
184+ safeIndex := membersCount
185+
186+ packedStorageSpaceStateData := or (
187+ and (
188+ packedStorageSpaceStateData, 0x0000000000000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000000000000000
189+ ),
190+ or (safeIndex, shl (192 , add (membersCount, 1 )))
191+ )
192+
193+ sstore (ROOT_SLOT, packedStorageSpaceStateData)
194+ }
195+ }
196+ else
197+ {
198+ uint256 stringIndex;
199+
200+ assembly
201+ {
202+ //get stringIndex
203+ stringIndex := shr (64 ,
204+ and (
205+ packedStorageSpaceStateData,
206+ 0x00000000000000000000000000000000FFFFFFFFFFFFFFFF0000000000000000
207+ )
208+ )
209+
210+ //pack with type
211+ let packedMemberData := or (
212+ shl (128 , stringIndex),
213+ valType
214+ )
215+
216+ //store entry in memberData
217+ mstore (0x0 , shl (
218+ 176 ,
219+ add (
220+ mul (storageSpace, MEMBERS_LIM),
221+ add (1 , membersCount))
222+ )
223+ )
224+ sstore (add (ROOT_SLOT, add (1 , membersCount)), packedMemberData)
225+
226+ //increment stringIndex, members
227+ membersCount := add (membersCount, 1 )
228+ stringIndex := add (stringIndex, 1 )
229+
230+ //store updated state data for storage space
231+ packedStorageSpaceStateData := and (
232+ packedStorageSpaceStateData, 0x0000000000000000FFFFFFFFFFFFFFFF0000000000000000FFFFFFFFFFFFFFFF
233+ )
234+
235+ packedStorageSpaceStateData := or (
236+ or (packedStorageSpaceStateData, shl (192 , membersCount)),
237+ shl (64 , stringIndex)
238+ )
239+
240+ sstore (ROOT_SLOT, packedStorageSpaceStateData)
241+ }
242+ }
243+ }
244+
245+ function get_storage_space_state_data (
246+ uint256 storageSpace
247+ ) external view returns (
248+ uint256 members ,
249+ uint256 entries ,
250+ uint256 stringIndex ,
251+ uint256 safeIndex
252+ )
253+ {
254+ uint256 ROOT_SLOT = _get_root_slot (storageSpace);
255+
256+ assembly
257+ {
258+ let packedStorageSpaceStateData := sload (ROOT_SLOT)
259+
260+ members := shr (192 , packedStorageSpaceStateData)
261+ entries := shr (128 , and (
262+ packedStorageSpaceStateData,
263+ 0x0000000000000000FFFFFFFFFFFFFFFF00000000000000000000000000000000
264+ ))
265+ stringIndex := shr (64 , and (
266+ packedStorageSpaceStateData,
267+ 0x00000000000000000000000000000000FFFFFFFFFFFFFFFF0000000000000000
268+ ))
269+ safeIndex := and (
270+ packedStorageSpaceStateData,
271+ 0x000000000000000000000000000000000000000000000000FFFFFFFFFFFFFFFF
272+ )
273+ }
274+ }
275+
276+ function get_member_data (
277+ uint256 memberIndex ,
278+ uint256 storageSpace
279+ ) external view returns (
280+ uint256 bitCount , uint256 valSize , uint256 valType )
281+ {
282+ uint256 ROOT_SLOT = _get_root_slot (storageSpace);
283+
284+ assembly
285+ {
286+ let packedStorageSpaceStateData := sload (add (ROOT_SLOT, add (1 , memberIndex)))
287+
288+ bitCount := shr (128 , packedStorageSpaceStateData)
289+ valSize := shr (64 ,
290+ and (packedStorageSpaceStateData, 0x00000000000000000000000000000000FFFFFFFFFFFFFFFF0000000000000000 )
291+ )
292+ valType := and (
293+ packedStorageSpaceStateData,
294+ 0x000000000000000000000000000000000000000000000000FFFFFFFFFFFFFFFF
295+ )
296+ }
297+ }
298+
299+ function _get_root_slot (uint256 storageSpace )
300+ internal view returns (uint256 slot )
301+ {
302+ if (storageSpace >= storageSpaces)
303+ {
304+ revert ("Invalid storage space! " );
305+ }
306+
307+ assembly
308+ {
309+ let offset := shl (176 , mul (storageSpace, MEMBERS_LIM))
310+ mstore (0x0 , offset)
311+ slot := keccak256 (0x0 , 0xA )
312+ }
313+ }
314+ }
0 commit comments