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

Fix typechain and contracts tests #374

Merged
merged 14 commits into from
May 16, 2023
11 changes: 8 additions & 3 deletions .github/workflows/subgraph-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ jobs:
- name: Install node
uses: actions/setup-node@v3
with:
cache: "yarn"
cache: 'yarn'
node-version: 16
- name: Install dependencies
run: yarn install --pure-lockfile
Expand All @@ -49,19 +49,24 @@ jobs:
working-directory: ${{env.working-directory}}
steps:
- uses: actions/checkout@v2
with:
ref: ${{ github.ref }}
fetch-depth: 0
- name: Install node
uses: actions/setup-node@v3
with:
cache: "yarn"
cache: 'yarn'
node-version: 16
- name: Install dependencies
run: yarn
- name: Build contracts-versions
run: yarn run build:contracts-versions
- name: Build contracts
run: yarn run build:contracts
- name: Build manifest
run: yarn run manifest
env:
NETWORK_NAME: "goerli"
NETWORK_NAME: 'goerli'
- name: Build
run: yarn run build
- name: Run Tests
Expand Down
73 changes: 73 additions & 0 deletions packages/contracts/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,79 @@ Then, copy the deployment address and paste it in to replace `DEPLOYED_CONTRACT_
npx hardhat verify --network goerli DEPLOYED_CONTRACT_ADDRESS "Hello, Hardhat!"
```

## Testing

The `@aragon/osx-versions` package allows you to work with previous versions of the contracts. The solidity source files of these versions are available in the `packages/contracts-versions/versions` directory after the package was built. For a details please refer to the [packages/contracts-versions/README.md](https://github.com/aragon/osx/blob/develop/packages/contracts-versions/README.md).

If you want to import and test a contract from a previous version, you must first import the contract into `contracts/src/tests/osx-versions/Migration.sol`. This step is necessary for the contract to be compiled.

```solidity
// contracts/src/tests/osx-versions/Migration.sol

import '../../contracts-versions/{version-name}/{path_to_contract}.sol';
Rekard0 marked this conversation as resolved.
Show resolved Hide resolved

// Replace {version-name} with the version number of the contract, and {path_to_contract} with the actual path to the contract.
```

After successful contract compilation, TypeChain typings will be automatically generated and placed in the `typechain/osx-versions/{version-name}` directory. This will allow you to interact with the contract in a type-safe manner in your tests.

```ts
// Generic example of usage in a test

...

import {MyContract} from '../../../typechain/osx-versions/{version-name}/{path to MyContract}';
import {MyContract__factory} from '../../../typechain/osx-versions/{version-name}/{path to MyContract__factory}';

describe('MyContract Test', function () {
let myContract: MyContract;

beforeEach(async function () {
const signers = await ethers.getSigners();
const myContractFactory = new MyContract__factory(signers[0]);
myContract = await myContractFactory.deploy();
});

it('Should do something', async function () {
const result = await myContract.someFunction();
expect(result).to.equal(something);
});
});

...

```

Please replace 'MyContract' with the actual name of your contract, and follow the same approach for the other placeholders (someFunction, something). This is an illustrative example, the actual test case will depend on the specific methods and functionality of your contract.

```ts
// Example of usage in a test
import {expect} from 'chai';
import {ethers} from 'hardhat';
import {SignerWithAddress} from '@nomiclabs/hardhat-ethers/signers';
import {deployWithProxy} from '../../test-utils/proxy';
import {
DAO as DAO_V1_3_0,
DAO__factory as DAO_V1_3_0__factory,
} from '../../typechain/osx-versions/v1_3_0/contracts/core/dao/DAO.sol';

describe('Legacy Test Example', function () {
let signers: SignerWithAddress[];
let daoV1_3_0: DAO_V1_3_0;

before(async function () {
signers = await ethers.getSigners();
const factory = new DAO_V1_3_0__factory(signers[0]);
daoV1_3_0 = await DAO_V1_3_0.deployWithProxy<DAO_V1_3_0>(factory);
});

it('should be version 1.3.0', async function () {
const result = await daoV1_3_0.protocolVersion();
expect(result).to.equal([1, 3, 0]);
});
});
```

# Performance optimizations

For faster runs of your tests and scripts, consider skipping ts-node's type checking by setting the environment variable `TS_NODE_TRANSPILE_ONLY` to `1` in hardhat's environment. For more details see [the documentation](https://hardhat.org/guides/typescript.html#performance-optimizations).
Expand Down
50 changes: 28 additions & 22 deletions packages/contracts/deploy/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,10 @@ import {findEvent} from '../utils/event';
import {getMergedABI} from '../utils/abi';
import {Operation} from '../utils/types';
import {VersionTag} from '../test/test-utils/psp/types';
import {PluginRepo__factory} from '../typechain';
import {ENSRegistry__factory, PluginRepo__factory} from '../typechain';
import {VersionCreatedEvent} from '../typechain/PluginRepo';
import {PluginRepoRegisteredEvent} from '../typechain/PluginRepoRegistry';
import {SignerWithAddress} from '@nomiclabs/hardhat-ethers/signers';

// TODO: Add support for L2 such as Arbitrum. (https://discuss.ens.domains/t/register-using-layer-2/688)
// Make sure you own the ENS set in the {{NETWORK}}_ENS_DOMAIN variable in .env
Expand Down Expand Up @@ -124,12 +125,12 @@ export async function updateActiveContractsJSON(payload: {

export async function detemineDeployerNextAddress(
index: number,
deployer: any
deployer: SignerWithAddress
): Promise<string> {
const [owner] = await ethers.getSigners();
const nonce = await owner.getTransactionCount();
const futureAddress = ethers.utils.getContractAddress({
from: deployer,
from: deployer.address,
nonce: nonce + index,
});
return futureAddress;
Expand All @@ -140,21 +141,22 @@ export async function createPluginRepo(
pluginName: string
): Promise<void> {
const {network} = hre;
const signers = await ethers.getSigners();

const pluginDomain =
process.env[`${network.name.toUpperCase()}_PLUGIN_ENS_DOMAIN`] || '';
if (
await isENSDomainRegistered(
`${pluginName}.${pluginDomain}`,
await getENSAddress(hre)
await getENSAddress(hre),
signers[0]
)
) {
// not beeing able to register the plugin repo means that something is not right with the framework deployment used.
// Either a frontrun happened or something else. Thus we abort here
throw new Error(`${pluginName} is already present! Aborting...`);
}

const signers = await ethers.getSigners();

const pluginRepoFactoryAddress = await getContractAddress(
'PluginRepoFactory',
hre
Expand Down Expand Up @@ -416,11 +418,12 @@ export async function managePermissions(

export async function isENSDomainRegistered(
domain: string,
ensRegistryAddress: string
ensRegistryAddress: string,
signer: SignerWithAddress
): Promise<boolean> {
const ensRegistryContract = await ethers.getContractAt(
'ENSRegistry',
ensRegistryAddress
const ensRegistryContract = ENSRegistry__factory.connect(
ensRegistryAddress,
signer
);

return ensRegistryContract.recordExists(ethers.utils.namehash(domain));
Expand Down Expand Up @@ -458,23 +461,22 @@ export async function getPublicResolverAddress(

export async function registerSubnodeRecord(
domain: string,
owner: string,
owner: SignerWithAddress,
ensRegistryAddress: string,
publicResolver: string
): Promise<string> {
const domainSplitted = domain.split('.');
const subdomain = domainSplitted.splice(0, 1)[0];
const parentDomain = domainSplitted.join('.');

const ensRegistryContract = await ethers.getContractAt(
'ENSRegistry',
ensRegistryAddress
const ensRegistryContract = ENSRegistry__factory.connect(
ensRegistryAddress,
owner
);

const tx = await ensRegistryContract.setSubnodeRecord(
ethers.utils.namehash(parentDomain),
ethers.utils.keccak256(ethers.utils.toUtf8Bytes(subdomain)),
owner,
owner.address,
publicResolver,
0
);
Expand All @@ -491,9 +493,11 @@ export async function transferSubnodeRecord(
const subdomain = domainSplitted.splice(0, 1)[0];
const parentDomain = domainSplitted.join('.');

const ensRegistryContract = await ethers.getContractAt(
'ENSRegistry',
ensRegistryAddress
const [deployer] = await ethers.getSigners();

const ensRegistryContract = ENSRegistry__factory.connect(
ensRegistryAddress,
deployer
);

const tx = await ensRegistryContract.setSubnodeOwner(
Expand All @@ -514,9 +518,11 @@ export async function transferSubnodeChain(
currentOwner: string,
ensRegistryAddress: string
): Promise<void> {
const ensRegistryContract = await ethers.getContractAt(
'ENSRegistry',
ensRegistryAddress
const [deployer] = await ethers.getSigners();

const ensRegistryContract = ENSRegistry__factory.connect(
ensRegistryAddress,
deployer
);

const daoDomainSplitted = fullDomain.split('.').reverse();
Expand Down
19 changes: 12 additions & 7 deletions packages/contracts/deploy/new/00_managing-dao/00_managing-dao.ts
Original file line number Diff line number Diff line change
@@ -1,34 +1,39 @@
import {HardhatRuntimeEnvironment} from 'hardhat/types';
Rekard0 marked this conversation as resolved.
Show resolved Hide resolved
import {DeployFunction} from 'hardhat-deploy/types';
import {ArtifactData, DeployFunction} from 'hardhat-deploy/types';

import daoArtifactJson from '../../../artifacts/src/core/dao/DAO.sol/DAO.json';
/** NOTE:
* Create a (Managing DAO) with no Plugin, to be the owner DAO for the framework, temporarily.
*/

const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) {
console.log(`\nDeploying ManagingDao.`);

const {deployments, getNamedAccounts, ethers} = hre;
const {deployments, ethers} = hre;
const {deploy} = deployments;
const {deployer} = await getNamedAccounts();
const [deployer] = await ethers.getSigners();

console.log(
`ManagingDAO will be owned by the (Deployer: ${deployer}) temporarily, while the entire framework is getting deployed.` +
`ManagingDAO will be owned by the (Deployer: ${deployer.address}) temporarily, while the entire framework is getting deployed.` +
` At the final step when Multisig is available, it will be installed on managingDAO and all roles for the Deployer will be revoked.`
);

const initializeParams = {
metadata: '0x',
initialOwner: deployer,
initialOwner: deployer.address,
trustedForwarder: ethers.constants.AddressZero,
daoURI: '0x',
};

const daoArtifactData = daoArtifactJson as ArtifactData;

await deploy('DAO', {
from: deployer,
contract: daoArtifactData,
from: deployer.address,
args: [],
log: true,
proxy: {
owner: deployer,
owner: deployer.address,
proxyContract: 'ERC1967Proxy',
proxyArgs: ['{implementation}', '{data}'],
execute: {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,28 +1,31 @@
import {DeployFunction} from 'hardhat-deploy/types';
import {HardhatRuntimeEnvironment} from 'hardhat/types';

import {Operation} from '../../../utils/types';

import {getContractAddress, managePermissions} from '../../helpers';
import {DAO__factory} from '../../../typechain';

const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) {
const {getNamedAccounts, ethers} = hre;
const {deployer} = await getNamedAccounts();
const {ethers} = hre;
const [deployer] = await ethers.getSigners();

console.log(`Granting ${deployer.address} temp execute permissions`);

console.log(`Granting ${deployer} temp execute permissions`);
// Get `managingDAO` address.
const managingDAOAddress = await getContractAddress('DAO', hre);

// Get `DAO` contract.
const managingDaoContract = await ethers.getContractAt(
'DAO',
managingDAOAddress
const managingDaoContract = DAO__factory.connect(
managingDAOAddress,
deployer
);

// grant the deployer execute permissions during deployment. This will be revoked in 40_finalize-managing-dao/40_revoke-permissions
await managePermissions(managingDaoContract, [
{
operation: Operation.Grant,
where: {name: 'DAO', address: managingDAOAddress},
who: {name: 'Deployer', address: deployer},
who: {name: 'Deployer', address: deployer.address},
permission: 'EXECUTE_PERMISSION',
},
]);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,18 +7,20 @@ import {
getContractAddress,
managePermissions,
} from '../../helpers';
import {DAO__factory} from '../../../typechain';

const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) {
console.log('\nSetting ManagingDao permissions.');
const {ethers} = hre;
const [deployer] = await ethers.getSigners();

// Get `managingDAO` address.
const managingDAOAddress = await getContractAddress('DAO', hre);

// Get `DAO` contract.
const managingDaoContract = await ethers.getContractAt(
'DAO',
managingDAOAddress
const managingDaoContract = DAO__factory.connect(
managingDAOAddress,
deployer
);

// Set all the permission needed for a DAO to operate normally as if it was created via DAOFactory.
Expand Down
11 changes: 6 additions & 5 deletions packages/contracts/deploy/new/00_managing-dao/99_verify_step.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,26 +7,27 @@ import {
DAO_PERMISSIONS,
getContractAddress,
} from '../../helpers';
import {DAO__factory} from '../../../typechain';

const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) {
console.log('\nVerifying managing DAO deployment.');

const {getNamedAccounts, ethers} = hre;
const {deployer} = await getNamedAccounts();
const [deployer] = await ethers.getSigners();

// Get `managingDAO` address.
const managingDAOAddress = await getContractAddress('DAO', hre);
// Get `DAO` contract.
const managingDaoContract = await ethers.getContractAt(
'DAO',
managingDAOAddress
const managingDaoContract = DAO__factory.connect(
managingDAOAddress,
deployer
);

// Check that deployer has root permission.
await checkPermission(managingDaoContract, {
operation: Operation.Grant,
where: {name: 'ManagingDAO', address: managingDAOAddress},
who: {name: 'Deployer', address: deployer},
who: {name: 'Deployer', address: deployer.address},
permission: 'ROOT_PERMISSION',
});

Expand Down
Loading