Skip to content

Commit

Permalink
Update docs from Foundry Upgrades (#1084)
Browse files Browse the repository at this point in the history
  • Loading branch information
ericglau authored Sep 24, 2024
1 parent ed565f4 commit 60dc229
Show file tree
Hide file tree
Showing 4 changed files with 71 additions and 22 deletions.
3 changes: 3 additions & 0 deletions docs/modules/ROOT/pages/foundry/api/pages/Options.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,12 @@ import { Options } from "openzeppelin-foundry-upgrades/Options.sol";
```solidity
struct Options {
string referenceContract;
string referenceBuildInfoDir;
bytes constructorData;
string[] exclude;
string unsafeAllow;
bool unsafeAllowRenames;
bool unsafeSkipProxyAdminCheck;
bool unsafeSkipStorageCheck;
bool unsafeSkipAllChecks;
struct DefenderOptions defender;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,39 @@
= OpenZeppelin Foundry Upgrades API

== Contract name formats

Contract names must be provided in specific formats depending on context. The following are the required formats for each context:

=== Foundry artifact format

Contexts:

* `contractName` parameter
* `referenceContract` option if `referenceBuildInfoDir` option is not set

Can be in any of the following forms according to Foundry's https://book.getfoundry.sh/cheatcodes/get-code[getCode] cheatcode:

* the Solidity file name, e.g. `ContractV1.sol`
* the Solidity file name and the contract name, e.g. `ContractV1.sol:ContractV1`
* the artifact path relative to the project root directory, e.g. `out/ContractV1.sol/ContractV1.json`

=== Annotation format

Contexts:

* `@custom:oz-upgrades-from <reference>` annotation
* `referenceContract` option if `referenceBuildInfoDir` option is set

Can be in any of the following forms according to the https://docs.openzeppelin.com/upgrades-plugins/api-core#define-reference-contracts[OpenZeppelin Upgrades CLI]:

* the contract name, e.g. `ContractV1`
* fully qualified contract name, e.g. `contracts/tokens/ContractV1.sol:ContractV1`

If the `referenceBuildInfoDir` option is set, include the build info directory short name as a prefix, resulting in one of the following forms:

* the build info directory short name and the contract name, e.g. `build-info-v1:ContractV1`
* the build info directory short name and the fully qualified contract name, e.g. `build-info-v1:contracts/tokens/ContractV1.sol:ContractV1`

== Common Options

The following options can be used with some of the below functions. See https://github.com/OpenZeppelin/openzeppelin-foundry-upgrades/blob/main/src/Options.sol[Options.sol] for detailed descriptions of each option.
Expand Down
54 changes: 33 additions & 21 deletions docs/modules/ROOT/pages/foundry/pages/foundry-upgrades.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -133,10 +133,12 @@ import {MyToken} from "src/MyToken.sol";

Then call functions from the imported library to run validations, deployments, or upgrades.

=== Examples
== Examples

The following examples assume you are using OpenZeppelin Contracts v5 and want to run upgrade safety validations.

=== Deploy a proxy

Deploy a UUPS proxy:
[source,solidity]
----
Expand All @@ -156,13 +158,28 @@ address proxy = Upgrades.deployTransparentProxy(
);
----

Deploy an upgradeable beacon and a beacon proxy:
[source,solidity]
----
address beacon = Upgrades.deployBeacon("MyContract.sol", INITIAL_OWNER_ADDRESS_FOR_BEACON);
address proxy = Upgrades.deployBeaconProxy(
beacon,
abi.encodeCall(MyContract.initialize, ("arguments for the initialize function"))
);
----

=== Use your contract

Call your contract's functions as normal, but remember to always use the proxy address:
[source,solidity]
----
MyContract instance = MyContract(proxy);
instance.myFunction();
----

=== Upgrade a proxy or beacon

Upgrade a transparent or UUPS proxy and call an arbitrary function (such as a reinitializer) during the upgrade process:
[source,solidity]
----
Expand All @@ -183,37 +200,32 @@ Upgrades.upgradeProxy(
);
----

WARNING: When upgrading a proxy or beacon, ensure that the new contract either has its `@custom:oz-upgrades-from <reference>` annotation set to the current implementation contract used by the proxy or beacon, or set it with the `referenceContract` option, for example:
[source,solidity]
----
Options memory opts;
opts.referenceContract = "MyContractV1.sol";
Upgrades.upgradeProxy(proxy, "MyContractV2.sol", "", opts);
// or Upgrades.upgradeBeacon(beacon, "MyContractV2.sol", opts);
----

Deploy an upgradeable beacon:
Upgrade a beacon:
[source,solidity]
----
address beacon = Upgrades.deployBeacon("MyContract.sol", INITIAL_OWNER_ADDRESS_FOR_BEACON);
Upgrades.upgradeBeacon(beacon, "MyContractV2.sol");
----

Deploy a beacon proxy:
WARNING: When upgrading a proxy or beacon, ensure that the new contract either has its `@custom:oz-upgrades-from <reference>` annotation set to the name of the old implementation contract used by the proxy or beacon, or set it with the `referenceContract` option, for example:
[source,solidity]
----
address proxy = Upgrades.deployBeaconProxy(
beacon,
abi.encodeCall(MyContract.initialize, ("arguments for the initialize function"))
);
Options memory opts;
opts.referenceContract = "MyContractV1.sol";
Upgrades.upgradeProxy(proxy, "MyContractV2.sol", "", opts);
// or Upgrades.upgradeBeacon(beacon, "MyContractV2.sol", opts);
----

Upgrade a beacon:
TIP: If possible, keep the old version of the implementation contract's source code somewhere in your project to use as a reference as above. This requires the new version to be in a different directory, Solidity file, or using a different contract name. Otherwise, if you want to use the same directory and name for the new version, keep the build info directory from the previous deployment (or build it from an older branch of your project repository) and reference it as follows:
[source,solidity]
----
Upgrades.upgradeBeacon(beacon, "MyContractV2.sol");
Options memory opts;
opts.referenceBuildInfoDir = "/old-builds/build-info-v1";
opts.referenceContract = "build-info-v1:MyContract";
Upgrades.upgradeProxy(proxy, "MyContract.sol", "", opts);
// or Upgrades.upgradeBeacon(beacon, "MyContract.sol", opts);
----

=== Coverage Testing
== Coverage Testing

To enable code coverage reports with `forge coverage`, use the following deployment pattern in your tests: instantiate your implementation contracts directly and use the `UnsafeUpgrades` library. For example:
```solidity
Expand All @@ -226,7 +238,7 @@ address proxy = Upgrades.deployUUPSProxy(

WARNING: `UnsafeUpgrades` is not recommended for use in Forge scripts. It does not validate whether your contracts are upgrade safe or whether new implementations are compatible with previous ones. Ensure you run validations before any actual deployments or upgrades, such as by using the `Upgrades` library in scripts.

=== Deploying and Verifying
== Deploying and Verifying

Run your script with `forge script` to broadcast and deploy. See Foundry's https://book.getfoundry.sh/tutorials/solidity-scripting[Solidity Scripting] guide.

Expand Down

0 comments on commit 60dc229

Please sign in to comment.