Skip to content

Commit fa803f5

Browse files
Warn when layout base is near the end of storage
1 parent 6d8ed86 commit fa803f5

File tree

2 files changed

+45
-0
lines changed

2 files changed

+45
-0
lines changed

libsolidity/analysis/PostTypeContractLevelChecker.cpp

+43
Original file line numberDiff line numberDiff line change
@@ -144,4 +144,47 @@ void PostTypeContractLevelChecker::checkStorageLayoutSpecifier(ContractDefinitio
144144
baseSlotExpression.location(),
145145
"Contract extends past the end of storage when this base slot value is specified."
146146
);
147+
148+
warnStorageLayoutBaseNearStorageEnd(_contract);
147149
}
150+
151+
void PostTypeContractLevelChecker::warnStorageLayoutBaseNearStorageEnd(ContractDefinition const& _contract)
152+
{
153+
if (Error::containsErrors(m_errorReporter.errors()))
154+
return;
155+
156+
auto storageSize = u256(contractStorageSizeUpperBound(_contract, VariableDeclaration::Location::Unspecified));
157+
auto baseSlot = layoutBaseForInheritanceHierarchy(_contract, DataLocation::Storage);
158+
if (
159+
u256 slotsLeft = std::numeric_limits<u256>::max() - baseSlot - storageSize;
160+
!Error::containsErrors(m_errorReporter.errors()) &&
161+
slotsLeft <= u256(1) << 64
162+
)
163+
{
164+
auto const& location = _contract.storageLayoutSpecifier() ?
165+
_contract.storageLayoutSpecifier()->location() :
166+
_contract.location()
167+
;
168+
169+
auto errorID = 3495_error;
170+
std::string errorMsg = "This contract is very close to the end of storage. This limits its future upgradability.";
171+
if (_contract.stateVariables().size() > 0)
172+
m_errorReporter.warning(
173+
errorID,
174+
location,
175+
errorMsg,
176+
SecondarySourceLocation{}.append(
177+
fmt::format(
178+
"There are {} slots between this state variable and the end of the storage.",
179+
formatNumberReadable(slotsLeft)
180+
),
181+
_contract.stateVariables().back()->location()
182+
));
183+
else
184+
m_errorReporter.warning(
185+
errorID,
186+
location,
187+
errorMsg
188+
);
189+
}
190+
}

libsolidity/analysis/PostTypeContractLevelChecker.h

+2
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,8 @@ class PostTypeContractLevelChecker
5252

5353
void checkStorageLayoutSpecifier(ContractDefinition const& _contract);
5454

55+
void warnStorageLayoutBaseNearStorageEnd(ContractDefinition const& _contract);
56+
5557
langutil::ErrorReporter& m_errorReporter;
5658
};
5759

0 commit comments

Comments
 (0)