Solidity’s new Custom Storage Layout Feature: Simplifying EIP 7702 Smart Accounts
Solidity 0.8.29 introduces a new feature: Custom Storage Layouts. This update allows developers to explicitly define where in storage their…
Solidity’s new Custom Storage Layout Feature: Simplifying EIP 7702 Smart Accounts
Solidity 0.8.29 introduces a new feature: Custom Storage Layouts. This update allows developers to explicitly define where in storage their contract variables start. This is very useful specifcally for EIP 7702 smart contract account implementations. EIP-7702 introduces a new transaction type that allows EOAs (regular wallets) to have code and behave as smart contracts. In this post you will understand how custom storage layouts are leveraged to avoid storage collision between the different smart account implementations a user can upgrade their EOA to over time. If you are not familiar with EIP 7702 this is a must primer before you continue reading.
Ethereum Storage Recap
Ethereum smart contracts store their state in storage slots, which are 32-byte spaces identified sequentially, starting from zero. Traditionally, Solidity assigns these slots automatically based on the declaration order:
contract StorageExample {
uint256 public firstVariable; // Slot 0
address public secondVariable; // Slot 1
bool public thirdVariable; // Slot 1 (packed)
mapping(uint256 => uint256) public mappingVariable; // Slot 2 (base slot , combined with key to retrive mapping values))
}
Storage Collisions in Upgradeable Contracts
Upgradeable contracts separate their storage which resides in the Proxy contract from logic which resides in the implementation contract. Similarly EIP 7702 smart accounts separate their state at the EOA level from the smart contract logic the EOA upgraded to. During upgrades, storage collisions can happen if the new implementation mistakenly reuses slots from the previous version. For example look at these two EIP 7702 Smart wallet implementations:
// Initial implementation
contract WalletV1 {
address public owner; // Slot 0
uint256 public nonce; // Slot 1
}
// New implementation
contract WalletV2 {
address public owner; // Slot 0 (safe)
uint256 public threshold; // Slot 1 (collision!)
}
Here, threshold incorrectly inherits the value of the previous nonce which can lead to unintented consquences. If a user upgraded their EOA from WalletV1 to WalletV2 this would lead to unintended possibly dangerous consequences.
Previous Solutions and Their Limitations
One method often used to avoid storage collision in upgradable contracts it to use storage gaps:
contract ChildUpgradeableContract {
uint256 public value;
address public owner;
// Reserved storage for future upgrades
uint256[48] private __gap;
}
contract Parent is ChildUpgradeableContract{
uint parentDummy;
}
However, managing these gaps is complicated and error-prone as it requires good knowledge of slot packing as well as solidity’s inheritance linearization for more complex inheritance set ups. Furthermore this would not work for EIP 7702 upgradability because new contracts have no knowledge of previous ones and are most likely completely unrelated.
ERC-7201 provides alternative solution by using storage namespaces in order to store variables at a dedicated space within the 2²⁵⁶-1 large storage space making collision virtually impossible.
struct AccountStorage {
address owner;
uint256 balance;
}
function _getAccountStorage() internal pure returns (AccountStorage storage s) {
bytes32 position = keccak256("account.storage");
assembly { s.slot := position }
}
function setOwner(address newOwner) external {
AccountStorage storage s = _getAccountStorage();
s.owner = newOwner;
}
While less error prone this includes low level assembly code and is quite verbose.
A Cleaner Approach: Custom Storage Layout
Solidity 0.8.29’s custom storage layout feature offers a simpler, cleaner solution:
pragma solidity ^0.8.29;
contract CustomStorage layout at keccak256("account.storage") {
address public owner; // slot keccak256("account.storage")
uint256 public balance; // slot keccak256("account.storage") + 1
}
This new syntax places storage layout at slot keccak256(“account.storage”instead of laying out storage starting at slot 0 which is solidity’s default behaviour. Now while this cannot really be leveraged by traditional upgradable contracts this is very useful for EIP 7702 upgradable smart account. This is because new dapps or wallets pushing the user to upgrade their EOAs to a new smart account implementation just want a totally fresh and unused storage space. Essentially this works similar to a ERC-7201 namespace implementation in which you would wrap the full state of the smart contract in one struct. In both cases the risk of collision is virtually non existent with a storage space as large as ²⁵⁶-1 storage slot.
Compare the old way avoiding storage collision when using ERC7201:
contract ERC7201Example {
// Define a namespace for account-related storage
/// @custom:storage-location erc7201:account.storage
struct AccountStorage {
address owner;
uint256 balance;
mapping(address => bool) authorizedUsers;
}
// This is where the magic happens - Solidity computes storage locations
// based on the namespace ID rather than sequential slot assignment
function _getAccountStorage() internal pure returns (AccountStorage storage s) {
bytes32 position = keccak256("account.storage");
assembly {
s.slot := position
}
}
// Example function using the namespaced storage
function setOwner(address newOwner) external {
AccountStorage storage s = _getAccountStorage();
s.owner = newOwner;
}
}
To the new solidity syntax:
contract CustomStorageExample layout at keccak256("account.storage") {
// Regular state variables - no struct needed!
address public owner;
uint256 public balance;
mapping(address => bool) public authorizedUsers;
// No assembly required!
function setOwner(address newOwner) external {
owner = newOwner;
}
}
Have fun using the new syntax!
메타데이터
- post_id
- e2efefd0389d
- slug
- soliditys-new-custom-storage-layout-feature-simplifying-eip-7702-smart-accounts-e2efefd0389d
- url
- https://medium.com/@letsgetonchain/soliditys-new-custom-storage-layout-feature-simplifying-eip-7702-smart-accounts-e2efefd0389d
- canonical_url
- https://medium.com/@letsgetonchain/soliditys-new-custom-storage-layout-feature-simplifying-eip-7702-smart-accounts-e2efefd0389d
- author_url
- https://medium.com/@letsgetonchain
- status
- ok
- fetched_at
- 2026-07-24 17:16:13