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

Support use with implementations and proxies from OpenZeppelin Contracts 4.x #2

Closed
2 tasks
ericglau opened this issue Dec 6, 2023 · 6 comments · Fixed by #50
Closed
2 tasks

Support use with implementations and proxies from OpenZeppelin Contracts 4.x #2

ericglau opened this issue Dec 6, 2023 · 6 comments · Fixed by #50

Comments

@ericglau
Copy link
Member

ericglau commented Dec 6, 2023

Users may want to migrate from Hardhat to Foundry, and they may have contracts and/or proxies already deployed with OpenZeppelin Contracts 4.x.

This would include:

  • Add support for 4.x UUPS implementations
  • Add support for upgrading existing 4.x proxies

Note that we will probably not support deploying new 4.x proxies, but this feature will cover support for upgrading existing ones.

Originally requested in https://forum.openzeppelin.com/t/first-look-at-the-upcoming-openzeppelin-foundry-upgrades-library/38347/2

@mrhouzlane
Copy link

Same situation
Want to migrate from Hardhat to Foundry with deployed contracts using UUPS with OZ v@4.9.2
Is it possible to migrate to Foundry and how to use proxies there ?

@ericglau
Copy link
Member Author

ericglau commented Jan 11, 2024

If you need to call a function on your new implementation during the upgrade (such as to call a reinitializer), you can just call upgradeProxy as documented in the readme.

If you don't need to call a function on your new implementation during the upgrade, you can do the following workaround:

  1. Call prepareUpgrade to pass in the new version of your implementation contract, which will validate that it is upgrade safe and will deploy the new implementation. Store the returned address in a variable.
  2. Invoke the upgradeTo function at your proxy address by calling upgradeTo(address) on the proxy, passing in the address of the new implementation that was returned in step 1.

@mrhouzlane
Copy link

mrhouzlane commented Jan 11, 2024

What is different from doing this ?

        vm.startBroadcast(deployPrivateKey);
        address implementation = address(new MyContract());
        console2.log(implementation);
        address proxy = address(new ERC1967Proxy(implementation, ""));
        MyContract myContract = MyContract(proxy);
        vm.stopBroadcast();

I believe both are using ERC1967Proxy contract from OZ, but the call from Upgrades.sol contract is more safe?
Also, here we are initializing a new proxy I believe ? How to use existing proxy with having to call prepareUpgrade which have as input a proxy address ?

  • If the proxy was deployed with Hardhat, since Foundry and Hardhat have different artifacts I believe, is that an issue for the continious migration ?

@ericglau
Copy link
Member Author

ericglau commented Jan 11, 2024

prepareUpgrade is similar to address(new MyContractV2()); but it also validates the new implementation for upgrade safety as a prerequisite before deploying it.

In order for the validations to work, in MyContractV2, you should add an annotation to specify the previous version that it upgrades from. See examples in https://docs.openzeppelin.com/upgrades-plugins/1.x/api-core#define-reference-contracts

Foundry does not use existing Hardhat artifacts. There is no need to, because the new annotation is used for validations, and you should recompile your contracts with Foundry instead of trying to reuse Hardhat compilation artifacts.

Here is an example of what the upgrade script could look like:

        Options memory opts;
        address newImpl = Upgrades.prepareUpgrade("MyContractV2.sol", opts);

        MyContract myContract = MyContract(myProxyAddress);
        myContract.upgradeTo(newImpl);

@mrhouzlane
Copy link

mrhouzlane commented Jan 12, 2024

Can OpenZeppelin/openzeppelin-foundry-upgrades be installed with a specific version ?
My contracts are using OZ@v4.9.2 which is incoherent with Upgrades.sol imports using ERC1976Utils, that are not in the Proxy package of OZ@v4.9.2

Can we upgrade contracts with Foundry without using the library openzeppelin-foundry-upgrades then, that's the only solution I see for this case.

@ericglau
Copy link
Member Author

Right, this issue will need to be fixed in order for 4.x to be used with Upgrades.sol.

To upgrade without openzeppelin-foundry-upgrades, it would be like:

        address newImpl = address(new MyContract());
        MyContract myContract = MyContract(myProxyAddress);
        myContract.upgradeTo(newImpl);

We still recommend validating storage layout compatibility before upgrading. You can do that using the validate command from the Upgrades CLI.

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 a pull request may close this issue.

2 participants