Skip to content

Commit

Permalink
Merge pull request #65 from rsksmart/feature/PP-278/PP-239/PP-438
Browse files Browse the repository at this point in the history
Deployment Script Hardhat
  • Loading branch information
ironFe93 authored Oct 4, 2022
2 parents d65de2a + dd109f1 commit dc471e9
Show file tree
Hide file tree
Showing 6 changed files with 264 additions and 4 deletions.
1 change: 1 addition & 0 deletions hardhat.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ const config: HardhatUserConfig = {
networks: {
regtest: {
url: 'http://localhost:4444',
chainId: 33
},
},
typechain: {
Expand Down
7 changes: 7 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,10 @@
{
"name": "Francisco Tobar",
"url": "https://github.com/franciscotobar"
},
{
"name": "Christos Otarola",
"url": "https://github/ironFe93"
}
],
"main": "dist/index.js",
Expand Down Expand Up @@ -82,12 +86,15 @@
"hardhat-dependency-compiler": "^1.1.3",
"hardhat-docgen": "^1.3.0",
"hardhat-watcher": "^2.5.0",
"sinon": "^14.0.0",
"typechain": "^8.0.0"
},
"devDependencies": {
"@commitlint/cli": "^17.0.3",
"@commitlint/config-conventional": "^17.0.3",
"@defi-wonderland/smock": "^2.2.0",
"@openzeppelin/contracts": "^3.4.0",
"@types/sinon": "^10.0.13",
"@typescript-eslint/eslint-plugin": "^5.35.1",
"@typescript-eslint/parser": "^5.33.1",
"chai-as-promised": "^7.1.1",
Expand Down
8 changes: 4 additions & 4 deletions scripts/deploy.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { constants } from 'ethers';
import { ethers } from 'hardhat';
import { deployContracts, generateJsonConfig } from './modules/deploy';

// FIXME: add contract deployment
const main = async () => {
await ethers.getContractAt('CustomSmartWallet', constants.AddressZero);
const contractAddresses = await deployContracts();
console.table(contractAddresses);
generateJsonConfig(contractAddresses);
};

// We recommend this pattern to be able to use async/await everywhere
Expand Down
16 changes: 16 additions & 0 deletions scripts/interfaces/contracts.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
export interface IContractAddresses {
Penalizer: string;
RelayHub: string;
SmartWallet: string;
SmartWalletFactory: string;
SmartWalletDeployVerifier: string;
SmartWalletRelayVerifier: string;
CustomSmartWallet: string;
CustomSmartWalletFactory: string;
CustomSmartWalletDeployVerifier: string;
CustomSmartWalletRelayVerifier: string;
UtilToken: string;
}
export interface IChainContractAddresses {
[key: string]: IContractAddresses
}
108 changes: 108 additions & 0 deletions scripts/modules/deploy.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
import { ethers, hardhatArguments, config } from 'hardhat';
import fs from 'fs';
import {
IChainContractAddresses,
IContractAddresses,
} from '../interfaces/contracts';

export const generateJsonConfig = (contractAddresses: IContractAddresses) => {
console.log('Generating json config file...');

const configFileName = 'contract-addresses.json';
let jsonConfig: Partial<IChainContractAddresses>;

if (fs.existsSync(configFileName)) {
jsonConfig = JSON.parse(
fs.readFileSync(configFileName, { encoding: 'utf-8' })
) as IChainContractAddresses;
} else {
jsonConfig = {};
}

const { network } = hardhatArguments;
if (!network) {
throw new Error('Unknown Network');
}
const { chainId } = config.networks[network];

if (!chainId) {
throw new Error('Unknown Chain Id');
}

jsonConfig[chainId] = contractAddresses;

fs.writeFileSync('contract-addresses.json', JSON.stringify(jsonConfig));
};

export const deployContracts = async () => {
const relayHubF = await ethers.getContractFactory('RelayHub');
const penalizerF = await ethers.getContractFactory('Penalizer');
const smartWalletF = await ethers.getContractFactory('SmartWallet');
const smartWalletFactoryF = await ethers.getContractFactory(
'SmartWalletFactory'
);
const deployVerifierF = await ethers.getContractFactory('DeployVerifier');
const relayVerifierF = await ethers.getContractFactory('RelayVerifier');
const utilTokenF = await ethers.getContractFactory('UtilToken');

const customSmartWalletF = await ethers.getContractFactory(
'CustomSmartWallet'
);
const customSmartWalletFactoryF = await ethers.getContractFactory(
'CustomSmartWalletFactory'
);
const customSmartWalletDeployVerifierF = await ethers.getContractFactory(
'CustomSmartWalletDeployVerifier'
);

const { address: penalizerAddress } = await penalizerF.deploy();
const { address: relayHubAddress } = await relayHubF.deploy(
penalizerAddress,
1,
1,
1,
1
);
const { address: smartWalletAddress } = await smartWalletF.deploy();
const { address: smartWalletFactoryAddress } =
await smartWalletFactoryF.deploy(smartWalletAddress);
const { address: deployVerifierAddress } = await deployVerifierF.deploy(
smartWalletFactoryAddress
);
const { address: relayVerifierAddress } = await relayVerifierF.deploy(
smartWalletFactoryAddress
);

const { address: customSmartWalletAddress } =
await customSmartWalletF.deploy();
const { address: customSmartWalletFactoryAddress } =
await customSmartWalletFactoryF.deploy(customSmartWalletAddress);
const { address: customDeployVerifierAddress } =
await customSmartWalletDeployVerifierF.deploy(
customSmartWalletFactoryAddress
);

const { address: customRelayVerifierAddress } = await relayVerifierF.deploy(
customSmartWalletFactoryAddress
);

let utilTokenAddress;
if(hardhatArguments.network != 'mainnet'){
const { address } = await utilTokenF.deploy();
utilTokenAddress = address
}

return {
Penalizer: penalizerAddress,
RelayHub: relayHubAddress,
SmartWallet: smartWalletAddress,
SmartWalletFactory: smartWalletFactoryAddress,
SmartWalletDeployVerifier: deployVerifierAddress,
SmartWalletRelayVerifier: relayVerifierAddress,
CustomSmartWallet: customSmartWalletAddress,
CustomSmartWalletFactory: customSmartWalletFactoryAddress,
CustomSmartWalletDeployVerifier: customDeployVerifierAddress,
CustomSmartWalletRelayVerifier: customRelayVerifierAddress,
UtilToken: utilTokenAddress,
};
};
128 changes: 128 additions & 0 deletions test/scripts/deploy.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
import chai, { expect } from 'chai';
import chaiAsPromised from 'chai-as-promised';
import { Contract, ContractFactory } from 'ethers';
import { ethers } from 'hardhat';
import sinon from 'sinon';
import fs from 'fs';
import * as hardhat from 'hardhat';
import {
deployContracts,
generateJsonConfig,
} from '../../scripts/modules/deploy';

chai.use(chaiAsPromised);

describe('Deploy Script', function () {
describe('deployContracts', function () {
const testAddress = '0x145845fd06c85B7EA1AA2d030E1a747B3d8d15D7';
beforeEach(function () {
const contract = new Contract(testAddress, []);
const contractFactoryStub = sinon.createStubInstance(ContractFactory);
sinon.stub(ethers, 'getContractFactory').resolves(contractFactoryStub);
contractFactoryStub.deploy.resolves(contract);
});

afterEach(function () {
sinon.restore();
});

it('should deploy all contracts', async function () {
const result = await deployContracts();
expect(result).to.have.all.keys(
'Penalizer',
'RelayHub',
'SmartWallet',
'SmartWalletFactory',
'SmartWalletDeployVerifier',
'SmartWalletRelayVerifier',
'CustomSmartWallet',
'CustomSmartWalletFactory',
'CustomSmartWalletDeployVerifier',
'CustomSmartWalletRelayVerifier',
'UtilToken'
);
});

it('should deploy contracts with valid addresses', async function () {
const result = await deployContracts();
Object.values(result).forEach((value) => {
expect(value, value).to.eq(testAddress);
});
});

it('should not deploy UtilToken if not in mainnet', async function () {
hardhat.hardhatArguments.network = 'mainnet';
const result = await deployContracts();
expect(result.UtilToken).to.be.undefined
});
});

describe('generateJsonConfig', function () {
const contractAddresses = {
Penalizer: '0x145845fd06c85B7EA1AA2d030E1a747B3d8d15D7',
RelayHub: '0x145845fd06c85B7EA1AA2d030E1a747B3d8d15D7',
SmartWallet: '0x145845fd06c85B7EA1AA2d030E1a747B3d8d15D7',
SmartWalletFactory: '0x145845fd06c85B7EA1AA2d030E1a747B3d8d15D7',
SmartWalletDeployVerifier: '0x145845fd06c85B7EA1AA2d030E1a747B3d8d15D7',
SmartWalletRelayVerifier: '0x145845fd06c85B7EA1AA2d030E1a747B3d8d15D7',
CustomSmartWallet: '0x145845fd06c85B7EA1AA2d030E1a747B3d8d15D7',
CustomSmartWalletFactory: '0x145845fd06c85B7EA1AA2d030E1a747B3d8d15D7',
CustomSmartWalletDeployVerifier:
'0x145845fd06c85B7EA1AA2d030E1a747B3d8d15D7',
CustomSmartWalletRelayVerifier:
'0x145845fd06c85B7EA1AA2d030E1a747B3d8d15D7',
UtilToken: '0x145845fd06c85B7EA1AA2d030E1a747B3d8d15D7',
};

const chainContractAddresses = {
'33': contractAddresses,
};

let spyWriteFileSync: sinon.SinonSpy;

beforeEach(function () {
spyWriteFileSync = sinon.spy(fs, 'writeFileSync');
hardhat.hardhatArguments.network = 'regtest';
hardhat.config.networks.regtest.chainId = 33;
});

afterEach(function () {
sinon.restore();
});

it('should generate a json config file with existing config file', function () {
sinon.stub(fs, 'existsSync').returns(true);
sinon
.stub(fs, 'readFileSync')
.returns(JSON.stringify(chainContractAddresses));
generateJsonConfig(contractAddresses);
spyWriteFileSync.calledOnceWith('contract-addresses.json', JSON.stringify(chainContractAddresses));
});

it('should generate a json config file when config file is not present', function () {
sinon.stub(fs, 'existsSync').returns(false);
generateJsonConfig(contractAddresses);
spyWriteFileSync.calledOnceWith('contract-addresses.json', JSON.stringify(chainContractAddresses));
});

it('should throw if network is undefined', function () {
sinon.stub(fs, 'existsSync').returns(true);
sinon
.stub(fs, 'readFileSync')
.returns(JSON.stringify(chainContractAddresses));
hardhat.hardhatArguments.network = undefined;
hardhat.config.networks.regtest.chainId = 33;
expect(() => generateJsonConfig(contractAddresses)).to.throw('Unknown Network');
});

it('should throw if chainId is undefined', function () {
sinon.stub(fs, 'existsSync').returns(true);
sinon
.stub(fs, 'readFileSync')
.returns(JSON.stringify(chainContractAddresses));
hardhat.hardhatArguments.network = 'regtest';
hardhat.config.networks.regtest.chainId = undefined;
expect(() => generateJsonConfig(contractAddresses)).to.throw('Unknown Chain Id');
});
});
});

0 comments on commit dc471e9

Please sign in to comment.