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

refactor: ownership redesign #119

Merged
merged 2 commits into from
Jun 28, 2023
Merged

refactor: ownership redesign #119

merged 2 commits into from
Jun 28, 2023

Conversation

PaulRBerg
Copy link
Owner

@PaulRBerg PaulRBerg commented Jun 17, 2023

Closes #108, addressing all of the audit report findings mentioned there.

@PaulRBerg PaulRBerg requested a review from andreivladbrg June 17, 2023 18:41
@PaulRBerg PaulRBerg force-pushed the refactor/ownership-redesign branch 5 times, most recently from 8e42354 to 9750486 Compare June 17, 2023 20:26
Copy link
Collaborator

@andreivladbrg andreivladbrg left a comment

Choose a reason for hiding this comment

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

I can say that the design is cleaner now.

Not sure if it's a good idea(it would slightly increase the gas) but what do you think about changing the internal _deploy function to: function _deploy(ConstructorParams calldata params). This way you will be able to remove duplicated code from _deploy and deployAndExecute.

src/PRBProxy.sol Outdated Show resolved Hide resolved
@PaulRBerg
Copy link
Owner Author

Thanks for the review. I agree that the new design is clearer - and safer.

Interesting idea to pass ConstructorParams to _deploy, but I suggest we don't do it because it would increase the gas cost by a non-trivial amount (not just "slightly"). ABI-encoding and decoding structs is an expensive operation. And gas costs are very important for deployments (on Ethereum Mainnet), so I would prefer to save any little that we can.

Both functions are well-tested, so we have a pretty good idea that they work as expected.

@PaulRBerg PaulRBerg force-pushed the refactor/ownership-redesign branch 2 times, most recently from c738a35 to b9144a7 Compare June 18, 2023 10:05
@PaulRBerg PaulRBerg force-pushed the refactor/ownership-redesign branch 2 times, most recently from b229563 to 17f65af Compare June 19, 2023 11:50
@andreivladbrg
Copy link
Collaborator

andreivladbrg commented Jun 21, 2023

Just noticed

constructorParams.owner = owner;
proxy = new PRBProxy{ salt: salt }();
delete constructorParams;

Given that the only variable used here is the owner, this can be optimized to:

        constructorParams.owner = owner;
        proxy = new PRBProxy{ salt: salt }();
        constructorParams.owner = address(0);

@PaulRBerg
Copy link
Owner Author

Interesting optimization idea @andreivladbrg but the two implementations cost the same gas when only the owner is set. See my conversation with ChatGPT:

https://chat.openai.com/share/3187fa95-2732-4fe8-95c0-539e259fc835

Also, assigning only the owner to zero is less secure than deleting the entire struct because of the possibility of reentrancy.

Copy link

@tibbarytsur tibbarytsur left a comment

Choose a reason for hiding this comment

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

Set the proxies[owner] to a temp value before creating the proxy to avoid reentrancy for the same owner

proxy = new PRBProxy{ salt: salt }();
delete constructorParams;
// Associate the the owner with the proxy in the mapping.
proxies[owner] = proxy;

noProxy(owner) modifier would pass otherwise when calling deployFor on the registry with the same owner creating 2 proxies with the same owner set in the proxy itself, and the first one set in the registry.

@tibbarytsur
Copy link

All constructor params should be set here (target and data to 0), not just the owner

constructorParams.owner = owner;

deployAndExecute can reenter in deployFor (via a target contract) which would only change the constructorParams.owner leaving target and data intact. The PRBProxy constructor would then get the constructor params from the registry including the old target and data and execute it on the second proxy (this time doing something else like setting token approvals).

@andreivladbrg
Copy link
Collaborator

andreivladbrg commented Jun 22, 2023

See my conversation with ChatGPT

I don't think that using GPT for this specific use case is the best choice, tested this in remix and it was actually a difference by few thousands.

the possibility of reentrancy.

Right, it is safer to use delete.

@PaulRBerg
Copy link
Owner Author

Thanks for your review, both!

noProxy(owner) modifier would pass otherwise when calling deployFor on the registry with the same owner creating 2 proxies with the same owner set in the proxy itself
...
deployAndExecute can reenter in deployFor (via a target contract) which would only change the constructorParams.owner leaving target and data intact.

As discussed on Discord, this cannot happen under the current design - happy to take a call tomorrow to walk through the low-level steps.

All constructor params should be set here (target and data to 0), not just the owner

Agree with this proposal - it would be a good precautionary step even if the attack above cannot happen.

I don't think that using GPT for this specific use case is the best choice, tested this in remix and it was actually a difference by few thousands.

You may be right about ChatGPT (the 2021 cut-off), but did you use via IR and the same number of optimizer runs in your test?

Right, it is safer to use delete.

Yep

@andreivladbrg
Copy link
Collaborator

but did you use ethereum/remix-project#2350 (comment) and the same number of optimizer runs in your test

Yes

@PaulRBerg PaulRBerg force-pushed the refactor/ownership-redesign branch from a721d89 to af7353c Compare June 23, 2023 09:03
chore: ignore and clean "coverage" directory
feat: add "ConstructorParams" in registry
refactor: delete "owner" from storage
refactor: make "owner" immutable
refactor: disallow delegate calling to the registry
test: add tests for proxy owner
test: delete unused imports
test: polish error messages in assertions
@PaulRBerg PaulRBerg force-pushed the refactor/ownership-redesign branch from af7353c to e060114 Compare June 23, 2023 09:05
@PaulRBerg PaulRBerg force-pushed the refactor/ownership-redesign branch from e060114 to 07fed42 Compare June 23, 2023 12:09
@PaulRBerg
Copy link
Owner Author

@tibbarytsur and @andreivladbrg have reviewed this PR, but I will also wait for Zach's confirmation before merging this in.

@PaulRBerg PaulRBerg merged commit c4fc47b into main Jun 28, 2023
@PaulRBerg PaulRBerg deleted the refactor/ownership-redesign branch June 28, 2023 18:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Remove "transferOwnership" functionality
3 participants