Conversation
… from a private slot (#110)
Tests are currently failing since right now we only restrict returning shielded addresses and integers.
…al fcts This fixes veridise issue 759. Moved the check from DeclarationTypeChecker to TypeChecker because with the new semantic we need to recursively check all child AST nodes (members of structs for example). Keeping the check in DeclarationTypeChecker was throwing some assert errors on some children nodes that haven't been previously been type checked themselves. Having the check done in TypeChecker also feels more natural anyways, since its checking for return types and there was already a function named checkArgumentAndReturnParameter.
4 of the tests were relying on returning shielded types, which now need to be modified to unshield the types before returning them from public functions.
Add failing tests that document the incomplete literal assignment warning for shielded types identified in the Veridise audit report. New test files demonstrating missing warnings: - warn_shielded_literal_struct.sol: Named struct field initialization - warn_shielded_literal_struct_positional.sol: Positional struct init - warn_shielded_literal_multiple_args.sol: Multiple arguments in struct - warn_shielded_fixedbytes_literal.sol: Direct sbytes literal conversion - warn_shielded_fixedbytes_literal_struct.sol: sbytes in struct These tests initially fail, documenting the gaps: 1. Only first argument checked (not all arguments) 2. Struct constructors not checked at all 3. ShieldedFixedBytes type not checked Updated existing sbytes tests to expect new warnings: - sbytes_explicit_conversions.sol - sbytes_implicit_conversions_fail.sol - sbytes_operations.sol - sbytes_size_conversions.sol - sbytes_struct.sol After the fix, all these tests will pass with proper warnings emitted.
Fix the incomplete literal assignment warning for shielded types as identified in the Veridise audit report. The original implementation only checked the first argument and missed: - Literals in non-first positions - Literals inside struct constructors - ShieldedFixedBytes type entirely Changes: - Refactored warning logic into two clear functions: * checkLiteralToShielded() - Core warning check (replaces inline code) * checkShieldedLiteralWarning() - Recursive dispatcher for complex cases - Extended coverage to all 4 shielded types: * ShieldedBool ✓ * ShieldedAddress ✓ * ShieldedInteger ✓ * ShieldedFixedBytes ✓ (NEW) - Now checks ALL arguments, not just the first - Recursively handles struct constructors (named and positional) - Cleaner code structure for auditor review All 3,709 syntax tests pass with no regressions.
This test demonstrates the bug where ArrayUtils::clearArray uses hardcoded SSTORE instead of CSTORE for small shielded arrays. The test shows that deleting shielded arrays like suint256[3] or saddress[4] incorrectly generates SSTORE instructions in the unrolled loop optimization path. This will be fixed in the next commit.
The original fix in commit 5c75476 addressed GenericStorageItem::setToZero, but ArrayUtils::clearArray had an optimization path that bypassed it. For small fixed-size arrays (storageSize <= 5), clearArray uses an unrolled loop that directly emits store instructions. This code path was using hardcoded SSTORE without checking if the base type is shielded. This meant that operations like `delete suint256[3]` would incorrectly use SSTORE instead of CSTORE, leaking private data to public storage. The fix checks if the array's base type is shielded and uses CSTORE for shielded types, SSTORE for non-shielded types. Affected code path: - ArrayUtils::clearArray lines 568-578 (unrolled loop for small arrays) Other code paths correctly use StorageItem::setToZero which handles shielded types properly after the original fix.
Tests are currently failing since right now we only restrict returning shielded addresses and integers.
4 of the tests were relying on returning shielded types, which now need to be modified to unshield the types before returning them from public functions.
…al fcts This fixes veridise issue 759. Moved the check from DeclarationTypeChecker to TypeChecker because with the new semantic we need to recursively check all child AST nodes (members of structs for example). Keeping the check in DeclarationTypeChecker was throwing some assert errors on some children nodes that haven't been previously been type checked themselves. Having the check done in TypeChecker also feels more natural anyways, since its checking for return types and there was already a function named checkArgumentAndReturnParameter.
Add tests to verify that copying shielded arrays uses cstore/cload instead of sstore/sload. These tests currently fail because the implementation hardcodes sstore/sload regardless of type shielding. Tests cover: - Memory-to-storage copy - Storage-to-storage copy - Calldata-to-storage copy - Multiple items per slot (sbool[]) Each test verifies: - Initial array length is 0 before copy - Array length after copy is correct - Array elements are correctly stored and retrieved Addresses: Veridise audit finding VER-771
This fixes a critical issue where storage array copy operations hardcoded sstore/sload regardless of whether the base type was shielded. For shielded value types like suint[] and sbool[], this would violate confidentiality guarantees and could cause reverts when accessing confidential storage slots. Changes: - Modified copyValueArrayToStorageFunction to select opcodes based on base type's isShielded() status - Fixed hardcoded sload in updateSrcPtr template to use parameterized loadOpcode for both single and multi-item-per-slot cases The generated IR now correctly emits cstore/cload for shielded arrays and sstore/sload for non-shielded arrays. Addresses: Veridise audit finding VER-771
We updated the semantics of confidential storage opcodes in SeismicSystems/seismic-revm#180. The changes here are needed to reflect the new semantics.
Run semantic tests in 4 configurations: 1. No optimizer, no IR (baseline) 2. With optimizer, no IR (baseline) 3. No optimizer, --via-ir (tests IR codegen) 4. With optimizer, --via-ir (tests optimized IR)
- shielded_array_storage_pop_zero_length.sol: Change EVMVersion from >=petersburg to >=mercury (suint[] requires CLOAD/CSTORE opcodes) - all_possible_user_defined_value_types_with_operators.sol: Add compileViaYul:false with explanatory comment (test exceeds EIP-170's 24KB contract size limit when compiled with via-IR without optimizer)
Add 4 regression tests with compileViaYul:also to ensure via-IR specific bugs are caught while maintaining non-IR test coverage: 1. shielded_struct_delete_mixed_viair.sol Tests that struct delete uses correct opcodes (sstore for uint16/uint8, cstore for sbytes1) when clearing mixed shielded/non-shielded fields. Prevents regression of clearStorageStructFunction bug. 2. sbytes_dynamic_packed_storage_viair.sol Tests sbytes1 array operations (push, index read, index write) use numBytes() not storageBytes() for shift/mask in packed storage. Prevents regression of packed storage bugs. 3. sbytes_abi_encoding_viair.sol Tests storage-to-memory copy uses cload not sload for sbytes arrays. Prevents regression of abiEncodingFunctionCompactStorageArray bug. 4. timestamp_magic_viair.sol Tests block.timestamp_seconds and block.timestamp_ms generate correct IR (timestamp() and timestampms() respectively). Prevents regression of IR timestamp member bug. All tests use compileViaYul:also to run in both IR and non-IR modes, ensuring comprehensive coverage and regression prevention.
Fixes all remaining issues blocking via-IR compilation for shielded types. Test results: 1641/1642 pass without optimizer (99.94%), 1642/1642 with optimizer (100%). Single failure is unrelated contract size limit. Issue 1: clearStorageStructFunction used wrong opcode for mixed structs - Problem: Mixed structs (uint16 + sbytes) used cstore for ALL fields - Fix: All shielded types have storageBytes()==32, so <32 branch is non-shielded only. Hardcode sstore with defensive assertion. - File: libsolidity/codegen/YulUtilFunctions.cpp:1915-1931 Issue 2: IR timestamp magic members called non-existent functions - Problem: Generated IR called timestamp_seconds() and timestamp_ms() - Fix: Map timestamp_seconds to timestamp(), timestamp_ms to timestampms() - File: libsolidity/codegen/ir/IRGeneratorForStatements.cpp:1979-1984 Issue 3: ABI routing bug for sbytes storage arrays - Problem: sbytes has storageBytes()==32 but IS a byte array - Fix: Check isByteArrayOrString() before storageBytes() check - File: libsolidity/codegen/ABIFunctions.cpp:328-335 Issue 4: Storage-to-memory copy used sload instead of cload - Problem: abiEncodingFunctionCompactStorageArray used sload for sbytes - Fix: Add loadOpcode template parameter checking isShielded() - File: libsolidity/codegen/ABIFunctions.cpp:727 Issue 5-7: Packed storage operations used storageBytes() not numBytes() - Problem: sbytes1 has storageBytes()=32 but occupies 1 byte in arrays - Fix: Use numBytes() for shift/mask calculations in packed storage - Files: libsolidity/codegen/YulUtilFunctions.cpp:3180,3235,2978 Issue 8: Memory byte array write rejected sbytes1 - Problem: Assertion expected only bytes1 for memory byte array elements - Fix: Accept both bytes1 and sbytes1 - File: libsolidity/codegen/ir/IRGeneratorForStatements.cpp:3233 Additional: Add --unsafe-via-ir flag to CLI and Standard JSON - Allows experimental use of via-IR pipeline with shielded types - Files: solc/CommandLineParser.cpp, libsolidity/interface/StandardCompiler.cpp
Run semantic tests in 4 configurations: 1. No optimizer, no IR (baseline) 2. With optimizer, no IR (baseline) 3. No optimizer, --via-ir (tests IR codegen) 4. With optimizer, --via-ir (tests optimized IR)
- shielded_array_storage_pop_zero_length.sol: Change EVMVersion from >=petersburg to >=mercury (suint[] requires CLOAD/CSTORE opcodes) - all_possible_user_defined_value_types_with_operators.sol: Add compileViaYul:false with explanatory comment (test exceeds EIP-170's 24KB contract size limit when compiled with via-IR without optimizer)
Add 4 regression tests with compileViaYul:also to ensure via-IR specific bugs are caught while maintaining non-IR test coverage: 1. shielded_struct_delete_mixed_viair.sol Tests that struct delete uses correct opcodes (sstore for uint16/uint8, cstore for sbytes1) when clearing mixed shielded/non-shielded fields. Prevents regression of clearStorageStructFunction bug. 2. sbytes_dynamic_packed_storage_viair.sol Tests sbytes1 array operations (push, index read, index write) use numBytes() not storageBytes() for shift/mask in packed storage. Prevents regression of packed storage bugs. 3. sbytes_abi_encoding_viair.sol Tests storage-to-memory copy uses cload not sload for sbytes arrays. Prevents regression of abiEncodingFunctionCompactStorageArray bug. 4. timestamp_magic_viair.sol Tests block.timestamp_seconds and block.timestamp_ms generate correct IR (timestamp() and timestampms() respectively). Prevents regression of IR timestamp member bug. All tests use compileViaYul:also to run in both IR and non-IR modes, ensuring comprehensive coverage and regression prevention.
Fixes all remaining issues blocking via-IR compilation for shielded types. Test results: 1641/1642 pass without optimizer (99.94%), 1642/1642 with optimizer (100%). Single failure is unrelated contract size limit. Issue 1: clearStorageStructFunction used wrong opcode for mixed structs - Problem: Mixed structs (uint16 + sbytes) used cstore for ALL fields - Fix: All shielded types have storageBytes()==32, so <32 branch is non-shielded only. Hardcode sstore with defensive assertion. - File: libsolidity/codegen/YulUtilFunctions.cpp:1915-1931 Issue 2: IR timestamp magic members called non-existent functions - Problem: Generated IR called timestamp_seconds() and timestamp_ms() - Fix: Map timestamp_seconds to timestamp(), timestamp_ms to timestampms() - File: libsolidity/codegen/ir/IRGeneratorForStatements.cpp:1979-1984 Issue 3: ABI routing bug for sbytes storage arrays - Problem: sbytes has storageBytes()==32 but IS a byte array - Fix: Check isByteArrayOrString() before storageBytes() check - File: libsolidity/codegen/ABIFunctions.cpp:328-335 Issue 4: Storage-to-memory copy used sload instead of cload - Problem: abiEncodingFunctionCompactStorageArray used sload for sbytes - Fix: Add loadOpcode template parameter checking isShielded() - File: libsolidity/codegen/ABIFunctions.cpp:727 Issue 5-7: Packed storage operations used storageBytes() not numBytes() - Problem: sbytes1 has storageBytes()=32 but occupies 1 byte in arrays - Fix: Use numBytes() for shift/mask calculations in packed storage - Files: libsolidity/codegen/YulUtilFunctions.cpp:3180,3235,2978 Issue 8: Memory byte array write rejected sbytes1 - Problem: Assertion expected only bytes1 for memory byte array elements - Fix: Accept both bytes1 and sbytes1 - File: libsolidity/codegen/ir/IRGeneratorForStatements.cpp:3233 Additional: Add --unsafe-via-ir flag to CLI and Standard JSON - Allows experimental use of via-IR pipeline with shielded types - Files: solc/CommandLineParser.cpp, libsolidity/interface/StandardCompiler.cpp
Add comprehensive test coverage for shielded type validation across different EVM versions. Tests verify that shielded types are rejected on pre-Mercury EVM versions with error 9978. State storage variables: - shielded_storage_evm_version_paris.sol: Single suint256 on Paris - shielded_storage_evm_version_cancun.sol: Multiple shielded types on Cancun - shielded_storage_struct_evm_version.sol: Struct containing shielded type - shielded_storage_sbytes_evm_version.sol: Shielded byte array Other variable contexts: - shielded_local_variable_evm_version.sol: Local function variable - shielded_immutable_evm_version.sol: Immutable variable (error 7491) - shielded_constant_evm_version.sol: Constant variable (error 7491) Positive test: - shielded_storage_evm_version_mercury.sol: Confirms Mercury support All tests run with both legacy and via-IR pipelines (compileViaYul: true). Note: Immutable and constant tests expect error 7491 (existing validation) rather than 9978, as shielded types cannot be immutable or constant.
Prevent emission of CLOAD/CSTORE opcodes on pre-Mercury EVM versions when using shielded types (suint, sbool, saddress, sbytes) in ANY context. ## Problem Compiling with --evm-version paris (or any pre-Mercury version) incorrectly emitted cload/cstore opcodes for shielded types, causing "invalid opcode" runtime errors on pre-Mercury VMs. ## Solution: Two-Layer Defense ### Layer 1: Type Checker (libsolidity/analysis/TypeChecker.cpp) Add comprehensive early validation in visit(VariableDeclaration) to reject ALL uses of shielded types on pre-Mercury versions: **Checked contexts:** - State storage variables (regular, non-constant, non-immutable) - Local storage references/pointers - Local value-type variables (stack/memory) - Immutable variables (value types only) - Constant variables **Safety considerations:** - For immutables: only check if value type (non-value types already error at line 532) - For constants: always safe (must be value types) - For state variables: always safe (storage location guaranteed) - For local storage: safe (storage location) - For local value types: safe (no nested mapping issues) Error 9978 provides actionable message guiding users to --evm-version mercury. ### Layer 2: Codegen Assertions **Legacy Pipeline (libsolidity/codegen/LValue.cpp)** Add 6 defensive assertions to catch any cases that slip through: - GenericStorageItem::retrieveValue() - line 237 - GenericStorageItem::storeValue() - line 310 - GenericStorageItem::setToZero() - line 521 - StorageByteArrayElement::retrieveValue() - line 569 - StorageByteArrayElement::storeValue() - line 584 - StorageByteArrayElement::setToZero() - line 614 **Via-IR Pipeline (libsolidity/codegen/YulUtilFunctions.cpp)** Add assertions in key functions: - readFromStorageValueType() - line 2864 - resizeDynamicByteArrayFunction() - line 1448 - storageArrayPopFunction() - line 1648 - storageArrayPushZeroFunction() - line 1799 ## Coverage - All variable contexts (state, local, immutable, constant) - Arrays/structs containing shielded types (containsShieldedType check) - Shielded byte arrays (StorageByteArrayElement handlers) - Both legacy and via-IR compilation pipelines - All shielded type categories (suint, sbool, saddress, sbytes)
Verify that EVMVersion() and EVMVersion::current() produce the same default version, catching mismatches between currentVersion and the m_version member initializer.
Set currentVersion to Mercury and initialize m_version from currentVersion, ensuring EVMVersion() and EVMVersion::current() always produce the same default version.
Add tests for LoadResolver and EqualStoreEliminator to verify that cstore/cload confidential storage operations are optimized by the data-flow analysis passes, and that cross-domain independence between sstore/sload and cstore/cload is maintained. Includes a test verifying that cstore invalidates sload knowledge for the same key.
Add ConfidentialStorage as a third StoreLoadLocation in the DataFlowAnalyzer, enabling LoadResolver and EqualStoreEliminator to optimize cload/cstore the same way they handle sload/sstore. cstore/cload operate on an independent storage domain from sstore/sload, so they are tracked in a separate environment map. When cstore(k, v) is encountered, regular storage knowledge for key k is invalidated because a subsequent sload would HALT at runtime (the slot is now private). The reverse invalidation is not needed: sstore on a private slot always HALTs, so sstore can never affect confidential storage.
Merges all 68 veridise-audit commits. Key additions: - sbool return type for shielded comparisons - Shielded transient storage rejection (error 9826) - Control flow condition warnings (5765) - Arithmetic info leak warnings (4281-4283) - msg.value to shielded type warning - Shielded constant expression leak warnings - KnownState revert fix (VER-762) - sbytes dynamic shielded byte array support - via-IR shielded type support - SHIELDED_TYPES.md documentation
Merges all 80 zellic-audit commits on top of veridise-audit. ## Conflict resolutions (54 files) ### Source code (2 files) - .github/workflows/test.yml: Set branch targets to seismic + merge-audits-2 - libsolidity/codegen/LValue.cpp: Keep veridise base, added zellic's solAssert EVM version checks in StorageByteArrayElement methods ### Test files (51 files) All resolved by taking veridise's version (stricter warning expectations match veridise source code: sbool returns, warnings 9665/4281-4283/5765) ### CMake (1 file) - test/CMakeLists.txt: Added zellic's EVMVersion.cpp test entry ## Auto-merged source files (verified correct) - TypeChecker.cpp: Both zellic EVM version validation + timestamp gating AND veridise warnings/sbool/unchecked tracking present - CompilerUtils.cpp: Zellic's || to && enum conversion guard fix included - YulUtilFunctions.cpp: All 4 zellic solAssert guards present ## Post-merge fixes (included in this commit) ### Build fixes — duplicate definitions from auto-merge Both branches independently added identical code in non-overlapping regions. Git kept both copies, producing duplicate definitions: - Types.h: Removed duplicate isShielded()/containsShieldedType() declarations in UserDefinedValueType (both branches added them) - TypeChecker.cpp: Removed duplicate checkLiteralToShielded() and checkMsgValueToShielded() definitions (both branches added identical implementations in different regions of the file) ### Test fixes - shielded_storage_evm_version_mercury.sol: Added missing warning 9665 expectation (zellic-only test now triggers veridise's dynamic array length warning) - Removed transient_shielded_state_variable.sol and transient_shielded_different_types.sol: zellic-only semantic tests that expected transient shielded storage to work at runtime, but we chose veridise's approach of rejecting it at the type-checker level (DeclarationError 9826). Covered by veridise's syntax test at syntaxTests/dataLocations/transient_shielded_state_variables.sol. ## New file: MERGE_AUDIT_SUMMARY.md Documents all 54 conflict resolutions, zellic-only features (40 commits), veridise-only features (39 commits), and 39 common fixes — all with specific commit hashes for traceability. ## Verification - soltest.sh (non-semantic): 8116/8116 pass - Semantic tests (no optimizer): 1655/1655 pass - Semantic tests (optimizer, 200 runs): 1655/1655 pass
samlaf
added a commit
to SeismicSystems/seismic-foundry
that referenced
this pull request
Feb 23, 2026
Adding option to pass --unsafe-via-ir option down to ssolc. This updates the seismic-compiler to get the similar changes from SeismicSystems/seismic-compilers#18 Needed because versions of ssolc (SeismicSystems/seismic-solidity#204) require --unsafe-via-ir argument, which foundry's config didn't support before this. Now one can change foundry.toml to have ``` via_ir = true unsafe_via_ir = true ``` and both of these will be passed down to ssolc. chore: Also fixed .gitignore since it was ignoring crates/cli/src/opts/build by mistake.
samlaf
added a commit
to SeismicSystems/seismic
that referenced
this pull request
Feb 23, 2026
New rules were enforced in SeismicSystems/seismic-solidity#204, such as not being allowed to abi.encode a shielded type.
samlaf
added a commit
to SeismicSystems/seismic
that referenced
this pull request
Feb 23, 2026
New rules were enforced in SeismicSystems/seismic-solidity#204, such as not being allowed to abi.encode a shielded type. Fixed these mindlessly, but I think we should take some time to look at the devex related to our current rules. It looks like we force a lot of manual typecasts which might confuse more than help. For example, we disallow abi encoding shielded types; I think a more intuitive rule would be to allow abi encoding shielded types but forcing the output to be sbytes instead of bytes?
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
No description provided.