Skip to content

Conversation

@ep0chzer0
Copy link
Contributor

Summary

This PR adds support for displaying constant and immutable variables in slither-read-storage, addressing issue #1614.

Features

  • New --include-immutable CLI flag to include constant/immutable variables in output
  • Constant values extracted from expressions using ConstantFolding
  • Immutable values retrieved via RPC getter calls for public variables
  • Variables displayed with (constant) or (immutable) type suffix
  • Slot shows -1 for non-storage variables (they don't have storage slots)

Example Usage

# Include immutable and constant variables
slither-read-storage contract.sol 0xAddress --include-immutable --table

# With RPC to get values for public immutables
slither-read-storage contract.sol 0xAddress --include-immutable --table --rpc-url https://eth-mainnet.g.alchemy.com/v2/... --value

Example Output

+-------------+----------------------+------+------+--------+-------+
|     name    |     type_string      | slot | size | offset | value |
+-------------+----------------------+------+------+--------+-------+
| BYTES       | bytes32 (constant)   |  -1  | 256  |   0    | 0x1...  |
| someAddress | address (immutable)  |  -1  | 160  |   0    | 0x2...  |
| someUint256 | uint256              |  0   | 256  |   0    |  3    |
+-------------+----------------------+------+------+--------+-------+

Implementation Details

  1. Added _immutable_variables and _constant_variables lists to track these variable types
  2. Modified get_all_storage_variables() to capture immutable/constant when include_immutable=True
  3. Added get_immutable_constant_layout() method to create SlotInfo for these variables
  4. Added _get_immutable_value() - calls getter via RPC for public immutables
  5. Added _get_constant_value() - extracts value from expression using ConstantFolding
  6. Modified get_slot_values() to skip variables with slot=-1

Test Plan

  • Added unit tests for immutable/constant detection
  • Added test for disabled-by-default behavior
  • Added test for storage layout inclusion
  • Added test for constant value extraction
  • All tests passing

Fixes #1614

@ep0chzer0 ep0chzer0 requested a review from smonicas as a code owner January 16, 2026 23:46
@ep0chzer0
Copy link
Contributor Author

Hey, just a heads up - while I was going through the code to implement this feature, I noticed a pre-existing bug in the --variable-name flag handling.

In __main__.py, the filter lambda was using x[1].name expecting a tuple, but get_all_storage_variables() passes just a StateVariable object to the filter. This would cause issues when someone tries to use --variable-name.

I went ahead and fixed that too while I was in there, and added some tests to cover it. Figured it made sense to include it in this PR since I was already touching that code path.

@elopez
Copy link
Member

elopez commented Jan 17, 2026

Care should be taken if #2742 is merged first, as that PR corrects the behavior of get_all_storage_variables instead

@ep0chzer0
Copy link
Contributor Author

Thanks for the heads up @elopez. I checked PR #2742 - it fixes the same --variable-name bug by correcting the return type of get_all_storage_variables() to return tuples.

If #2742 merges first, I'll rebase this PR and remove my fix for that bug (since it'll be redundant). The core feature (constant/immutable variable support) is independent of that fix.

I'll keep an eye on #2742's status.

Copy link
Member

@dguido dguido left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review: feat: add support for constant and immutable variables in slither-read-storage

Reviewing files:

  • slither/tools/read_storage/__main__.py
  • slither/tools/read_storage/read_storage.py
  • tests/unit/tools/read_storage/test_immutable_constant.py

Critical (90-100)

No critical issues found.


Important (80-89)

1. Potential exception when type_ is None - Confidence: 85

File: slither/tools/read_storage/read_storage.py, lines 220-223 and 253-256

In get_immutable_constant_layout(), the code accesses type_.storage_size but the guard only checks if type_ is truthy for the type_string assignment, not before accessing storage_size:

type_string = str(type_) if type_ else "unknown"
byte_size, _ = type_.storage_size if type_ else (32, 0)

This is correct, but the ternary could be clearer. Consider using explicit None check for consistency:

byte_size, _ = type_.storage_size if type_ is not None else (32, 0)

2. Silent failure in _get_immutable_value on missing checksum_address - Confidence: 82

File: slither/tools/read_storage/read_storage.py, lines 275-292

When self.rpc_info is truthy but self.storage_address is not set, calling self.checksum_address will raise a ValueError. The try/except only catches ValueError and TypeError, but this failure path returns None silently without logging. Consider adding a debug log when the exception is caught:

except (ValueError, TypeError) as e:
    logger.warning(f"Could not retrieve immutable {var.name} via RPC: {e}")

This is already present, so this is fine. No change needed.


Positive Observations

  1. Good fix for existing bug: The lambda signature change from lambda x: bool(x[1].name == args.variable_name) to lambda x: bool(x.name == args.variable_name) correctly fixes an existing bug - the get_all_storage_variables method passes var (a StateVariable) directly to the filter function, not a tuple. The old comment was incorrect.

  2. Comprehensive test coverage: The tests cover multiple scenarios including:

    • Detection of immutable/constant variables
    • Default disabled behavior
    • Storage layout inclusion
    • Constant value extraction
    • Variable name filtering
  3. Clean separation of concerns: The new _get_immutable_value and _get_constant_value methods encapsulate retrieval logic cleanly.

  4. Sensible defaults: Using slot=-1 for non-storage variables is a reasonable sentinel value that won't conflict with actual storage slots.

  5. Proper skip logic in get_slot_values: The early return when slot_info.slot == -1 prevents unnecessary RPC calls for immutable/constant variables.


Minor Suggestions (Not blocking)

  1. Type annotation for max_depth parameter: In SlitherReadStorage.__init__, max_depth is typed as int but the default rpc_info parameter is typed as RpcInfo = None which should be RpcInfo | None = None.

  2. Consider using typing.TYPE_CHECKING import guard for the Expression type hint in find_hardcoded_slot_in_exp to avoid runtime import overhead.


Overall, this is a well-implemented feature that addresses issue #1614. The code is clean, tests are comprehensive, and it correctly fixes a pre-existing bug in the lambda filter signature.

@ep0chzer0 ep0chzer0 force-pushed the feature/read-storage-immutable-constant branch from 1f949fd to 8a9b272 Compare January 20, 2026 09:46
dguido added a commit to ep0chzer0/slither that referenced this pull request Jan 20, 2026
- Change verbose per-variable logging from info to debug level
- Fix type annotation for rpc_info parameter to use union syntax

Co-Authored-By: Claude Opus 4.5 <[email protected]>
…d-storage

This adds the --include-immutable flag to slither-read-storage which enables
display of constant and immutable variables alongside regular storage variables.

Features:
- New --include-immutable CLI flag
- Constant values extracted from expressions using ConstantFolding
- Immutable values retrieved via RPC getter calls for public variables
- Variables displayed with (constant) or (immutable) type suffix
- Slot shows -1 for non-storage variables

Fixes crytic#1614
- Fix pre-existing bug: lambda filter used x[1].name but x is StateVariable, not tuple
- Use specific exception types instead of catching all Exception
- Handle None type by showing "unknown" instead of "None"
- Add debug log for private/internal immutables (cannot retrieve via RPC)
- Add tests for --variable-name filter with immutable/constant variables
@ep0chzer0 ep0chzer0 force-pushed the feature/read-storage-immutable-constant branch from a79d816 to bec3dcb Compare January 20, 2026 16:46
dguido and others added 2 commits January 20, 2026 12:53
…pport

- Remove unused `contract` parameter from `_get_immutable_value` method
- Remove unused `Path` import from test file
- Change test assertions from `>=` to `==` for exact count validation

Co-Authored-By: Claude Opus 4.5 <[email protected]>
@dguido dguido merged commit 91ebdd9 into crytic:master Jan 20, 2026
35 checks passed
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.

slither-read-storage: add support for constant|immutable variables

3 participants