Beginner FriendlySolidity
100 EXP
View results
Submission Details
Severity: high
Valid

Mismatched Transient Storage Slot in nonReentrant Modifier

Summary

During a manual code review, the nonReentrant modifier in the InheritanceManager.sol contract referenced an external Solidity blog post on Transient Storage for Reentrancy Locks. Upon navigating to the URL provided in the NatSpec comment (https://soliditylang.org/blog/2024/01/26/transient-storage/), I compared the implementation in the official blog with the one in the contract and found a critical mismatch in the transient storage slot used for reentrancy protection.

This discrepancy allows a bypass of the reentrancy guard, enabling double execution of critical functions like withdrawals, token transfers, or contract interactions.

Vulnerability Details

Root Cause

The vulnerability arises due to a mismatch between the transient storage slot checked for reentrancy (tload(1)) and the slot used for locking (tstore(0, 1)).

tload(1) checks the wrong slot, while tstore(0, 1) locks another.

Since the tload(1) check is pointing to the wrong transient storage slot, reentrancy is not properly prevented.

modifier nonReentrant() {
assembly {
if tload(1) { revert(0, 0) } // Checking transient slot 1
tstore(0, 1) // Locking using transient slot 0
}
_;
assembly {
tstore(0, 0) // Unlocking using transient slot 0
}
}

Check (tload(1)) looks at transient storage slot 1.

  • Lock (tstore(0, 1)) sets transient storage slot 0 to 1.

  • Unlock (tstore(0, 0)) resets transient storage slot 0.

Since the check and lock operate on different slots, a reentrant call can bypass the check and re-enter the function.

Reentrancy Not Properly Prevented

  • A reentrant call might check tload(0), which is 0, allowing it to execute, even though tload(1) was used in the check.

Impact

This vulnerability completely breaks the reentrancy protection

Tools Used

manual review

Recommendations

Use a Consistent Transient Storage Slot

The transient storage slot must be the same for checking and locking.

modifier nonReentrant() {
assembly {
if tload(0) { revert(0, 0) } // Check correct slot
tstore(0, 1) // Lock correct slot
}
_;
assembly {
tstore(0, 0) // Unlock correct slot
}
}

Both tload(0) and tstore(0, 1) use the same transient slot (0).

  • Ensures proper locking and prevents reentrancy attacks.

Updates

Lead Judging Commences

0xtimefliez Lead Judge 6 months ago
Submission Judgement Published
Validated
Assigned finding tags:

Wrong value in nonReentrant modifier

Support

FAQs

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