sstore3
is a hyper-optimized method for reading and writing contract storage. It seeks to fill the gap for cheap short-form data storage, whereas sstore2
has achieved an efficiency upgrade for long-form over the standard sstore
.
sstore3
for example offers contract read and write storage for less than half the costs of standard store
.
sstore3
consists of two chief methods that are native to addresses themselves: (1) the wei balance
of an address, and (2) the address
0x itself for short-form data storage, such as price, status or contract type flags.
The selfbalance()
opcode has a fixed cost of 5
gas. It is therefore a convenient and technically mutable source of state change for a public contract.
// SPDX-License-Identifier: AGPL-3.0-only
pragma solidity ^0.8.19;
contract sstore3 {
function store() public payable {}
function data() public view returns (uint256 bits) {
assembly ("memory-safe") {
bits := selfbalance()
}
}
}
Tests demonstrating this approach: π
A public contract that uses the sstore3
balance method should take some care to guard a deposit (payable) function so that it is not trivial to update the contract's wei balance. This introduces no new costs to the normal methods of guarded storage (for example, an owner-only function that performs a sstore
or creates a contract via sstore2
).
For example:
function store() public payable onlyOwner {}
Here, the onlyOwner
modifier should enforce the right to call this storage function.
The sstore3
balance method can potentially be abused by either self-destructing a contract or withdrawing consensus layer rewards in order to force a wei balance change on an otherwise guarded public contract.
Depending on the exact application this attack vector can span from a low-severity griefing attack to a critical vulnerability!
A safe example here, where these considerations still wouldn't matter, would be a public contract with a "flip the switch" initialization state where the authors don't care who calls to turn on this state (or actually want to disclaim this responsibility altogether), such as, for example, "unpausing" the transferability of a token.
In such event, the token contract and the public would be able to sync this new state the moment it receives a wei.
Data can also be cheaply associated with and effectively stored into a contract through its 0x address. For example, Uniswap V4 pool contracts utilize the address profile in order to determine configuration status, and some contracts might check whether an address starts with a certain number of zeros to flag if it should be treated as immutable by a contract.
In this similar fashion, sstore3
address method anticipates using create2crunch
or similar address mining technique to locate and deploy bytecode to specific addresses that follow a protocol's storage conventions. sstore3
is agnostic to how these conventions may themselves be developed, but a few examples may aid in understanding the application.
To illustrate, the address 0x000000004f5b1f858B5D96cc0d013b8867A5fF60
might contain arbitrary logic but calls to this logic can be framed according to a convention that follows the proposed sstore3
address method.
To illustrate further, consider that a calling contract might read this address from storage but then otherwise want more data in order to correctly call this address according to its protocol. Typically, this would involve another call or reading more data from local storage.
Alternatively, and more efficiently, this protocol could be designed such that if an address has four leading 0
(0x00000000
) bytes, rather than 1
, calls to such address will follow the ERC20 interface rather than the ERC721 interface. Additionally, the number 4
directly following might be a signifier to external applications that the callee contract is on its version 4
and includes a certain ABI format.
The point in all of the above being, to reduce and remove any redundant bytecode or onchain interactions that can elaborate information about a contract by being contained in the contract address itself using create2
.
Run: curl -L https://foundry.paradigm.xyz | bash && source ~/.bashrc && foundryup
Build the foundry project with forge build
. Run tests with forge test
. Measure gas with forge snapshot
. Format with forge fmt
.
lib
ββ forge-std β https://github.com/foundry-rs/forge-std
src
ββ sstore1 β standard store
ββ sstore2 β sstore2 example
ββ sstore3 β sstore3 example
test
ββ sstore1.t β test standard
ββ sstore2.t β test sstore2
ββ sstore3.t - test sstore3
These smart contracts and testing suite are being provided as is. No guarantee, representation or warranty is being made, express or implied, as to the safety or correctness of anything provided herein or through related user interfaces. This repository and related code have not been audited and as such there can be no assurance anything will work as intended, and users may experience delays, failures, errors, omissions, loss of transmitted information or loss of funds. The creators are not liable for any of the foregoing. Users should proceed with caution and use at their own risk.
See LICENSE for more details.