-
Notifications
You must be signed in to change notification settings - Fork 12
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
refactor: split upgrade repo script into two (#60)
* refactor: renamed file * refactor: extract skip function * refactor: renaming and commenting * style: satisfy linter * chore: maintained guide * refactor: don't alias * fix: wrong import * fix: change the execution order so that reinitialization happens by default * refactor: common steps
- Loading branch information
1 parent
5d892e4
commit d35e7e1
Showing
5 changed files
with
203 additions
and
168 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
167 changes: 0 additions & 167 deletions
167
packages/contracts/deploy/30_upgrade_repo/31_upgrade_repo.ts
This file was deleted.
Oops, something went wrong.
36 changes: 36 additions & 0 deletions
36
packages/contracts/deploy/30_upgrade_repo/31a_upgrade_repo.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
import {fetchData, 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 fetchData(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; |
58 changes: 58 additions & 0 deletions
58
packages/contracts/deploy/30_upgrade_repo/31b_upgrade_and_reinitialize_repo.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
import {fetchData, 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 fetchData(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; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,106 @@ | ||
import {findPluginRepo, getProductionNetworkName} from '../../utils/helpers'; | ||
import { | ||
getLatestNetworkDeployment, | ||
getNetworkNameByAlias, | ||
} from '@aragon/osx-commons-configs'; | ||
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'; | ||
|
||
export type SemVer = [number, number, number]; | ||
|
||
type FetchedData = { | ||
deployer: SignerWithAddress; | ||
pluginRepo: PluginRepo; | ||
latestPluginRepoImplementation: PluginRepo; | ||
ensDomain: string; | ||
current: SemVer; | ||
latest: SemVer; | ||
}; | ||
|
||
export async function fetchData( | ||
hre: HardhatRuntimeEnvironment | ||
): Promise<FetchedData> { | ||
const [deployer] = await hre.ethers.getSigners(); | ||
const productionNetworkName: string = getProductionNetworkName(hre); | ||
const network = getNetworkNameByAlias(productionNetworkName); | ||
if (network === null) { | ||
throw new UnsupportedNetworkError(productionNetworkName); | ||
} | ||
const networkDeployments = getLatestNetworkDeployment(network); | ||
if (networkDeployments === null) { | ||
throw `Deployments are not available on network ${network}.`; | ||
} | ||
|
||
// Get PluginRepo | ||
const {pluginRepo, ensDomain} = await findPluginRepo(hre); | ||
if (pluginRepo === null) { | ||
throw `PluginRepo '${ensDomain}' does not exist yet.`; | ||
} | ||
|
||
console.log( | ||
`Upgrading plugin repo '${ensDomain}' (${pluginRepo.address})...` | ||
); | ||
|
||
// Get the latest `PluginRepo` implementation as the upgrade target | ||
const latestPluginRepoImplementation = PluginRepo__factory.connect( | ||
networkDeployments.PluginRepoBase.address, | ||
deployer | ||
); | ||
|
||
// Get the current OSX protocol version from the current plugin repo implementation | ||
let current: SemVer; | ||
try { | ||
current = await pluginRepo.protocolVersion(); | ||
} catch { | ||
current = [1, 0, 0]; | ||
} | ||
|
||
// Get the OSX protocol version from the latest plugin repo implementation | ||
const latest: SemVer = await latestPluginRepoImplementation.protocolVersion(); | ||
|
||
console.log( | ||
`Upgrading from current protocol version v${current[0]}.${current[1]}.${current[2]} to the latest version v${latest[0]}.${latest[1]}.${latest[2]}.` | ||
); | ||
|
||
return { | ||
deployer, | ||
pluginRepo, | ||
latestPluginRepoImplementation, | ||
ensDomain, | ||
current, | ||
latest, | ||
}; | ||
} | ||
|
||
/** | ||
* Skips the plugin repo upgrade if the implementation is already up-to-date. | ||
* @param {HardhatRuntimeEnvironment} hre | ||
*/ | ||
export const skipUpgrade = async (hre: HardhatRuntimeEnvironment) => { | ||
console.log(`\n🏗️ ${path.basename(__filename)}:`); | ||
|
||
const {ensDomain, pluginRepo, current, latest: target} = await fetchData(hre); | ||
|
||
// Throw an error if attempting to upgrade to an earlier version | ||
if ( | ||
current[0] > target[0] || | ||
current[1] > target[1] || | ||
current[2] > target[2] | ||
) { | ||
throw `The plugin repo, currently at 'v${current[0]}.${current[1]}.${current[2]}' cannot be upgraded to the earlier version v${target[0]}.${target[1]}.${target[2]}.`; | ||
} | ||
|
||
// Skip if versions are equal | ||
if (JSON.stringify(current) == JSON.stringify(target)) { | ||
console.log( | ||
`PluginRepo '${ensDomain}' (${pluginRepo.address}) has already been upgraded to | ||
the current protocol version v${target[0]}.${target[1]}.${target[2]}. Skipping upgrade...` | ||
); | ||
return true; | ||
} | ||
|
||
return false; | ||
}; |