Skip to content

Commit ce2bdae

Browse files
authored
Merge f2f6e8e into eac6336
2 parents eac6336 + f2f6e8e commit ce2bdae

14 files changed

+2736
-0
lines changed

ERCS/erc-7844.md

Lines changed: 568 additions & 0 deletions
Large diffs are not rendered by default.

assets/erc-7844/Adaptability.svg

Lines changed: 1 addition & 0 deletions
Loading

assets/erc-7844/Architecture.svg

Lines changed: 1 addition & 0 deletions
Loading

assets/erc-7844/BasicInteractionFlow.svg

Lines changed: 1 addition & 0 deletions
Loading

assets/erc-7844/CDSInitExpansion.svg

Lines changed: 1 addition & 0 deletions
Loading

assets/erc-7844/CDSMinimal.sol

Lines changed: 314 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,314 @@
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+
}

assets/erc-7844/FirstInitCreateStorageMetadata.svg

Lines changed: 1 addition & 0 deletions
Loading

assets/erc-7844/LiveDataStorage.svg

Lines changed: 1 addition & 0 deletions
Loading

assets/erc-7844/ScalingCDS.svg

Lines changed: 1 addition & 0 deletions
Loading

assets/erc-7844/ScalingDiamonds.svg

Lines changed: 1 addition & 0 deletions
Loading

0 commit comments

Comments
 (0)