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: moved over and adapted multisig script #5

Merged
merged 1 commit into from
Mar 8, 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
34 changes: 0 additions & 34 deletions packages/contracts/deploy/00_info/00-env-check.ts

This file was deleted.

2 changes: 1 addition & 1 deletion packages/contracts/deploy/10_create_repo/11_create_repo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) {
);

console.log(
`'${pluginEnsDomain(hre)}' PluginRepo deployed at: ${pluginRepo.address}.`
`PluginRepo '${pluginEnsDomain(hre)}' deployed at '${pluginRepo.address}'.`
);

hre.aragonToVerifyContracts.push({
Expand Down
74 changes: 59 additions & 15 deletions packages/contracts/deploy/20_new_version/23_publish.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,23 @@
import {
METADATA,
PLUGIN_CONTRACT_NAME,
PLUGIN_REPO_ENS_SUBDOMAIN_NAME,
PLUGIN_SETUP_CONTRACT_NAME,
VERSION,
} from '../../plugin-settings';
import {
findPluginRepo,
getPastVersionCreatedEvents,
impersonatedManagementDaoSigner,
isLocal,
pluginEnsDomain,
} from '../../utils/helpers';
import {
PLUGIN_REPO_PERMISSIONS,
toHex,
uploadToIPFS,
} from '@aragon/osx-commons-sdk';
import {writeFile} from 'fs/promises';
import {DeployFunction} from 'hardhat-deploy/types';
import {HardhatRuntimeEnvironment} from 'hardhat/types';
import path from 'path';
Expand Down Expand Up @@ -77,25 +81,42 @@ const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) {
);
}

// Create Version
if (setup == undefined || setup?.receipt == undefined) {
throw Error('setup deployment unavailable');
}

const isDeployerMaintainer = await pluginRepo.isGranted(
pluginRepo.address,
deployer.address,
PLUGIN_REPO_PERMISSIONS.MAINTAINER_PERMISSION_ID,
[]
);

// If this is a local deployment and the deployer doesn't have `MAINTAINER_PERMISSION_ID` permission
// we impersonate the management DAO for integration testing purposes.
const signer =
isDeployerMaintainer || !isLocal(hre)
? deployer
: await impersonatedManagementDaoSigner(hre);

// Check if the signer has the permission to maintain the plugin repo
if (
await pluginRepo.callStatic.isGranted(
await pluginRepo.isGranted(
pluginRepo.address,
deployer.address,
signer.address,
PLUGIN_REPO_PERMISSIONS.MAINTAINER_PERMISSION_ID,
[]
)
) {
const tx = await pluginRepo.createVersion(
VERSION.release,
setup.address,
toHex(buildMetadataURI),
toHex(releaseMetadataURI)
);

if (setup == undefined || setup?.receipt == undefined) {
throw Error('setup deployment unavailable');
}
// Create the new version
const tx = await pluginRepo
.connect(signer)
.createVersion(
VERSION.release,
setup.address,
toHex(buildMetadataURI),
toHex(releaseMetadataURI)
);

await tx.wait();

Expand All @@ -110,8 +131,31 @@ const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) {
`Published ${PLUGIN_SETUP_CONTRACT_NAME} at ${setup.address} in PluginRepo ${PLUGIN_REPO_ENS_SUBDOMAIN_NAME} at ${pluginRepo.address}.`
);
} else {
throw Error(
`The new version cannot be published because the deployer ('${deployer.address}') is lacking the ${PLUGIN_REPO_PERMISSIONS.MAINTAINER_PERMISSION_ID} permission on repo (${pluginRepo.address}).`
// The deployer does not have `MAINTAINER_PERMISSION_ID` permission and we are not deploying to a production network,
// so we write the data into a file for a management DAO member to create a proposal from it.
const data = {
proposalTitle: `Publish '${PLUGIN_CONTRACT_NAME}' plugin v${VERSION.release}.${VERSION.build}`,
proposalSummary: `Publishes v${VERSION.release}.${VERSION.build} of the '${PLUGIN_CONTRACT_NAME}' plugin in the '${ensDomain}' plugin repo.`,
proposalDescription: `Publishes the '${PLUGIN_SETUP_CONTRACT_NAME}' deployed at '${setup.address}'
as v${VERSION.release}.${VERSION.build} in the '${ensDomain}' plugin repo at '${pluginRepo.address}',
with release metadata '${releaseMetadataURI}' and (immutable) build metadata '${buildMetadataURI}'.`,
actions: [
{
to: pluginRepo.address,
createVersion: {
_release: VERSION.release,
_pluginSetup: setup.address,
_buildMetadata: toHex(buildMetadataURI),
_releaseMetadata: toHex(releaseMetadataURI),
},
},
],
};

const path = `./createVersionProposalData-${hre.network.name}.json`;
await writeFile(path, JSON.stringify(data, null, 2));
console.log(
`Saved data to '${path}'. Use this to create a proposal on the managing DAO calling the 'createVersion' function on the ${ensDomain} plugin repo deployed at ${pluginRepo.address}.`
);
}
};
Expand Down
5 changes: 2 additions & 3 deletions packages/contracts/deploy/30_upgrade_repo/31_upgrade_repo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,8 @@ import path from 'path';
type SemVer = [number, number, number];

/**
* This function pushes an upgrade to the plugin repo. It does not upgrade the actual plugin - this requires
* DAOs installing said plugin to upgrade the plugin themselves. In Aragon's case, this requires the management
* DAO to create a proposal to upgrade the plugin.
* Upgrades the plugin repo to the latest implementation.
* @param {HardhatRuntimeEnvironment} hre
*/
const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) {
const [deployer] = await hre.ethers.getSigners();
Expand Down
111 changes: 111 additions & 0 deletions packages/contracts/deploy/40_conclude/41_transfer_ownership.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
import {findPluginRepo, getManagementDao} from '../../utils/helpers';
import {
DAO_PERMISSIONS,
Operation,
PERMISSION_MANAGER_FLAGS,
PLUGIN_REPO_PERMISSIONS,
} from '@aragon/osx-commons-sdk';
import {DAOStructs} from '@aragon/osx-ethers';
import {DeployFunction} from 'hardhat-deploy/types';
import {HardhatRuntimeEnvironment} from 'hardhat/types';
import path from 'path';

/**
* Creates a plugin repo under Aragon's ENS base domain with subdomain requested in the `./plugin-settings.ts` file.
* @param {HardhatRuntimeEnvironment} hre
*/
const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) {
// Get PluginRepo
const {pluginRepo, ensDomain} = await findPluginRepo(hre);
if (pluginRepo === null) {
throw `PluginRepo '${ensDomain}' does not exist yet.`;
}

// Get the management DAO address
const managementDao = await getManagementDao(hre);
const [deployer] = await hre.ethers.getSigners();

console.log(
`Transferring ownership of the '${ensDomain}' plugin repo at '${pluginRepo.address}' from the deployer '${deployer.address}' to the management DAO at '${managementDao.address}'...`
);

const permissions: DAOStructs.MultiTargetPermissionStruct[] = [
// Grant to the managment DAO
{
operation: Operation.Grant,
where: pluginRepo.address,
who: managementDao.address,
condition: PERMISSION_MANAGER_FLAGS.NO_CONDITION,
permissionId: PLUGIN_REPO_PERMISSIONS.MAINTAINER_PERMISSION_ID,
},
{
operation: Operation.Grant,
where: pluginRepo.address,
who: managementDao.address,
condition: PERMISSION_MANAGER_FLAGS.NO_CONDITION,
permissionId: PLUGIN_REPO_PERMISSIONS.UPGRADE_REPO_PERMISSION_ID,
},
{
operation: Operation.Grant,
where: pluginRepo.address,
who: managementDao.address,
condition: PERMISSION_MANAGER_FLAGS.NO_CONDITION,
permissionId: DAO_PERMISSIONS.ROOT_PERMISSION_ID,
},
// Revoke from deployer
{
operation: Operation.Revoke,
where: pluginRepo.address,
who: deployer.address,
condition: PERMISSION_MANAGER_FLAGS.NO_CONDITION,
permissionId: PLUGIN_REPO_PERMISSIONS.MAINTAINER_PERMISSION_ID,
},
{
operation: Operation.Revoke,
where: pluginRepo.address,
who: deployer.address,
condition: PERMISSION_MANAGER_FLAGS.NO_CONDITION,
permissionId: PLUGIN_REPO_PERMISSIONS.UPGRADE_REPO_PERMISSION_ID,
},
{
operation: Operation.Revoke,
where: pluginRepo.address,
who: deployer.address,
condition: PERMISSION_MANAGER_FLAGS.NO_CONDITION,
permissionId: DAO_PERMISSIONS.ROOT_PERMISSION_ID,
},
];

await pluginRepo.connect(deployer).applyMultiTargetPermissions(permissions);
};

export default func;
func.tags = ['TransferOwnershipToManagmentDao'];

/**
* Skips the transfer of ownership if it has already been transferred to the management DAO
* @param {HardhatRuntimeEnvironment} hre
*/
func.skip = async (hre: HardhatRuntimeEnvironment) => {
console.log(`\n🏗️ ${path.basename(__filename)}:`);

const {pluginRepo, ensDomain} = await findPluginRepo(hre);
if (pluginRepo === null) {
throw `PluginRepo '${ensDomain}' does not exist yet.`;
}
const managementDao = await getManagementDao(hre);

const mgmtDaoHasRootPerm = await pluginRepo.isGranted(
pluginRepo.address,
managementDao.address,
DAO_PERMISSIONS.ROOT_PERMISSION_ID,
[]
);

if (mgmtDaoHasRootPerm)
console.log(
`The ownership of the plugin repo '${ensDomain}' has already been transferred to the management DAO. Skipping...`
);

return mgmtDaoHasRootPerm;
};
2 changes: 1 addition & 1 deletion packages/contracts/hardhat.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ const config: HardhatUserConfig = {
throwOnTransactionFailures: true,
throwOnCallFailures: true,
blockGasLimit: BigNumber.from(10).pow(6).mul(30).toNumber(), // 30 million, really high to test some things that are only possible with a higher block gas limit
gasPrice: BigNumber.from(10).pow(9).mul(150).toNumber(), // 150 gwei
gasPrice: BigNumber.from(10).pow(9).mul(1000).toNumber(), // 1000 gwei
accounts: getHardhatNetworkAccountsConfig(
Object.keys(namedAccounts).length
),
Expand Down
8 changes: 2 additions & 6 deletions packages/contracts/plugin-settings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import buildMetadata from './src/build-metadata.json';
import releaseMetadata from './src/release-metadata.json';
import {VersionTag} from '@aragon/osx-commons-sdk';
import {ethers} from 'hardhat';
import { GovernanceERC20 } from './test/test-utils/typechain-versions';

export const PLUGIN_CONTRACT_NAME = 'TokenVoting'; // This must match the filename `packages/contracts/src/MyPlugin.sol` and the contract name `MyPlugin` within.
export const PLUGIN_SETUP_CONTRACT_NAME = 'TokenVotingSetup'; // This must match the filename `packages/contracts/src/MyPluginSetup.sol` and the contract name `MyPluginSetup` within.
Expand All @@ -26,12 +27,7 @@ const zeroTokenAddress = ethers.constants.AddressZero;
const emptyName = '';
const emptySymbol = '';

export type MintSettings = {
receivers: string[];
amounts: number[];
};

export const emptyMintSettings: MintSettings = {
export const emptyMintSettings: GovernanceERC20.MintSettingsStruct = {
receivers: [],
amounts: [],
};
Expand Down
Loading
Loading