diff --git a/libsolidity/analysis/TypeChecker.cpp b/libsolidity/analysis/TypeChecker.cpp index 9790a585f..534aa91a9 100644 --- a/libsolidity/analysis/TypeChecker.cpp +++ b/libsolidity/analysis/TypeChecker.cpp @@ -552,7 +552,52 @@ bool TypeChecker::visit(VariableDeclaration const& _variable) "Type " + varType->humanReadableName() + " is only valid in storage because it contains a (nested) mapping." ); } - else if (_variable.visibility() >= Visibility::Public) + + // Validate EVM version for shielded types + // Check all variables: state storage, local, immutable, constant + bool shouldCheckShieldedTypes = false; + if (_variable.immutable()) + { + // Immutables must be value types (error 6377 if not) + // Only check if it's actually a value type to avoid assertion failures + shouldCheckShieldedTypes = varType->isValueType(); + } + else if (_variable.isConstant()) + { + // Constants are always value types, safe to check + shouldCheckShieldedTypes = true; + } + else if (_variable.isStateVariable()) + { + // Regular state storage variables + shouldCheckShieldedTypes = true; + } + else if (_variable.referenceLocation() == VariableDeclaration::Location::Storage) + { + // Local storage references/pointers + shouldCheckShieldedTypes = true; + } + else if (varType->isValueType()) + { + // Local value-type variables (stack/memory) + shouldCheckShieldedTypes = true; + } + + if (shouldCheckShieldedTypes && varType->containsShieldedType()) + { + if (!m_evmVersion.supportShieldedStorage()) + { + m_errorReporter.typeError( + 9978_error, + _variable.location(), + "Shielded types (suint, sbool, saddress, sbytes, etc.) require the Mercury EVM version or later. " + "The current EVM version \"" + m_evmVersion.name() + "\" does not support shielded types. " + "Use \"--evm-version mercury\" to enable shielded type support." + ); + } + } + + if (_variable.isStateVariable() && _variable.visibility() >= Visibility::Public) { if (varType->containsShieldedType()) { diff --git a/libsolidity/codegen/LValue.cpp b/libsolidity/codegen/LValue.cpp index f84233084..7765131de 100644 --- a/libsolidity/codegen/LValue.cpp +++ b/libsolidity/codegen/LValue.cpp @@ -234,6 +234,10 @@ void GenericStorageItem::retrieveValue(langutil::SourceLocation con } if (!_remove) CompilerUtils(m_context).copyToStackTop(sizeOnStack(), sizeOnStack()); + solAssert( + !m_dataType->isShielded() || m_context.evmVersion().supportShieldedStorage(), + "Shielded storage types require Mercury EVM version. This should have been caught by type checker." + ); if (m_dataType->isShielded() && m_dataType->storageBytes() == 32) m_context << Instruction::POP << (IsTransient ? s_loadInstruction : Instruction::CLOAD); else if (m_dataType->storageBytes() == 32) @@ -305,6 +309,10 @@ void GenericStorageItem::storeValue(Type const& _sourceType, langut { solAssert(m_dataType->storageBytes() <= 32, "Invalid storage bytes size."); solAssert(m_dataType->storageBytes() > 0, "Invalid storage bytes size."); + solAssert( + !m_dataType->isShielded() || m_context.evmVersion().supportShieldedStorage(), + "Shielded storage types require Mercury EVM version. This should have been caught by type checker." + ); if (m_dataType->isShielded() && m_dataType->storageBytes() == 32) { solAssert(m_dataType->sizeOnStack() == 1, "Invalid stack size."); @@ -509,6 +517,10 @@ void GenericStorageItem::setToZero(langutil::SourceLocation const&, else { solAssert(m_dataType->isValueType(), "Clearing of unsupported type requested: " + m_dataType->toString()); + solAssert( + !m_dataType->isShielded() || m_context.evmVersion().supportShieldedStorage(), + "Shielded storage types require Mercury EVM version. This should have been caught by type checker." + ); if (!_removeReference) CompilerUtils(m_context).copyToStackTop(sizeOnStack(), sizeOnStack()); if (m_dataType->isShielded() && m_dataType->storageBytes() == 32) @@ -555,6 +567,10 @@ StorageByteArrayElement::StorageByteArrayElement(CompilerContext& _compilerConte void StorageByteArrayElement::retrieveValue(SourceLocation const&, bool _remove) const { + solAssert( + !m_isShielded || m_context.evmVersion().supportShieldedStorage(), + "Shielded storage types require Mercury EVM version. This should have been caught by type checker." + ); auto const loadInstruction = m_isShielded ? Instruction::CLOAD : Instruction::SLOAD; // stack: ref byte_number if (_remove) @@ -568,6 +584,10 @@ void StorageByteArrayElement::retrieveValue(SourceLocation const&, bool _remove) void StorageByteArrayElement::storeValue(Type const&, SourceLocation const&, bool _move) const { + solAssert( + !m_isShielded || m_context.evmVersion().supportShieldedStorage(), + "Shielded storage types require Mercury EVM version. This should have been caught by type checker." + ); auto const loadInstruction = m_isShielded ? Instruction::CLOAD : Instruction::SLOAD; auto const storeInstruction = m_isShielded ? Instruction::CSTORE : Instruction::SSTORE; // stack: value ref byte_number @@ -590,6 +610,10 @@ void StorageByteArrayElement::storeValue(Type const&, SourceLocation const&, boo void StorageByteArrayElement::setToZero(SourceLocation const&, bool _removeReference) const { + solAssert( + !m_isShielded || m_context.evmVersion().supportShieldedStorage(), + "Shielded storage types require Mercury EVM version. This should have been caught by type checker." + ); auto const loadInstruction = m_isShielded ? Instruction::CLOAD : Instruction::SLOAD; auto const storeInstruction = m_isShielded ? Instruction::CSTORE : Instruction::SSTORE; // stack: ref byte_number diff --git a/libsolidity/codegen/YulUtilFunctions.cpp b/libsolidity/codegen/YulUtilFunctions.cpp index 2c438ef81..7ea50dd52 100644 --- a/libsolidity/codegen/YulUtilFunctions.cpp +++ b/libsolidity/codegen/YulUtilFunctions.cpp @@ -1444,6 +1444,10 @@ std::string YulUtilFunctions::resizeDynamicByteArrayFunction(ArrayType const& _t { std::string functionName = "resize_array_" + _type.identifier(); return m_functionCollector.createFunction(functionName, [&](std::vector& _args, std::vector&) { + solAssert( + !_type.baseType()->isShielded() || m_evmVersion.supportShieldedStorage(), + "Shielded storage types require Mercury EVM version. This should have been caught by type checker." + ); _args = {"array", "newLen"}; return Whiskers(R"( let data := (array) @@ -1640,6 +1644,10 @@ std::string YulUtilFunctions::storageArrayPopFunction(ArrayType const& _type) std::string functionName = "array_pop_" + _type.identifier(); return m_functionCollector.createFunction(functionName, [&]() { + solAssert( + !_type.containsShieldedType() || m_evmVersion.supportShieldedStorage(), + "Shielded storage types require Mercury EVM version. This should have been caught by type checker." + ); return Whiskers(R"( function (array) { let oldLen := (array) @@ -1787,6 +1795,10 @@ std::string YulUtilFunctions::storageArrayPushZeroFunction(ArrayType const& _typ solUnimplementedAssert(_type.baseType()->storageBytes() <= 32, "Base type is not yet implemented."); std::string functionName = "array_push_zero_" + _type.identifier(); return m_functionCollector.createFunction(functionName, [&]() { + solAssert( + !_type.containsShieldedType() || m_evmVersion.supportShieldedStorage(), + "Shielded storage types require Mercury EVM version. This should have been caught by type checker." + ); return Whiskers(R"( function (array) -> slot, offset { @@ -2861,6 +2873,13 @@ std::string YulUtilFunctions::readFromStorageValueType( _type.identifier(); return m_functionCollector.createFunction(functionName, [&] { + if (_type.isShielded() && !m_evmVersion.supportShieldedStorage()) + { + solAssert(false, + "Shielded storage types require Mercury EVM version. " + "This should have been caught by type checker." + ); + } Whiskers templ(R"( function (slot, offset) -> addr, selectorvalue { let value := ((slot), offset) diff --git a/test/libsolidity/syntaxTests/types/shielded_constant_evm_version.sol b/test/libsolidity/syntaxTests/types/shielded_constant_evm_version.sol new file mode 100644 index 000000000..ea857897c --- /dev/null +++ b/test/libsolidity/syntaxTests/types/shielded_constant_evm_version.sol @@ -0,0 +1,8 @@ +contract C { + suint256 constant X = suint256(100); +} +// ==== +// EVMVersion: =paris +// compileViaYul: true +// ---- +// DeclarationError 7491: (20-48): Shielded objects cannot be set to constant or immutable. diff --git a/test/libsolidity/syntaxTests/types/shielded_immutable_evm_version.sol b/test/libsolidity/syntaxTests/types/shielded_immutable_evm_version.sol new file mode 100644 index 000000000..054bcbf99 --- /dev/null +++ b/test/libsolidity/syntaxTests/types/shielded_immutable_evm_version.sol @@ -0,0 +1,12 @@ +contract C { + suint256 immutable x; + + constructor() { + x = suint256(42); + } +} +// ==== +// EVMVersion: =cancun +// compileViaYul: true +// ---- +// DeclarationError 7491: (20-40): Shielded objects cannot be set to constant or immutable. diff --git a/test/libsolidity/syntaxTests/types/shielded_local_variable_evm_version.sol b/test/libsolidity/syntaxTests/types/shielded_local_variable_evm_version.sol new file mode 100644 index 000000000..03f4ec767 --- /dev/null +++ b/test/libsolidity/syntaxTests/types/shielded_local_variable_evm_version.sol @@ -0,0 +1,10 @@ +contract C { + function f() public { + suint256 x = suint256(0); + } +} +// ==== +// EVMVersion: =paris +// compileViaYul: true +// ---- +// TypeError 9978: (49-72): Shielded types (suint, sbool, saddress, sbytes, etc.) require the Mercury EVM version or later. The current EVM version "paris" does not support shielded types. Use "--evm-version mercury" to enable shielded type support. diff --git a/test/libsolidity/syntaxTests/types/shielded_storage_evm_version_cancun.sol b/test/libsolidity/syntaxTests/types/shielded_storage_evm_version_cancun.sol new file mode 100644 index 000000000..a00cda26a --- /dev/null +++ b/test/libsolidity/syntaxTests/types/shielded_storage_evm_version_cancun.sol @@ -0,0 +1,14 @@ +contract C { + suint256 a; + sbool b; + saddress c; + suint8 d; +} +// ==== +// EVMVersion: =cancun +// compileViaYul: true +// ---- +// TypeError 9978: (20-31): Shielded types (suint, sbool, saddress, sbytes, etc.) require the Mercury EVM version or later. The current EVM version "cancun" does not support shielded types. Use "--evm-version mercury" to enable shielded type support. +// TypeError 9978: (37-46): Shielded types (suint, sbool, saddress, sbytes, etc.) require the Mercury EVM version or later. The current EVM version "cancun" does not support shielded types. Use "--evm-version mercury" to enable shielded type support. +// TypeError 9978: (52-64): Shielded types (suint, sbool, saddress, sbytes, etc.) require the Mercury EVM version or later. The current EVM version "cancun" does not support shielded types. Use "--evm-version mercury" to enable shielded type support. +// TypeError 9978: (70-79): Shielded types (suint, sbool, saddress, sbytes, etc.) require the Mercury EVM version or later. The current EVM version "cancun" does not support shielded types. Use "--evm-version mercury" to enable shielded type support. diff --git a/test/libsolidity/syntaxTests/types/shielded_storage_evm_version_mercury.sol b/test/libsolidity/syntaxTests/types/shielded_storage_evm_version_mercury.sol new file mode 100644 index 000000000..3975f7a01 --- /dev/null +++ b/test/libsolidity/syntaxTests/types/shielded_storage_evm_version_mercury.sol @@ -0,0 +1,15 @@ +contract C { + suint256 a; + sbool b; + saddress c; + sbytes data; + + struct S { + suint256 x; + uint256 y; + } + S s; +} +// ==== +// EVMVersion: >=mercury +// compileViaYul: true diff --git a/test/libsolidity/syntaxTests/types/shielded_storage_evm_version_paris.sol b/test/libsolidity/syntaxTests/types/shielded_storage_evm_version_paris.sol new file mode 100644 index 000000000..ed7cf5e42 --- /dev/null +++ b/test/libsolidity/syntaxTests/types/shielded_storage_evm_version_paris.sol @@ -0,0 +1,8 @@ +contract C { + suint256 x; +} +// ==== +// EVMVersion: =paris +// compileViaYul: true +// ---- +// TypeError 9978: (20-31): Shielded types (suint, sbool, saddress, sbytes, etc.) require the Mercury EVM version or later. The current EVM version "paris" does not support shielded types. Use "--evm-version mercury" to enable shielded type support. diff --git a/test/libsolidity/syntaxTests/types/shielded_storage_sbytes_evm_version.sol b/test/libsolidity/syntaxTests/types/shielded_storage_sbytes_evm_version.sol new file mode 100644 index 000000000..360005fff --- /dev/null +++ b/test/libsolidity/syntaxTests/types/shielded_storage_sbytes_evm_version.sol @@ -0,0 +1,8 @@ +contract C { + sbytes data; +} +// ==== +// EVMVersion: =cancun +// compileViaYul: true +// ---- +// TypeError 9978: (20-31): Shielded types (suint, sbool, saddress, sbytes, etc.) require the Mercury EVM version or later. The current EVM version "cancun" does not support shielded types. Use "--evm-version mercury" to enable shielded type support. diff --git a/test/libsolidity/syntaxTests/types/shielded_storage_struct_evm_version.sol b/test/libsolidity/syntaxTests/types/shielded_storage_struct_evm_version.sol new file mode 100644 index 000000000..5fb58d20c --- /dev/null +++ b/test/libsolidity/syntaxTests/types/shielded_storage_struct_evm_version.sol @@ -0,0 +1,12 @@ +contract C { + struct S { + suint256 x; + uint256 y; + } + S s; +} +// ==== +// EVMVersion: =paris +// compileViaYul: true +// ---- +// TypeError 9978: (88-91): Shielded types (suint, sbool, saddress, sbytes, etc.) require the Mercury EVM version or later. The current EVM version "paris" does not support shielded types. Use "--evm-version mercury" to enable shielded type support.