-
Notifications
You must be signed in to change notification settings - Fork 348
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
✨ SSTORE2 should chunk saves to circumvent the 4M gas limit! #399
Comments
Have been thinking about this myself, I'm a fan for sure 👏. While impractical due to gas, this could be used to store a somewhat high resolution image on-chain. |
Yes that's a good point, the client should probably do the chunking to save gas. So here is my revised proposal which I think is pretty good! Would be even better integrated into SSTORE2 of course. library ChunkedSSTORE2Lib {
struct ByteChunks {
address[] locations;
}
function writeChunks(bytes[] memory chunks) internal returns (ByteChunks memory) {
address[] memory locations = new address[](chunks.length);
for (uint i; i < locations.length;) {
locations[i] = SSTORE2.write(chunks[i]);
unchecked {++i;}
}
return ChunkedSSTORE2Lib.ByteChunks(locations);
}
// AddressChunks by @xtremetom
// https://github.com/intartnft/scripty.sol/blob/main/contracts/scripty/utils/AddressChunks.sol
function readChunks(ByteChunks memory blob) internal view returns (bytes memory combinedBytes) {
address[] memory chunks = blob.locations;
unchecked {
assembly {
let len := mload(chunks)
let totalSize := 0x20
let size := 0
combinedBytes := mload(0x40)
// loop through all chunk addresses
// - get address
// - get data size
// - get code and add to o_code
// - update total size
let targetChunk := 0
for {
let i := 0
} lt(i, len) {
i := add(i, 1)
} {
targetChunk := mload(add(chunks, add(0x20, mul(i, 0x20))))
size := sub(extcodesize(targetChunk), 1)
extcodecopy(targetChunk, add(combinedBytes, totalSize), 1, size)
totalSize := add(totalSize, size)
}
// update o_code size
mstore(combinedBytes, sub(totalSize, 0x20))
// store o_code
mstore(0x40, add(combinedBytes, and(add(totalSize, 0x1f), not(0x1f))))
}
}
}
} |
I am using a similar approach in EthFS, with the additional feature of allowing you to specify exactly the bytecode start/end for each address to support reusing bytecode from any arbitrary contract, not just ones stored via SSTORE2: https://github.com/holic/ethfs/blob/main/packages/contracts/src/File.sol |
This gas limit is artificial and users shouldn't have to juggle it themselves. This is similar to automatically increasing the buffer when the user appends "too much" in DynamicBuffer. Many users are sheeple and cannot handle the complexity themselves!
Like with DynamicBuffer, SSTORE2 could operate with a custom struct that abstracts away these inessential details.
Something like:
Yes, this would mean that our children will store data on Ethereum without truly learning it goes into an address and how weird and cute that is, but I think it's worth it!
Here's something I found that handles the read side:
Thoughts?
The text was updated successfully, but these errors were encountered: