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: split upgrade repo script into two #60

Merged
merged 9 commits into from
Apr 15, 2024
Merged
Show file tree
Hide file tree
Changes from 8 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
4 changes: 3 additions & 1 deletion USAGE_GUIDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,9 @@ The standard deploy scripts in the `packages/contracts/deploy` should already be
- Fetches the plugin setup and implementation contract and queues it for block explorer verification.
- `20_new_version/23_publish.ts`
- Publishes the plugin setup contract on the plugin repo created in `10_repo/11_create_repo.ts`
- `30_upgrade_repo/31_upgrade_repo.ts`
- `30_upgrade_repo/31a_upgrade_and_reinitialize_repo.ts`
- Upgrades the plugin repo to the latest Aragon OSx protocol version and reinitializes it.
- `30_upgrade_repo/31b_upgrade_repo.ts`
- Upgrades the plugin repo to the latest Aragon OSx protocol version.
- `40_conclude/41_conclude.ts`
- Prints information on the used account's balance after deployment.
Expand Down
36 changes: 36 additions & 0 deletions packages/contracts/deploy/30_upgrade_repo/31a_upgrade_repo.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import {commonUpgradeSteps, skipUpgrade} from './_common';
import {PLUGIN_REPO_PERMISSIONS} from '@aragon/osx-commons-sdk';
import {DeployFunction} from 'hardhat-deploy/types';
import {HardhatRuntimeEnvironment} from 'hardhat/types';

/**
* Upgrades the plugin repo to the latest implementation.
* This script CAN be called if the contract does not require reinitialization.
* It MUST NOY be called if the contract requires reinitialization, because this
* would leave the proxy unreinitialized.
* @param {HardhatRuntimeEnvironment} hre
*/
const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) {
const {deployer, pluginRepo, latestPluginRepoImplementation} =
await commonUpgradeSteps(hre);

// Check if deployer has the permission to upgrade the plugin repo
if (
await pluginRepo.isGranted(
pluginRepo.address,
deployer.address,
PLUGIN_REPO_PERMISSIONS.UPGRADE_REPO_PERMISSION_ID,
[]
)
) {
await pluginRepo.upgradeTo(latestPluginRepoImplementation.address);
} else {
throw Error(
`The new version cannot be published because the deployer ('${deployer.address}')
is lacking the ${PLUGIN_REPO_PERMISSIONS.UPGRADE_REPO_PERMISSION_ID} permission.`
);
}
};
export default func;
func.tags = ['UpgradeRepo'];
func.skip = skipUpgrade;
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import {commonUpgradeSteps, skipUpgrade} from './_common';
import {PLUGIN_REPO_PERMISSIONS} from '@aragon/osx-commons-sdk';
import {BytesLike} from 'ethers';
import {DeployFunction} from 'hardhat-deploy/types';
import {HardhatRuntimeEnvironment} from 'hardhat/types';

/**
* Upgrades the plugin repo to the latest implementation and reinitializes the proxy.
* This script MUST be called if the contract requires reinitialization -- otherwise
* the proxy is left unreinitialized.
* @param {HardhatRuntimeEnvironment} hre
*/
const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) {
const {deployer, pluginRepo, latestPluginRepoImplementation, current} =
await commonUpgradeSteps(hre);

// Define the `_initData` arguments
const initData: BytesLike[] = [];

// Encode the call to `function initializeFrom(uint8[3] calldata _previousProtocolVersion, bytes calldata _initData)` with `initData`.
const initializeFromCalldata =
latestPluginRepoImplementation.interface.encodeFunctionData(
// Re-initialization will happen through a call to `function initializeFrom(uint8[3] calldata _previousProtocolVersion, bytes calldata _initData)`
// that Aragon will add to the `PluginRepo` contract once it's required.
'initializeFrom',
[current, initData]
);

// Check if deployer has the permission to upgrade the plugin repo
if (
await pluginRepo.isGranted(
pluginRepo.address,
deployer.address,
PLUGIN_REPO_PERMISSIONS.UPGRADE_REPO_PERMISSION_ID,
[]
)
) {
// Use `upgradeToAndCall` to reinitialize the new `PluginRepo` implementation after the update.
if (initializeFromCalldata.length > 0) {
await pluginRepo.upgradeToAndCall(
latestPluginRepoImplementation.address,
initializeFromCalldata
);
} else {
throw Error(
`Initialization data is missing for 'upgradeToAndCall'. Stopping repo upgrade and reinitialization...`
);
}
} else {
throw Error(
`The new version cannot be published because the deployer ('${deployer.address}')
is lacking the ${PLUGIN_REPO_PERMISSIONS.UPGRADE_REPO_PERMISSION_ID} permission.`
);
}
};
export default func;
func.tags = ['UpgradeAndReinitializeRepo'];
func.skip = skipUpgrade;
Original file line number Diff line number Diff line change
Expand Up @@ -3,23 +3,25 @@ import {
getLatestNetworkDeployment,
getNetworkNameByAlias,
} from '@aragon/osx-commons-configs';
import {
PLUGIN_REPO_PERMISSIONS,
UnsupportedNetworkError,
} from '@aragon/osx-commons-sdk';
import {PluginRepo__factory} from '@aragon/osx-ethers';
import {BytesLike} from 'ethers';
import {DeployFunction} from 'hardhat-deploy/types';
import {UnsupportedNetworkError} from '@aragon/osx-commons-sdk';
import {PluginRepo, PluginRepo__factory} from '@aragon/osx-ethers';
import {SignerWithAddress} from '@nomiclabs/hardhat-ethers/signers';
import {HardhatRuntimeEnvironment} from 'hardhat/types';
import path from 'path';

type SemVer = [number, number, number];
export type SemVer = [number, number, number];

/**
* Upgrades the plugin repo to the latest implementation.
* @param {HardhatRuntimeEnvironment} hre
*/
const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) {
type Result = {
deployer: SignerWithAddress;
pluginRepo: PluginRepo;
latestPluginRepoImplementation: PluginRepo;
current: SemVer;
latest: SemVer;
};

export async function commonUpgradeSteps(
hre: HardhatRuntimeEnvironment
): Promise<Result> {
const [deployer] = await hre.ethers.getSigners();
const productionNetworkName: string = getProductionNetworkName(hre);
const network = getNetworkNameByAlias(productionNetworkName);
Expand Down Expand Up @@ -62,56 +64,20 @@ const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) {
`Upgrading from current protocol version v${current[0]}.${current[1]}.${current[2]} to the latest version v${latest[0]}.${latest[1]}.${latest[2]}.`
);

// NOTE: The following code can be uncommented and `initData` can be filled
// with arguments in case re-initialization of the `PluginRepo` should become necessary.
// Re-initialization will happen through a call to `function initializeFrom(uint8[3] calldata _previousProtocolVersion, bytes calldata _initData)`
// that Aragon might add to the `PluginRepo` contract once it's required.
/*
// Define the `_initData` arguments
const initData: BytesLike[] = [];
// Encode the call to `function initializeFrom(uint8[3] calldata _previousProtocolVersion, bytes calldata _initData)` with `initData`
const initializeFromCalldata =
latestPluginRepoImplementation.interface.encodeFunctionData('initializeFrom', [
current,
initData,
]);
*/
const initializeFromCalldata: BytesLike = [];

// Check if deployer has the permission to upgrade the plugin repo
if (
await pluginRepo.isGranted(
pluginRepo.address,
deployer.address,
PLUGIN_REPO_PERMISSIONS.UPGRADE_REPO_PERMISSION_ID,
[]
)
) {
// Use `upgradeToAndCall` if the new implementation must be re-initialized by calling
// on the `PluginRepo` proxy. If not, we use `upgradeTo`.
if (initializeFromCalldata.length > 0) {
await pluginRepo.upgradeToAndCall(
latestPluginRepoImplementation.address,
initializeFromCalldata
);
} else {
await pluginRepo.upgradeTo(latestPluginRepoImplementation.address);
}
} else {
throw Error(
`The new version cannot be published because the deployer ('${deployer.address}')
is lacking the ${PLUGIN_REPO_PERMISSIONS.UPGRADE_REPO_PERMISSION_ID} permission.`
);
}
};
export default func;
func.tags = ['UpgradeRepo'];
return {
deployer,
pluginRepo,
latestPluginRepoImplementation,
current,
latest,
};
}

/**
* Skips the plugin repo upgrade if exists in the plugin repo.
* Skips the plugin repo upgrade if the implementation is already up-to-date.
* @param {HardhatRuntimeEnvironment} hre
*/
func.skip = async (hre: HardhatRuntimeEnvironment) => {
export const skipUpgrade = async (hre: HardhatRuntimeEnvironment) => {
console.log(`\n🏗️ ${path.basename(__filename)}:`);

const [deployer] = await hre.ethers.getSigners();
Expand Down
Loading