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

Update docs from Foundry Upgrades #1084

Merged
merged 1 commit into from
Sep 24, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading