Skip to content

[WIP] Feat: Upgrade Functionality #2

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

Open
wants to merge 45 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
45 commits
Select commit Hold shift + click to select a range
171fd7a
refactor clearDBForVersion
Whytecrowe Feb 6, 2024
faaeba3
rename current db getter and add another one for deployed version
Whytecrowe Feb 6, 2024
bb93140
draft the BaseUpgradeMission for needed method placeholders and place…
Whytecrowe Feb 6, 2024
8e870b1
add an enum for all the possible operations for upgrade
Whytecrowe Feb 7, 2024
816e1eb
make version an optional field on IContractDbData
Whytecrowe Feb 7, 2024
0a47a31
fix wrongly named DB getters on base mission
Whytecrowe Feb 7, 2024
0b1cb3d
use the new enum in upgrade mission and add dbCopy method
Whytecrowe Feb 7, 2024
a6db753
refactor and make new deployer types for the upgradeProxy calls
Whytecrowe Feb 8, 2024
2690082
add upgradeProxy method that uses hardhat-upgrades under the hood
Whytecrowe Feb 8, 2024
a06fd5e
implement upgrade() method along with implementing other placeholders…
Whytecrowe Feb 8, 2024
e2c4954
extract tx awaiting logic on HardhatDeployer into it's own method and…
Whytecrowe Feb 8, 2024
f7aefa0
remove redundant bytecode comparison and try to rely on upgrades for …
Whytecrowe Feb 8, 2024
ae765c0
install HH related packages as devDeps
Whytecrowe Feb 10, 2024
b005b4d
add include field in tsconfig to only compile src folder
Whytecrowe Feb 10, 2024
deadf03
start refatoring types on HardhatDeployer
Whytecrowe Feb 10, 2024
b87f933
finish retyping HardhatDeployer
Whytecrowe Feb 12, 2024
e27d0c5
remove usage of IHardhatBase and ISignerBase from the main classes an…
Whytecrowe Feb 12, 2024
846c55b
remove IHardhatBase type and fix types in all existing classes
Whytecrowe Feb 12, 2024
04d0467
remove src and test folders from the package
Whytecrowe Feb 12, 2024
17cf776
start fixing tests
Whytecrowe Feb 12, 2024
b39a9cf
specify what goes into the module's package in package.json
Whytecrowe Feb 13, 2024
10aacd8
fix some base types
Whytecrowe Feb 13, 2024
eb1460c
Merge branch 'type-refactor' into feat/upgrade-logic
Whytecrowe Feb 13, 2024
cbe8bd9
add "clean" script and add that to the build
Whytecrowe Feb 13, 2024
a2437ac
fix types and patch holes, remove redundant type args everywhere
Whytecrowe Feb 13, 2024
43782b8
fix incorrect db getter calls
Whytecrowe Feb 16, 2024
f62d9b1
add methods to read all version docs from db
Whytecrowe Feb 16, 2024
af0b4a9
add source maps to tsconfig
Whytecrowe Feb 20, 2024
848cb5f
fix a bug in execute of Upgrade mission
Whytecrowe Feb 20, 2024
d72003a
Merge branch 'master' into feat/upgrade-logic
Whytecrowe Sep 12, 2024
9cab7a0
fix errors after update from master
Whytecrowe Sep 12, 2024
d3f5405
update hardhat and ethers packages
Whytecrowe Sep 12, 2024
b15d55f
fix versioner to archive only at the end of campaign run
Whytecrowe Sep 26, 2024
fdf798f
update eslint config
Whytecrowe Oct 1, 2024
3b03537
add bytecode comparison func draft
Whytecrowe Oct 1, 2024
b184460
start reworking upgrade determination logic after all the testing:
Whytecrowe Oct 1, 2024
5b14e5d
remove redundant deploy await method from deployer
Whytecrowe Oct 3, 2024
8356ca4
refactoring and new logic:
Whytecrowe Oct 3, 2024
c878c70
Merge branch 'master' into feat/upgrade-logic
Whytecrowe Mar 19, 2025
fa94e9b
fix compiler errors
Whytecrowe Mar 19, 2025
644db95
update yarn.lock
Whytecrowe Mar 19, 2025
d9a1b73
renormalize line endings for the whole repo
Whytecrowe Mar 19, 2025
447fcbc
renormalize repo again
Whytecrowe Mar 19, 2025
ecdeea1
update vulnerable axios package
Whytecrowe Mar 19, 2025
5092477
update eslintrc to turn off removed rule
Whytecrowe Mar 19, 2025
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
5 changes: 3 additions & 2 deletions .eslintrc
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,13 @@
"no-console": "off",
"no-shadow": "warn",
"@typescript-eslint/no-shadow": "warn",
"no-invalid-this": "off"
"no-invalid-this": "off",
"jsdoc/newline-after-description": "off"
// "@typescript-eslint/no-unused-vars": "off" // For debugging
},
"parserOptions": {
"project": "./tsconfig.eslint.json"
}
}
]
}
}
4 changes: 2 additions & 2 deletions .npmignore
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
.idea
src
.eslintrc
tsconfig.json
test
src/
test/
.circleci
```
11 changes: 8 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@
"npm": ">=9"
},
"scripts": {
"build": "tsc",
"clean": "rm -rf dist",
"build": "yarn clean && tsc",
"prepare": "yarn build",
"lint": "yarn eslint .",
"test": "mocha --require ts-node/register ./test/cases/*.ts"
Expand All @@ -24,14 +25,18 @@
"lint"
],
"dependencies": {
"axios": "1.7.4",
"axios": "^1.8.4",
"mongodb": "^6.3.0",
"winston": "^3.11.0"
},
"devDependencies": {
"@types/mocha": "^10.0.6",
"@types/node": "^18.15.11",
"@zero-tech/eslint-config-cpt": "0.2.7",
"ethers": "^6.13.2",
"hardhat": "^2.22.10",
"@openzeppelin/hardhat-upgrades": "^3.2.1",
"@nomicfoundation/hardhat-ethers": "^3.0.8",
"@zero-tech/eslint-config-cpt": "0.2.8",
"eslint": "^8.56.0",
"mocha": "^10.2.0",
"ts-node": "10.9.1",
Expand Down
24 changes: 11 additions & 13 deletions src/campaign/deploy-campaign.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,24 +3,22 @@ import {
ICampaignState,
TLogger,
IMissionInstances,
IContractV6, IDeployCampaignConfig, IContractState,
IDeployCampaignConfig, IContractState,
} from "./types";
import { HardhatDeployer } from "../deployer/hardhat-deployer";
import { ITenderlyContractData, TDeployMissionCtor } from "../missions/types";
import { BaseDeployMission } from "../missions/base-deploy-mission";
import { MongoDBAdapter } from "../db/mongo-adapter/mongo-adapter";
import { IHardhatBase, ISignerBase } from "../deployer/types";
import { makeCampaignProxy } from "./proxy";
import { Contract } from "ethers";


export class DeployCampaign <
H extends IHardhatBase,
S extends ISignerBase,
C extends IDeployCampaignConfig<S>,
C extends IDeployCampaignConfig,
St extends IContractState,
> {
state : ICampaignState<H, S, C, St>;
deployer : HardhatDeployer<H, S>;
state : ICampaignState<C, St>;
deployer : HardhatDeployer;
dbAdapter : MongoDBAdapter;
logger : TLogger;
config : C;
Expand All @@ -35,7 +33,7 @@ export class DeployCampaign <
dbAdapter,
logger,
config,
} : ICampaignArgs<H, S, C, St>) {
} : ICampaignArgs<C, St>) {
this.state = {
missions,
instances: {},
Expand All @@ -50,7 +48,7 @@ export class DeployCampaign <

// instantiate all missions
this.state.instances = missions.reduce(
(acc : IMissionInstances<H, S, C, St>, mission : TDeployMissionCtor<H, S, C, St>) => {
(acc : IMissionInstances<C, St>, mission : TDeployMissionCtor<C, St>) => {
const instance = new mission({
campaign: campaignProxy,
logger,
Expand Down Expand Up @@ -85,7 +83,7 @@ export class DeployCampaign <
await Object.values(this.state.instances).reduce(
async (
acc : Promise<void>,
missionInstance : BaseDeployMission<H, S, C, St>,
missionInstance : BaseDeployMission<C, St>,
) : Promise<void> => {
await acc;
return missionInstance.execute();
Expand All @@ -105,7 +103,7 @@ export class DeployCampaign <
this.logger.info(`Deploy Campaign execution finished successfully under DB Version: ${this.dbAdapter.versioner.curDbVersion}.`);
}

updateStateContract (instanceName : string, contractName : string, contract : IContractV6) {
updateStateContract (instanceName : string, contractName : string, contract : Contract) {
// TODO: can we improve this?
(this.state.contracts as IContractState)[instanceName] = contract;
this.logger.debug(`Data of deployed contract '${contractName}' is added to Campaign state at '${instanceName}'.`);
Expand All @@ -115,7 +113,7 @@ export class DeployCampaign <
return Object.values(this.state.instances).reduce(
async (
acc : Promise<void>,
missionInstance : BaseDeployMission<H, S, C, St>,
missionInstance : BaseDeployMission<C, St>,
) => {
await acc;
return missionInstance.verify();
Expand All @@ -130,7 +128,7 @@ export class DeployCampaign <
const contracts = await Object.values(this.state.instances).reduce(
async (
acc : Promise<Array<ITenderlyContractData>>,
missionInstance : BaseDeployMission<H, S, C, St>,
missionInstance : BaseDeployMission<C, St>,
) : Promise<Array<ITenderlyContractData>> => {
const newAcc = await acc;
const data = await missionInstance.getMonitoringData();
Expand Down
7 changes: 2 additions & 5 deletions src/campaign/proxy.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,10 @@
import { IHardhatBase, ISignerBase } from "../deployer/types";
import { DeployCampaign } from "./deploy-campaign";
import { IContractState, IDeployCampaignConfig } from "./types";

export const makeCampaignProxy = <
H extends IHardhatBase,
S extends ISignerBase,
C extends IDeployCampaignConfig<S>,
C extends IDeployCampaignConfig,
St extends IContractState,
> (campaign : DeployCampaign<H, S, C, St>) => new Proxy(campaign, {
> (campaign : DeployCampaign<C, St>) => new Proxy(campaign, {
get : (target, prop) => {
if (typeof prop === "string") {
if (!!target.state.contracts[prop]) {
Expand Down
71 changes: 30 additions & 41 deletions src/campaign/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@ import { TDeployMissionCtor } from "../missions/types";
import { HardhatDeployer } from "../deployer/hardhat-deployer";
import { Logger as WinstonLogger } from "winston";
import { MongoDBAdapter } from "../db/mongo-adapter/mongo-adapter";
import { IHardhatBase, ISignerBase, TEnvironment } from "../deployer/types";
import { TSigner, TEnvironment } from "../deployer/types";
import { ContractInterface, BaseContract } from "ethers";


export type TSupportedChain = "zchain" | "ethereum";
Expand All @@ -12,6 +13,19 @@ export interface ISupportedChains {
eth : TSupportedChain;
}

export interface IDeployCampaignConfig extends IBaseDataMap {
env : TEnvironment;
upgrade : boolean;
deployAdmin : TSigner;
confirmationsN : number;
srcChainName : TSupportedChain;
postDeploy : {
tenderlyProjectSlug : string;
monitorContracts : boolean;
verifyContracts : boolean;
};
}

export interface ITransactionReceipt {
hash : string;
}
Expand All @@ -24,74 +38,49 @@ export type TCampaignDataType = bigint
| boolean
| object;

export interface IBaseDataMap<T> {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
[key : string] : TCampaignDataType | T | IBaseDataMap<T> | undefined;
export interface IBaseDataMap {
[key : string] : TCampaignDataType | TSigner | undefined;
}

export interface IAddressable {
getAddress : () => Promise<string>;
}

export type TLogger = WinstonLogger | Console;

export interface ITransactionResponseBase {
wait(confirms ?: number, timeout ?: number) : Promise<ITransactionReceipt | null>;
}

export interface IContractV6 {
getAddress : () => Promise<string>;
waitForDeployment : () => Promise<IContractV6>;
deploymentTransaction : () => ITransactionResponseBase | null;
target : string | IAddressable;
interface : object;
}

export type TLogger = WinstonLogger | Console;
export type TGeneralContract = BaseContract & Omit<ContractInterface, keyof BaseContract>;

export interface IContractState<C extends IContractV6 = IContractV6> {
[key : string] : C;
export interface IContractState {
[name : string] : BaseContract;
}

export interface IMissionInstances <
H extends IHardhatBase,
S extends ISignerBase,
C extends IDeployCampaignConfig<S>,
C extends IDeployCampaignConfig,
St extends IContractState,
> {
[key : string] : BaseDeployMission<H, S, C, St>;
[key : string] : BaseDeployMission<C, St>;
}

export interface ICampaignState <
H extends IHardhatBase,
S extends ISignerBase,
C extends IDeployCampaignConfig<S>,
C extends IDeployCampaignConfig,
St extends IContractState,
> {
missions : Array<TDeployMissionCtor<H, S, C, St>>;
instances : IMissionInstances<H, S, C, St>;
missions : Array<TDeployMissionCtor<C, St>>;
instances : IMissionInstances<C, St>;
contracts : St;
}

export interface ICampaignArgs <
H extends IHardhatBase,
S extends ISignerBase,
C extends IDeployCampaignConfig<S>,
C extends IDeployCampaignConfig,
St extends IContractState,
> {
missions : Array<TDeployMissionCtor<H, S, C, St>>;
deployer : HardhatDeployer<H, S>;
missions : Array<TDeployMissionCtor<C, St>>;
deployer : HardhatDeployer;
dbAdapter : MongoDBAdapter;
logger : TLogger;
config : C;
}

export interface IDeployCampaignConfig <Signer> extends IBaseDataMap<Signer> {
env : TEnvironment;
deployAdmin : Signer;
confirmationsN : number;
srcChainName : TSupportedChain;
postDeploy : {
tenderlyProjectSlug : string;
monitorContracts : boolean;
verifyContracts : boolean;
};
}
14 changes: 6 additions & 8 deletions src/create.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,12 @@
import { getLogger } from "./logger/create-logger";
import { HardhatDeployer, IHardhatBase, ISignerBase } from "./deployer";
import { HardhatDeployer, HardhatExtended } from "./deployer";
import { DeployCampaign, IContractState, IDeployCampaignConfig, TLogger } from "./campaign";
import { getMongoAdapter, MongoDBAdapter } from "./db";
import { TDeployMissionCtor } from "./missions";


export const createDeployCampaign = async <
H extends IHardhatBase,
S extends ISignerBase,
C extends IDeployCampaignConfig<S>,
C extends IDeployCampaignConfig,
St extends IContractState,
> ({
hre,
Expand All @@ -24,10 +22,10 @@ export const createDeployCampaign = async <
clientOpts,
contractsVersion,
} : {
hre : H;
hre : HardhatExtended;
config : C;
missions : Array<TDeployMissionCtor<H, S, C, St>>;
deployer ?: HardhatDeployer<H, S>;
missions : Array<TDeployMissionCtor<C, St>>;
deployer ?: HardhatDeployer;
logger ?: TLogger;
dbAdapter ?: MongoDBAdapter;
dbUri ?: string;
Expand Down Expand Up @@ -58,7 +56,7 @@ export const createDeployCampaign = async <
clientOpts,
});

return new DeployCampaign<H, S, C, St>({
return new DeployCampaign<C, St>({
missions,
deployer,
dbAdapter,
Expand Down
2 changes: 1 addition & 1 deletion src/db/mongo-adapter/get-adapter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ export const getMongoAdapter = async ({
contractsVersion,
};

if (!mongoAdapter) {
if (mongoAdapter === null) {
logger.debug("Creating new MongoDBAdapter instance");
mongoAdapter = new MongoDBAdapter({
...params,
Expand Down
6 changes: 1 addition & 5 deletions src/db/mongo-adapter/mongo-adapter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -112,11 +112,7 @@ export class MongoDBAdapter {
}

async clearDBForVersion (version : string) {
await this.contracts.deleteMany({
version,
});

return this.versioner.clearDBForVersion(version);
return this.versioner.clearDBForVersion(version, this.db);
}

async finalize (version ?: string) {
Expand Down
2 changes: 1 addition & 1 deletion src/db/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ export interface IContractDbData {
abi : string;
bytecode : string;
implementation : string | null;
version : string;
version ?: string;
}

export type TContractDBDoc = WithId<IContractDbData> & IContractDbData;
Loading