Skip to content

Conversation

@d1r1
Copy link
Contributor

@d1r1 d1r1 commented Sep 15, 2025

Refactor Storage System to Solidity-Compatible Layout

Summary

This PR completely refactors the storage system to provide a more ergonomic, type-safe API while maintaining full Solidity storage layout compatibility.

Key Changes

API Improvements

  • Replace solidity_storage! macro with #[derive(Storage)] for better IDE support and Rust idioms
  • Introduce strongly-typed storage primitives (StorageU256, StorageAddress, StorageMap, etc.)
  • Add automatic storage packing for types smaller than 32 bytes
  • Support composable storage structures through nested derives

Technical Enhancements

  • Implement proper Solidity storage layout rules (slot allocation, packing, keccak256 hashing)
  • Add native support for alloy types in storage codec
  • Optimize storage access with direct slot manipulation for primitives
  • Provide accessor methods for clean read/write operations

Migration Impact

  • Updated all examples to use the new storage API
  • Simplified ERC20 implementation demonstrating the new patterns
  • Added comprehensive tests for storage layout verification

Breaking Changes

  • Old solidity_storage! macro is deprecated
  • Storage fields are now accessed through auto-generated accessor methods (e.g., self.balance_accessor())
  • Storage types must use new Storage* wrappers

Example

// Before
solidity_storage! {
    mapping(Address => U256) Balance;
}

// After
#[derive(Storage)]
pub struct Contract<SDK> {
    sdk: SDK,
    balances: StorageMap<Address, StorageU256>,
}

// Usage
impl<SDK> Contract<SDK> {
    pub fn get_balance(&self, addr: Address) -> U256 {
        self.balances_accessor().entry(addr).get(&self.sdk)
    }
}

d1r1 added 16 commits September 11, 2025 13:50
Add PrimitiveCodec implementations for Uint, Signed, and FixedBytes types
from alloy_primitives. Also add support for Rust primitive signed integers
(i8-i128) and u128/usize. Remove redundant MapKey implementations for
signed integers as they're now covered by the generic PrimitiveCodec impl.

- Implement PrimitiveCodec for Uint<BITS, LIMBS> (8-256 bits)
- Implement PrimitiveCodec for Signed<BITS, LIMBS> (8-256 bits)
- Implement PrimitiveCodec for FixedBytes<N> (1-32 bytes)
- Add support for Rust primitive types: i8-i128, u128, usize, isize
- Add comprehensive test coverage for all new types
Refactor storage module to simplify the API and remove unnecessary type bounds.
Major breaking changes to constants, traits, and vector operations to provide
a cleaner and more ergonomic interface for storage operations.

- Rename StorageLayout constants: REQUIRED_SLOTS to SLOTS, ENCODED_SIZE to BYTES
- Rename PrimitiveCodec trait to PackableCodec for clarity
- Remove composite module and integrate functionality directly
- Add manual Copy/Clone implementations to avoid unnecessary T: Copy bounds
- Change vector API: push/pop to grow/shrink for complex types
- Add specialized push/pop methods for vectors of primitive types
@dmitry123 dmitry123 merged commit b46b1c1 into devel Sep 15, 2025
4 checks passed
@dmitry123 dmitry123 deleted the fix/storage-sol branch September 15, 2025 12:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants