Part 2

Zaros
PerpetualsDEXFoundrySolidity
70,000 USDC
View results
Submission Details
Severity: medium
Invalid

[M-10] Incorrect pure Modifier in load Function Allows Unexpected Storage Access

Summary

The load function is incorrectly marked as pure while directly interacting with storage using inline assembly. This misclassification breaks Solidity’s security guarantees and can lead to unintended storage access, potentially exposing sensitive data or causing logical errors in contract execution.

Vulnerability Details

The load function, which retrieves a withdrawalRequest from storage, is declared as pure, implying it neither reads nor modifies blockchain state. However, it uses inline assembly to directly access storage by assigning a slot in memory. Solidity’s type system does not enforce pure restrictions within assembly, allowing unintended state interactions.

  • pure functions should not read or modify storage, but load does.

  • Developers may incorrectly assume load has no storage interaction, leading to security oversights.

  • If used in sensitive contexts, this could bypass security assumptions about contract state access.

Calling this function gives the illusion of "safe" execution while interacting with contract state.

Impact - MEDIUM

  • Breaks Solidity’s function classification, leading to misleading assumptions.

  • Could expose sensitive data if used improperly in access-controlled logic.

  • Potential storage access manipulation, increasing risk in upgradeable contracts.

Likelihood Explanation - LOW

  • Any contract using load under incorrect assumptions is vulnerable.

  • Inline assembly bypasses Solidity’s safety checks, making this issue subtle but impactful.

  • No direct exploit, but risk escalates in complex contract interactions.

Tools Used

Recommendations

Change pure to view

function load(
uint128 vaultId,
address account,
uint128 withdrawalRequestId
)
internal
view
returns (Data storage withdrawalRequest)
{
bytes32 slot = keccak256(abi.encode(WITHDRAWAL_REQUEST_LOCATION, vaultId, account, withdrawalRequestId));
assembly { withdrawalRequest.slot := slot }
}

This prevents the compiler and developers from assuming load() has no storage interaction.

Updates

Lead Judging Commences

inallhonesty Lead Judge
6 months ago
inallhonesty Lead Judge 6 months ago
Submission Judgement Published
Invalidated
Reason: Non-acceptable severity

Support

FAQs

Can't find an answer? Chat with us on Discord, Twitter or Linkedin.