Skip to content
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

Inconsistent view/pure semantic restrictions related to storage pointers #15886

Open
Philogy opened this issue Feb 23, 2025 · 0 comments
Open
Labels

Comments

@Philogy
Copy link

Philogy commented Feb 23, 2025

Description

  • The compiler requires internal functions that index into storage mappings just to return a storage pointer not read the actual contents be marked view.
  • When manually creating & assigning the slot of a struct storage pointer via inline assembly the compiler does not impose the same constraint of requiring the method to be marked view, it accepts pure
  • Furthermore a public function that calls the pure, storage pointer returning method just to publicly return the struct as a memory struct (implicitly reading storage) the compiler does not require said function to be marked view

Intuitively one would expect that neither creation of the storage pointer (assembly or vanilla Solidity) should be view as it does not actually read storage yet, simply create a stack variable based on some inputs. However casting a storage pointer to a memory struct which requires reading the storage pointer should be marked as an environment touching operation.

Environment

  • Compiler version: v0.8.25 / v0.8.28
  • Compilation pipeline (legacy, IR, EOF): legacy & via-IR
  • Target EVM version (as per compiler settings): paris, shanghai, cancun
  • Framework/IDE (e.g. Foundry, Hardhat, Remix): foundry
  • EVM execution environment / backend / blockchain client: standard
  • Operating system: macOS (apple silicon)

Steps to Reproduce

Example

struct TestStruct {
    uint256 value;
}

mapping(bytes32 => TestStruct) _map;

/// @dev Compiler ❌ ERROR: At least visibility of *view* required.
function _get_no_assembly(bytes32 key) internal pure returns (TestStruct storage state) {
    state = _map[key];
}

/// @dev Compiler accepts ✅
function _get_assembly(bytes32 key) internal pure returns (TestStruct storage state) {
    assembly ("memory-safe") {
        mstore(0x00, key)
        mstore(0x20, _map.slot)
        state.slot := keccak256(0x00, 0x40)
    }
}

/// @dev Implicit storage read passes as *pure*
function pub_get(bytes32 key) public pure returns (TestStruct memory) {
    return _get_assembly(key);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

1 participant