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 upgradability tests #437

Merged
merged 36 commits into from
Jul 26, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
cd42367
improve getMerggedAbi function filtering
josemarinas Jun 21, 2023
0c32df0
remove getmergedAbi usage
josemarinas Jun 23, 2023
ee14c95
Merge remote-tracking branch 'origin/develop' into f/OS-532-add-check…
heueristik Jul 18, 2023
d292d71
fix: helpers.ts
heueristik Jul 18, 2023
5acbc82
fix: dao-factory.ts
heueristik Jul 18, 2023
106d0f4
fix: plugin-setup-processor.ts
heueristik Jul 18, 2023
ef4d842
fix: admin.ts
heueristik Jul 18, 2023
7e909a6
fix: token-voting.ts
heueristik Jul 18, 2023
b992524
fix: addresslist-voting.ts
heueristik Jul 18, 2023
bcce07f
feature: improved error
heueristik Jul 18, 2023
5a6ea50
fix: multisig.ts
heueristik Jul 18, 2023
323c8d9
feature: refactored upgradeability tests
heueristik Jul 19, 2023
19ac7c3
feature: merkle minter and distributor tests
heueristik Jul 19, 2023
2d4609a
fix: use explicit artifacts for managing DAO tests
heueristik Jul 20, 2023
9341378
fix: typo
heueristik Jul 20, 2023
4b144c1
feature: improved names and comments
heueristik Jul 20, 2023
5ec1a61
fix: ambiguous artifacts
heueristik Jul 20, 2023
2ab0e5c
fix: use existing interface
heueristik Jul 20, 2023
a9e40fb
feature: improved typing
heueristik Jul 20, 2023
922d74e
fix: provide explicit paths to smock
heueristik Jul 20, 2023
41edd82
Merge branch 'f/OS-532-add-checks-to-getMergedAbi' into feature/OS-40…
heueristik Jul 20, 2023
306579d
fix: use strict comparision
heueristik Jul 20, 2023
4679e66
fix: missing await
heueristik Jul 20, 2023
d67e46c
Merge branch 'f/OS-532-add-checks-to-getMergedAbi' into feature/OS-40…
heueristik Jul 20, 2023
8f6b669
fix: remove redundant typecast
heueristik Jul 21, 2023
703e0b4
fix: removed redundant ts-ignore
heueristik Jul 21, 2023
fc64eeb
Merge branch 'f/OS-532-add-checks-to-getMergedAbi' into feature/OS-40…
heueristik Jul 21, 2023
ff211a1
feature: maintain checklists
heueristik Jul 21, 2023
eafe78a
revert: wrong await / async
heueristik Jul 21, 2023
c3181e9
feature: improved checklist
heueristik Jul 21, 2023
fc2a96f
feature: renamed function
heueristik Jul 21, 2023
3861c64
refactor: improved tests
heueristik Jul 21, 2023
8e6c099
Merge remote-tracking branch 'origin/develop' into feature/OS-408-upg…
heueristik Jul 21, 2023
ee567da
fix: remove redundant imports
heueristik Jul 21, 2023
b2cec9e
refactor: remove method
heueristik Jul 21, 2023
ecdf7e7
fix: added removed args
heueristik Jul 21, 2023
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
1 change: 1 addition & 0 deletions UPDATE_CHECKLIST.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ This checklist is seen as a guide to update the existing deployment.

- [ ] Make sure you are using Node v16
- [ ] Verify that all changes of this update are reflected in [contracts/CHANGELOG.md](packages/contracts/CHANGELOG.md) by comparing the diff with the previous release commit.
- [ ] Check that storage corruption tests using OZ's `hardhat-upgrades` package (e.g., by using the methods in [uups-upgradeable.ts](packages/contracts/test/test-utils/uups-upgradeable.ts)) exist for every upgradeable contract and test the upgrade from all prior versions to the current version.
- [ ] Check that all contracts that undergo an upgrade and
- [ ] do require reinitialzation are reinitialized correctly by an `upgradeToAndCall` call to a respective initialization method with an incremented `reinitializer(X)` number
- [ ] do NOT require reinitialzation are upgraded via `upgradeTo` and keep the same `reinitializer(X)` number in the respective initialization methods
Expand Down
11 changes: 11 additions & 0 deletions packages/contracts/src/test/Migration.sol
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,14 @@ pragma solidity 0.8.17;
*/

import {DAO as DAO_v1_0_0} from "@aragon/osx-v1.0.1/core/dao/DAO.sol";
import {DAORegistry as DAORegistry_v1_0_0} from "@aragon/osx-v1.0.1/framework/dao/DAORegistry.sol";
import {PluginRepo as PluginRepo_v1_0_0} from "@aragon/osx-v1.0.1/framework/plugin/repo/PluginRepo.sol";
import {PluginRepoRegistry as PluginRepoRegistry_v1_0_0} from "@aragon/osx-v1.0.1/framework/plugin/repo/PluginRepoRegistry.sol";
import {ENSSubdomainRegistrar as ENSSubdomainRegistrar_v1_0_0} from "@aragon/osx-v1.0.1/framework/utils/ens/ENSSubdomainRegistrar.sol";

import {TokenVoting as TokenVoting_v1_0_0} from "@aragon/osx-v1.0.1/plugins/governance/majority-voting/token/TokenVoting.sol";
import {AddresslistVoting as AddresslistVoting_v1_0_0} from "@aragon/osx-v1.0.1/plugins/governance/majority-voting/addresslist/AddresslistVoting.sol";
import {Multisig as Multisig_v1_0_0} from "@aragon/osx-v1.0.1/plugins/governance/multisig/Multisig.sol";

import {MerkleMinter as MerkleMinter_v1_0_0} from "@aragon/osx-v1.0.1/plugins/token/MerkleMinter.sol";
import {MerkleDistributor as MerkleDistributor_v1_0_0} from "@aragon/osx-v1.0.1/plugins/token/MerkleDistributor.sol";
65 changes: 51 additions & 14 deletions packages/contracts/test/core/dao/dao.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import chai, {expect} from 'chai';
import {ethers} from 'hardhat';
import {ContractFactory} from 'ethers';
import {SignerWithAddress} from '@nomiclabs/hardhat-ethers/signers';

import {
Expand All @@ -21,6 +22,12 @@ import {
IEIP4824__factory,
IProtocolVersion__factory,
} from '../../../typechain';
import {DAO__factory as DAO_V1_0_0__factory} from '../../../typechain/@aragon/osx-v1.0.1/core/dao/DAO.sol';

import {
getProtocolVersion,
ozUpgradeCheckManagingContract,
} from '../../test-utils/uups-upgradeable';
import {findEvent, DAO_EVENTS} from '../../../utils/event';
import {flipBit} from '../../test-utils/bitmap';

Expand All @@ -37,7 +44,6 @@ import {OZ_ERRORS} from '../../test-utils/error';
import {smock} from '@defi-wonderland/smock';
import {deployWithProxy} from '../../test-utils/proxy';
import {UNREGISTERED_INTERFACE_RETURN} from './callback-handler';
import {shouldUpgradeCorrectly} from '../../test-utils/uups-upgradeable';
import {UPGRADE_PERMISSIONS} from '../../test-utils/permissions';
import {ZERO_BYTES32, daoExampleURI} from '../../test-utils/dao';
import {ExecutedEvent} from '../../../typechain/DAO';
Expand Down Expand Up @@ -94,10 +100,12 @@ describe('DAO', function () {
let dao: DAO;
let DAO: DAO__factory;

beforeEach(async function () {
before(async () => {
signers = await ethers.getSigners();
ownerAddress = await signers[0].getAddress();
});

beforeEach(async function () {
DAO = new DAO__factory(signers[0]);
dao = await deployWithProxy<DAO>(DAO);
await dao.initialize(
Expand Down Expand Up @@ -140,19 +148,8 @@ describe('DAO', function () {
PERMISSION_IDS.REGISTER_STANDARD_CALLBACK_PERMISSION_ID
),
]);

this.upgrade = {
contract: dao,
dao: dao,
user: signers[8],
};
});

shouldUpgradeCorrectly(
UPGRADE_PERMISSIONS.UPGRADE_DAO_PERMISSION_ID,
'Unauthorized'
);

it('does not support the empty interface', async () => {
expect(await dao.supportsInterface('0xffffffff')).to.be.false;
});
Expand Down Expand Up @@ -327,6 +324,47 @@ describe('DAO', function () {
});
});

describe('Upgrades', async () => {
let legacyContractFactory: ContractFactory;
let currentContractFactory: ContractFactory;

before(() => {
currentContractFactory = new DAO__factory(signers[0]);
});

it('from v1.0.0', async () => {
legacyContractFactory = new DAO_V1_0_0__factory(signers[0]);

const {fromImplementation, toImplementation} =
await ozUpgradeCheckManagingContract(
signers[0],
signers[1],
{
metadata: dummyMetadata1,
initialOwner: signers[0].address,
trustedForwarder: dummyAddress1,
daoURI: daoExampleURI,
},
'initialize',
legacyContractFactory,
currentContractFactory,
UPGRADE_PERMISSIONS.UPGRADE_DAO_PERMISSION_ID
);
expect(toImplementation).to.not.equal(fromImplementation);

const fromProtocolVersion = await getProtocolVersion(
legacyContractFactory.attach(fromImplementation)
);
const toProtocolVersion = await getProtocolVersion(
currentContractFactory.attach(toImplementation)
);

expect(fromProtocolVersion).to.not.deep.equal(toProtocolVersion);
expect(fromProtocolVersion).to.deep.equal([1, 0, 0]);
expect(toProtocolVersion).to.deep.equal(CURRENT_PROTOCOL_VERSION);
});
});

describe('ERC-165', async () => {
it('does not support the empty interface', async () => {
expect(await dao.supportsInterface('0xffffffff')).to.be.false;
Expand Down Expand Up @@ -1147,7 +1185,6 @@ describe('DAO', function () {
});

it('should allow only `SET_SIGNATURE_VALIDATOR_PERMISSION_ID` to set validator', async () => {
const signers = await ethers.getSigners();
await expect(
dao
.connect(signers[2])
Expand Down
111 changes: 59 additions & 52 deletions packages/contracts/test/deploy/managing-dao.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,11 @@ import {
} from '../../typechain';

import daoArtifactData from '../../artifacts/src/core/dao/DAO.sol/DAO.json';
import daoRegistryArtifactData from '../../artifacts/@aragon/osx-v1.0.1/framework/dao/DAORegistry.sol/DAORegistry.json';
heueristik marked this conversation as resolved.
Show resolved Hide resolved
import pluginRepoRegistryArtifactData from '../../artifacts/@aragon/osx-v1.0.1/framework/plugin/repo/PluginRepoRegistry.sol/PluginRepoRegistry.json';
import pluginRepoArtifactData from '../../artifacts/@aragon/osx-v1.0.1/framework/plugin/repo/PluginRepo.sol/PluginRepo.json';
import ensSubdomainRegistrarArtifactData from '../../artifacts/@aragon/osx-v1.0.1/framework/utils/ens/ENSSubdomainRegistrar.sol/ENSSubdomainRegistrar.json';

import {SignerWithAddress} from '@nomiclabs/hardhat-ethers/signers';
import {initializeDeploymentFixture} from '../test-utils/fixture';

Expand Down Expand Up @@ -157,57 +162,59 @@ describe('Managing DAO', function () {

it('Should be able to upgrade `DaoRegistry`', async function () {
// deploy a new implementation.
await deployments.deploy('DAORegistryV2', {
contract: 'DAORegistry',
from: ownerAddress,
args: [],
log: true,
});

const daoRegistryV2Deployment: Deployment = await deployments.get(
'DAORegistryV2'
const daoRegistry_v1_0_0_Deployment = await deployments.deploy(
'DAORegistry_v1_0_0',
{
contract: daoRegistryArtifactData,
from: ownerAddress,
args: [],
log: true,
}
);

// make sure new `DAORegistryV2` deployment is just an implementation and not a proxy
expect(daoRegistryV2Deployment.implementation).to.be.equal(undefined);
expect(daoRegistry_v1_0_0_Deployment.implementation).to.be.equal(undefined);

// check new implementation is deferent from the one on the `DaoRegistry`.
// read from slot
let implementationAddress = (
await readImplementationValuesFromSlot([daoRegistry.address])
)[0];

expect(daoRegistryV2Deployment.address).not.equal(implementationAddress);
expect(daoRegistry_v1_0_0_Deployment.address).not.equal(
implementationAddress
);

// create proposal to upgrade to new implementation
await createUpgradeProposal(
[daoRegistry.address],
daoRegistryV2Deployment.address
daoRegistry_v1_0_0_Deployment.address
);

// re-read from slot
implementationAddress = (
await readImplementationValuesFromSlot([daoRegistry.address])
)[0];

expect(daoRegistryV2Deployment.address).to.be.equal(implementationAddress);
expect(daoRegistry_v1_0_0_Deployment.address).to.be.equal(
implementationAddress
);
});

it('Should be able to upgrade `PluginRepoRegistry`', async function () {
// deploy a new implementation.
await deployments.deploy('PluginRepoRegistryV2', {
contract: 'PluginRepoRegistry',
from: ownerAddress,
args: [],
log: true,
});

const pluginRepoRegistryV2Deployment: Deployment = await deployments.get(
'PluginRepoRegistryV2'
const pluginRepoRegistry_v1_0_0_Deployment = await deployments.deploy(
'PluginRepoRegistry_v1_0_0',
{
contract: pluginRepoRegistryArtifactData,
from: ownerAddress,
args: [],
log: true,
}
);

// make sure new `PluginRepoRegistryV2` deployment is just an implementation and not a proxy
expect(pluginRepoRegistryV2Deployment.implementation).to.be.equal(
expect(pluginRepoRegistry_v1_0_0_Deployment.implementation).to.be.equal(
undefined
);

Expand All @@ -217,41 +224,40 @@ describe('Managing DAO', function () {
await readImplementationValuesFromSlot([pluginRepoRegistry.address])
)[0];

expect(pluginRepoRegistryV2Deployment.address).not.equal(
expect(pluginRepoRegistry_v1_0_0_Deployment.address).not.equal(
implementationAddress
);

// create proposal to upgrade to new implementation
await createUpgradeProposal(
[pluginRepoRegistry.address],
pluginRepoRegistryV2Deployment.address
pluginRepoRegistry_v1_0_0_Deployment.address
);

// re-read from slot
implementationAddress = (
await readImplementationValuesFromSlot([pluginRepoRegistry.address])
)[0];

expect(pluginRepoRegistryV2Deployment.address).to.be.equal(
expect(pluginRepoRegistry_v1_0_0_Deployment.address).to.be.equal(
implementationAddress
);
});

it('Should be able to upgrade `ENSSubdomainRegistrar`', async function () {
// deploy a new implementation.
await deployments.deploy('ENSSubdomainRegistrarV2', {
contract: 'ENSSubdomainRegistrar',
from: ownerAddress,
args: [],
log: true,
});

const ensSubdomainRegistrarV2Deployment: Deployment = await deployments.get(
'ENSSubdomainRegistrarV2'
const ensSubdomainRegistrar_v1_0_0_Deployment = await deployments.deploy(
'ENSSubdomainRegistrar_v1_0_0',
{
contract: ensSubdomainRegistrarArtifactData,
from: ownerAddress,
args: [],
log: true,
}
);

// make sure new `ENSSubdomainRegistrarV2` deployment is just an implementation and not a proxy
expect(ensSubdomainRegistrarV2Deployment.implementation).to.be.equal(
expect(ensSubdomainRegistrar_v1_0_0_Deployment.implementation).to.be.equal(
undefined
);

Expand All @@ -264,15 +270,15 @@ describe('Managing DAO', function () {

for (let index = 0; index < implementationValues.length; index++) {
const implementationAddress = implementationValues[index];
expect(ensSubdomainRegistrarV2Deployment.address).not.equal(
expect(ensSubdomainRegistrar_v1_0_0_Deployment.address).not.equal(
implementationAddress
);
}

// create proposal to upgrade to new implementation
await createUpgradeProposal(
ensSubdomainRegistrars.map(ensSR => ensSR.address),
ensSubdomainRegistrarV2Deployment.address
ensSubdomainRegistrar_v1_0_0_Deployment.address
);

// re-read from slot
Expand All @@ -283,27 +289,26 @@ describe('Managing DAO', function () {

for (let index = 0; index < implementationValues.length; index++) {
const implementationAddress = implementationValues[index];
expect(ensSubdomainRegistrarV2Deployment.address).to.be.equal(
expect(ensSubdomainRegistrar_v1_0_0_Deployment.address).to.be.equal(
implementationAddress
);
}
});

it('Should be able to upgrade `PluginRepo`s', async function () {
// deploy a new implementation.
await deployments.deploy('PluginRepoV2', {
contract: 'PluginRepo',
from: ownerAddress,
args: [],
log: true,
});

const pluginRepoV2Deployment: Deployment = await deployments.get(
'PluginRepoV2'
const PluginRepo_v1_0_0_Deployment = await deployments.deploy(
'PluginRepo_v1_0_0',
{
contract: pluginRepoArtifactData,
from: ownerAddress,
args: [],
log: true,
}
);

// make sure new `PluginRepoV2` deployment is just an implementation and not a proxy
expect(pluginRepoV2Deployment.implementation).to.be.equal(undefined);
expect(PluginRepo_v1_0_0_Deployment.implementation).to.be.equal(undefined);

// check new implementation is deferent from the one on the `DaoRegistry`.
// read from slot
Expand All @@ -316,15 +321,15 @@ describe('Managing DAO', function () {

for (let index = 0; index < implementationValues.length; index++) {
const implementationAddress = implementationValues[index];
expect(pluginRepoV2Deployment.address).to.not.equal(
expect(PluginRepo_v1_0_0_Deployment.address).to.not.equal(
implementationAddress
);
}

// create proposal to upgrade to new implementation
await createUpgradeProposal(
Object.values(hre.aragonPluginRepos),
pluginRepoV2Deployment.address
PluginRepo_v1_0_0_Deployment.address
);

// re-read from slot
Expand All @@ -337,7 +342,9 @@ describe('Managing DAO', function () {

for (let index = 0; index < implementationValues.length; index++) {
const implementationAddress = implementationValues[index];
expect(pluginRepoV2Deployment.address).to.be.equal(implementationAddress);
expect(PluginRepo_v1_0_0_Deployment.address).to.be.equal(
implementationAddress
);
}
});
});
Loading