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

1.4.0: Improve ProxyFactory #468

Merged
merged 4 commits into from
Jan 12, 2023
Merged

1.4.0: Improve ProxyFactory #468

merged 4 commits into from
Jan 12, 2023

Conversation

mmv08
Copy link
Member

@mmv08 mmv08 commented Dec 23, 2022

This PR:

Regarding dependency version changes:
I had to regenerate the lock file because the current dependencies snapshot didn't work for me with the latest Node LTS release. Tests simply didn't run. After I did rm -rf node modules && rm -rf yarn.lock && yarn, tests that expected return data in reverts failed, allegedly because of a bug in ethers, see NomicFoundation/hardhat#3438
As a result, I pinned hardhat and ethers dependencies. Furthermore, I also pinned solhint-related things because updated versions do not pass the lining check and require contract code reformatting.

Open questions:

  • The original ticket says that we should check that the singleton contract exists only when initializer data is passed. IMO, it might be wise to check it regardless of the initializer because, in the end, we want the singleton to be a contract. Also, we do check for a zero address in the proxy constructor so why not. But let me know if that doesn't sound good and we should fall back to the initial plan

Gas before changes:

  Proxy - creation
           Used 112621 gas for >creation<
    ✓ with an EOA (285ms)
           Used 143730 gas for >creation<
    ✓ with a single owner Safe
           Used 149530 gas for >creation<
    ✓ with a single owner and guard Safe
           Used 150796 gas for >creation<
    ✓ with a 2 out of 23 Safe
           Used 157852 gas for >creation<
    ✓ with a 3 out of 3 Safe
           Used 157852 gas for >creation<
    ✓ with a 3 out of 5 Safe

After changes:

  Proxy - creation
           Used 115015 gas for >creation<
    ✔ with an EOA (223ms)
           Used 146133 gas for >creation<
    ✔ with a single owner Safe
           Used 151954 gas for >creation<
    ✔ with a single owner and guard Safe
           Used 153201 gas for >creation<
    ✔ with a 2 out of 23 Safe
           Used 160267 gas for >creation<
    ✔ with a 3 out of 3 Safe
           Used 160267 gas for >creation<
    ✔ with a 3 out of 5 Safe

  Proxy - chain specific creation
           Used 115167 gas for >chain specific creation<
    ✔ with an EOA (215ms)
           Used 146285 gas for >chain specific creation<
    ✔ with a single owner Safe
           Used 152106 gas for >chain specific creation<
    ✔ with a single owner and guard Safe
           Used 153353 gas for >chain specific creation<
    ✔ with a 2 out of 23 Safe
           Used 160419 gas for >chain specific creation<
    ✔ with a 3 out of 3 Safe
           Used 160407 gas for >chain specific creation<
    ✔ with a 3 out of 5 Safe

@coveralls
Copy link

coveralls commented Dec 23, 2022

Pull Request Test Coverage Report for Build 3895212699

  • 14 of 14 (100.0%) changed or added relevant lines in 1 file are covered.
  • No unchanged relevant lines lost coverage.
  • Overall coverage decreased (-1.5%) to 96.963%

Totals Coverage Status
Change from base Build 3882598817: -1.5%
Covered Lines: 301
Relevant Lines: 309

💛 - Coveralls

@mmv08 mmv08 force-pushed the feat/improve-proxy-factory branch 2 times, most recently from 10b24e5 to 7e18917 Compare December 23, 2022 20:14
@mmv08 mmv08 requested a review from a team December 23, 2022 20:31
@mmv08 mmv08 marked this pull request as ready for review December 23, 2022 20:35
@@ -46,9 +46,9 @@
"devDependencies": {
Copy link
Member Author

Choose a reason for hiding this comment

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

I pinned some versions because of bugs/incompatibilities. Please see description for a more detailed explanation

@rmeissner
Copy link
Member

it might be wise to check it regardless of the initializer because, in the end, we want the singleton to be a contract.

I did not see this as critical as there is no attack vector in this case (afaik). When an inititalizer is passed this is critical as the initializer depends on the singleton logic.

But yeah, it is more secure to always check and if someone wants to go the "unsecure" way they could create their own factory. So opting for the secure by default makes sense

contracts/proxies/GnosisSafeProxyFactory.sol Outdated Show resolved Hide resolved
contracts/proxies/GnosisSafeProxyFactory.sol Outdated Show resolved Hide resolved
test/factory/ProxyFactory.spec.ts Outdated Show resolved Hide resolved
test/factory/ProxyFactory.spec.ts Outdated Show resolved Hide resolved
@mmv08 mmv08 force-pushed the feat/improve-proxy-factory branch 2 times, most recently from 1845dd4 to 0474607 Compare December 25, 2022 16:25
@mmv08 mmv08 requested a review from rmeissner December 25, 2022 16:25
@mmv08 mmv08 linked an issue Dec 25, 2022 that may be closed by this pull request
@mmv08
Copy link
Member Author

mmv08 commented Dec 27, 2022

But yeah, it is more secure to always check and if someone wants to go the "unsecure" way they could create their own factory. So opting for the secure by default makes sense

Given we have this check in place, should we keep the address(0) check in the Proxy contract?

@rmeissner
Copy link
Member

Given we have this check in place, should we keep the address(0) check in the Proxy contract?

I would keep it for now. It uses very little gas and having an additional check doesn't hurt.

/// @param _singleton Address of singleton contract.
/// @param initializer Payload for message call sent to new proxy contract.
/// @param saltNonce Nonce that will be used to generate the salt to calculate the address of the new proxy contract.
function calculateCreateChainSpecificProxyWithNonceAddress(
Copy link
Member

Choose a reason for hiding this comment

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

ahh I know why you added this and it is not a blocker, but I would not add any more methods that use the revert approach to return data. It doesn't work well with all nodes (as they all return revert messages differently. If we want to we could refactor this into a custom error with a bytes param ... but that is not available at the solidity version we use afaik.

That being said I would remove both method to calculate the address completely (they provide no benefit). Also maybe we should remove the proxyRuntimeCode as it provides little value (as on-chain information) and breaks zkSync support.

Copy link
Member Author

Choose a reason for hiding this comment

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

I agree with reverting methods, they can really behave in an unexpected manner, see NomicFoundation/hardhat#3438

regarding proxyRuntimeCode i'd like to hear Uxio's opinion (iirc methods were added because of him) but he's on vacation until Jan 16th

Copy link
Member

Choose a reason for hiding this comment

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

This was used in the relay service which we deprecated, therefore I would optimistically remove the methods, worst case we add them back later :P

Copy link
Member Author

Choose a reason for hiding this comment

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

Done, please check

Copy link
Member

Choose a reason for hiding this comment

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

@mmv08 mmv08 mentioned this pull request Jan 10, 2023
) public returns (GnosisSafeProxy proxy) {
// If the initializer changes the proxy address should change too. Hashing the initializer data is cheaper than just concatinating it
bytes32 salt = keccak256(abi.encodePacked(keccak256(initializer), saltNonce, getChainId()));
proxy = deployProxy(_singleton, salt);
if (initializer.length > 0)
Copy link
Member

Choose a reason for hiding this comment

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

I realized that we could move this to the deployProxy method or use the createProxyWithNonce method in this function (with the saltNonce being keccak256(abi.encodePacked(saltNonce, callback)) (as it is for createProxyWithCallback). This would reduce code duplication.

Copy link
Member Author

Choose a reason for hiding this comment

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

good call, please check it now. I had to import the runtime bytecode from solc artifacts to be used in tests though.

@mmv08 mmv08 force-pushed the feat/improve-proxy-factory branch 2 times, most recently from e8606e2 to 40d832f Compare January 11, 2023 16:36
@mmv08 mmv08 merged commit 5a91e2c into main Jan 12, 2023
@mmv08 mmv08 deleted the feat/improve-proxy-factory branch January 12, 2023 16:51
@github-actions github-actions bot locked and limited conversation to collaborators Jan 12, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Improve ProxyFactory
3 participants