Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make Gateway entry points nonreantrant #1358

Open
wants to merge 10 commits into
base: main
Choose a base branch
from

Conversation

alistair-singh
Copy link
Contributor

@alistair-singh alistair-singh commented Dec 24, 2024

Update to solidity 0.8.28 and Cancun EVM version. Make the entry points to the Gateway nonreantrant.

Resolves: https://linear.app/snowfork/issue/SNO-1222

modifier nonreentrant() {
assembly {
// Check if flag is set and if true revert because it means the function is currently executing.
if tload(0) { revert(0, 0) }
Copy link
Contributor

@yrong yrong Jan 1, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can use that pattern. But in the V2 code we use slot 0? Is this an issue?

Copy link
Contributor Author

@alistair-singh alistair-singh Jan 7, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It should be fine because all our variables except for DISPATCH_OVERHEAD_GAS are constant or immutable. DISPATCH_OVERHEAD_GAS is neither constant or immutable but we never write to it, so storage slot 0 is never used in Gateway.
Just to be safe I made DISPATCH_OVERHEAD_GAS constant in:
6148116
And added a storage slot for the reentrancy guard so that we do not mistakenly re-use that slot 0 in future by adding variables to the mutable Gateway.
266a350

Nice catch!

Copy link
Collaborator

@vgeddes vgeddes Jan 8, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Transient storage lives in a separate data location from normal storage, at least that's what the internet says. So transient slot 0 is separate from normal storage slot 0. Can check this with a test.

I generally don't like the way OpenZeppelin code is implemented, its verbose.

@yrong yrong mentioned this pull request Jan 1, 2025
@alistair-singh alistair-singh force-pushed the alistair/nonreantrant-entry-points branch from 41f01ba to 6148116 Compare January 7, 2025 22:54
@alistair-singh alistair-singh requested a review from yrong January 7, 2025 23:43
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems overly complicated compared to the version in Contracts V2, which is defined inline in the Gateway contract:

modifier nonreentrant {
    assembly {
        if tload(0) { revert(0, 0) }
        tstore(0, 1)
    }
    _;
    assembly {
        tstore(0, 0)
    }
}

Copy link
Contributor Author

@alistair-singh alistair-singh Jan 8, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I do not think using slot 0 is the right thing to do even for V2. See this comment: #1358 (comment)

If someone adds a mutable variable to the Gateway contract at a later stage, is it not possible that the compiler will assign it to slot 0 and clash with the reentrancy guard? Or is my understanding of this incorrect?

So the only reason I moved this code to a library is because of the use of an explicit slot for reentrancy, but I can move the implementation with the explicit slot back to Gateway.sol?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Transient storage is a separate data location from normal storage. They don't overlap. So its not possible to overwrite normal storage. You check this with a test.

So yeah, am in favour of moving back to Gateway contract.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants