Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 46 additions & 1 deletion libsolidity/analysis/TypeChecker.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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())
{
Expand Down
24 changes: 24 additions & 0 deletions libsolidity/codegen/LValue.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,10 @@ void GenericStorageItem<IsTransient>::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)
Expand Down Expand Up @@ -305,6 +309,10 @@ void GenericStorageItem<IsTransient>::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.");
Expand Down Expand Up @@ -509,6 +517,10 @@ void GenericStorageItem<IsTransient>::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)
Expand Down Expand Up @@ -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)
Expand All @@ -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
Expand All @@ -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
Expand Down
19 changes: 19 additions & 0 deletions libsolidity/codegen/YulUtilFunctions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<std::string>& _args, std::vector<std::string>&) {
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 := <loadOpcode>(array)
Expand Down Expand Up @@ -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 <functionName>(array) {
let oldLen := <fetchLength>(array)
Expand Down Expand Up @@ -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 <functionName>(array) -> slot, offset {
<?isBytes>
Expand Down Expand Up @@ -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 <functionName>(slot<?dynamic>, offset</dynamic>) -> <?split>addr, selector<!split>value</split> {
<?split>let</split> value := <extract>(<loadOpcode>(slot)<?dynamic>, offset</dynamic>)
Expand Down
Original file line number Diff line number Diff line change
@@ -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.
Original file line number Diff line number Diff line change
@@ -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.
Original file line number Diff line number Diff line change
@@ -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.
Original file line number Diff line number Diff line change
@@ -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.
Original file line number Diff line number Diff line change
@@ -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
Original file line number Diff line number Diff line change
@@ -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.
Original file line number Diff line number Diff line change
@@ -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.
Original file line number Diff line number Diff line change
@@ -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.