diff --git a/package-lock.json b/package-lock.json index 23cab14..b8c0780 100644 --- a/package-lock.json +++ b/package-lock.json @@ -14,7 +14,6 @@ "@nomicfoundation/hardhat-verify": "1.1.1", "@nomiclabs/hardhat-truffle5": "2.0.7", "axios": "1.5.0", - "bignumber.js": "9.1.2", "ora": "5.4.1" }, "devDependencies": { @@ -35,7 +34,7 @@ "eslint-plugin-import": "^2.28.1", "eslint-plugin-prettier": "^5.0.0", "eslint-plugin-promise": "^6.1.1", - "ethers": "^6.7.1", + "ethers": "^6.8.0", "hardhat": "^2.17.0", "mocha": "^10.0.0", "pinst": "^3.0.0", @@ -5491,6 +5490,7 @@ "resolved": "https://registry.npmjs.org/abstract-leveldown/-/abstract-leveldown-7.2.0.tgz", "integrity": "sha512-DnhQwcFEaYsvYDnACLZhMmCWd3rkOeEvglpa4q5i/5Jlm3UIsWaxVzuXvDLFCSCWRO3yy2/+V/G7FusFgejnfQ==", "dev": true, + "optional": true, "peer": true, "dependencies": { "buffer": "^6.0.3", @@ -5523,6 +5523,7 @@ "url": "https://feross.org/support" } ], + "optional": true, "peer": true, "dependencies": { "base64-js": "^1.3.1", @@ -5534,6 +5535,7 @@ "resolved": "https://registry.npmjs.org/level-supports/-/level-supports-2.1.0.tgz", "integrity": "sha512-E486g1NCjW5cF78KGPrMDRBYzPuueMZ6VBXHT6gC7A8UYWGiM14fGgp+s/L1oFfDWSPV/+SFkYCmZ0SiESkRKA==", "dev": true, + "optional": true, "peer": true, "engines": { "node": ">=10" @@ -6387,6 +6389,7 @@ "version": "9.1.2", "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.1.2.tgz", "integrity": "sha512-2/mKyZH9K85bzOEfhXDBFZTGd1CTs+5IHpeFQo9luiBG7hghdC851Pj2WAhb6E3R6b9tZj/XKhbg4fum+Kepug==", + "dev": true, "engines": { "node": "*" } @@ -7995,6 +7998,7 @@ "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.4.1.tgz", "integrity": "sha512-r4eRSeStEGf6M5SKdrQhhLK5bOwOBxQhIE3YSTnZE3GpKiLfnnhE+tPtrJE79+eDJgm39BM6LSoI8SCx4HbwlQ==", "dev": true, + "optional": true, "peer": true, "engines": { "node": ">=6" @@ -14322,6 +14326,7 @@ "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.3.0.tgz", "integrity": "sha512-HR7EVodfFUdQCTIeySw+WDRFJlPcLOJbXfwwZ7Oom6tjsvZ3bOkCDJHehQC3nxJrv7+f9XecwazynjU8e4Vw3Q==", "dev": true, + "optional": true, "peer": true }, "node_modules/immutable": { @@ -15129,6 +15134,7 @@ "resolved": "https://registry.npmjs.org/level-concat-iterator/-/level-concat-iterator-3.1.0.tgz", "integrity": "sha512-BWRCMHBxbIqPxJ8vHOvKUsaO0v1sLYZtjN3K2iZJsRBYtp+ONsY6Jfi6hy9K3+zolgQRryhIn2NRZjZnWJ9NmQ==", "dev": true, + "optional": true, "peer": true, "dependencies": { "catering": "^2.1.0" @@ -15299,6 +15305,7 @@ "integrity": "sha512-iB8O/7Db9lPaITU1aA2txU/cBEXAt4vWwKQRrrWuS6XDgbP4QZGj9BL2aNbwb002atoQ/lIotJkfyzz+ygQnUQ==", "dev": true, "hasInstallScript": true, + "optional": true, "peer": true, "dependencies": { "abstract-leveldown": "~6.2.1", @@ -15314,6 +15321,7 @@ "resolved": "https://registry.npmjs.org/abstract-leveldown/-/abstract-leveldown-6.2.3.tgz", "integrity": "sha512-BsLm5vFMRUrrLeCcRc+G0t2qOaTzpoJQLOubq2XM72eNpjF5UdU5o/5NvlNhx95XHcAvcl8OMXr4mlg/fRgUXQ==", "dev": true, + "optional": true, "peer": true, "dependencies": { "buffer": "^5.5.0", @@ -15331,6 +15339,7 @@ "resolved": "https://registry.npmjs.org/level-concat-iterator/-/level-concat-iterator-2.0.1.tgz", "integrity": "sha512-OTKKOqeav2QWcERMJR7IS9CUo1sHnke2C0gkSmcR7QuEtFNLLzHQAvnMw8ykvEcv0Qtkg0p7FOwP1v9e5Smdcw==", "dev": true, + "optional": true, "peer": true, "engines": { "node": ">=6" @@ -15341,6 +15350,7 @@ "resolved": "https://registry.npmjs.org/level-supports/-/level-supports-1.0.1.tgz", "integrity": "sha512-rXM7GYnW8gsl1vedTJIbzOrRv85c/2uCMpiiCzO2fndd06U/kUXEEU9evYn4zFggBOg36IsBW8LzqIpETwwQzg==", "dev": true, + "optional": true, "peer": true, "dependencies": { "xtend": "^4.0.2" @@ -15354,6 +15364,7 @@ "resolved": "https://registry.npmjs.org/napi-macros/-/napi-macros-2.0.0.tgz", "integrity": "sha512-A0xLykHtARfueITVDernsAWdtIMbOJgKgcluwENp3AlsKN/PloyO10HtmoqnFAQAcxPkgZN7wdfPfEd0zNGxbg==", "dev": true, + "optional": true, "peer": true }, "node_modules/leveldown/node_modules/node-gyp-build": { @@ -15361,6 +15372,7 @@ "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.1.1.tgz", "integrity": "sha512-dSq1xmcPDKPZ2EED2S6zw/b9NKsqzXRE6dVr8TVQnI3FJOTteUMuqF3Qqs6LZg+mLGYJWqQzMbIjMtJqTv87nQ==", "dev": true, + "optional": true, "peer": true, "bin": { "node-gyp-build": "bin.js", @@ -25475,6 +25487,7 @@ "resolved": "https://registry.npmjs.org/abstract-leveldown/-/abstract-leveldown-7.2.0.tgz", "integrity": "sha512-DnhQwcFEaYsvYDnACLZhMmCWd3rkOeEvglpa4q5i/5Jlm3UIsWaxVzuXvDLFCSCWRO3yy2/+V/G7FusFgejnfQ==", "dev": true, + "optional": true, "peer": true, "requires": { "buffer": "^6.0.3", @@ -25490,6 +25503,7 @@ "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", "dev": true, + "optional": true, "peer": true, "requires": { "base64-js": "^1.3.1", @@ -25501,6 +25515,7 @@ "resolved": "https://registry.npmjs.org/level-supports/-/level-supports-2.1.0.tgz", "integrity": "sha512-E486g1NCjW5cF78KGPrMDRBYzPuueMZ6VBXHT6gC7A8UYWGiM14fGgp+s/L1oFfDWSPV/+SFkYCmZ0SiESkRKA==", "dev": true, + "optional": true, "peer": true } } @@ -26148,7 +26163,8 @@ "bignumber.js": { "version": "9.1.2", "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.1.2.tgz", - "integrity": "sha512-2/mKyZH9K85bzOEfhXDBFZTGd1CTs+5IHpeFQo9luiBG7hghdC851Pj2WAhb6E3R6b9tZj/XKhbg4fum+Kepug==" + "integrity": "sha512-2/mKyZH9K85bzOEfhXDBFZTGd1CTs+5IHpeFQo9luiBG7hghdC851Pj2WAhb6E3R6b9tZj/XKhbg4fum+Kepug==", + "dev": true }, "binary-extensions": { "version": "2.2.0", @@ -27413,6 +27429,7 @@ "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.4.1.tgz", "integrity": "sha512-r4eRSeStEGf6M5SKdrQhhLK5bOwOBxQhIE3YSTnZE3GpKiLfnnhE+tPtrJE79+eDJgm39BM6LSoI8SCx4HbwlQ==", "dev": true, + "optional": true, "peer": true }, "emoji-regex": { @@ -32434,6 +32451,7 @@ "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.3.0.tgz", "integrity": "sha512-HR7EVodfFUdQCTIeySw+WDRFJlPcLOJbXfwwZ7Oom6tjsvZ3bOkCDJHehQC3nxJrv7+f9XecwazynjU8e4Vw3Q==", "dev": true, + "optional": true, "peer": true }, "immutable": { @@ -33013,6 +33031,7 @@ "resolved": "https://registry.npmjs.org/level-concat-iterator/-/level-concat-iterator-3.1.0.tgz", "integrity": "sha512-BWRCMHBxbIqPxJ8vHOvKUsaO0v1sLYZtjN3K2iZJsRBYtp+ONsY6Jfi6hy9K3+zolgQRryhIn2NRZjZnWJ9NmQ==", "dev": true, + "optional": true, "peer": true, "requires": { "catering": "^2.1.0" @@ -33145,6 +33164,7 @@ "resolved": "https://registry.npmjs.org/leveldown/-/leveldown-5.6.0.tgz", "integrity": "sha512-iB8O/7Db9lPaITU1aA2txU/cBEXAt4vWwKQRrrWuS6XDgbP4QZGj9BL2aNbwb002atoQ/lIotJkfyzz+ygQnUQ==", "dev": true, + "optional": true, "peer": true, "requires": { "abstract-leveldown": "~6.2.1", @@ -33157,6 +33177,7 @@ "resolved": "https://registry.npmjs.org/abstract-leveldown/-/abstract-leveldown-6.2.3.tgz", "integrity": "sha512-BsLm5vFMRUrrLeCcRc+G0t2qOaTzpoJQLOubq2XM72eNpjF5UdU5o/5NvlNhx95XHcAvcl8OMXr4mlg/fRgUXQ==", "dev": true, + "optional": true, "peer": true, "requires": { "buffer": "^5.5.0", @@ -33171,6 +33192,7 @@ "resolved": "https://registry.npmjs.org/level-concat-iterator/-/level-concat-iterator-2.0.1.tgz", "integrity": "sha512-OTKKOqeav2QWcERMJR7IS9CUo1sHnke2C0gkSmcR7QuEtFNLLzHQAvnMw8ykvEcv0Qtkg0p7FOwP1v9e5Smdcw==", "dev": true, + "optional": true, "peer": true }, "level-supports": { @@ -33178,6 +33200,7 @@ "resolved": "https://registry.npmjs.org/level-supports/-/level-supports-1.0.1.tgz", "integrity": "sha512-rXM7GYnW8gsl1vedTJIbzOrRv85c/2uCMpiiCzO2fndd06U/kUXEEU9evYn4zFggBOg36IsBW8LzqIpETwwQzg==", "dev": true, + "optional": true, "peer": true, "requires": { "xtend": "^4.0.2" @@ -33188,6 +33211,7 @@ "resolved": "https://registry.npmjs.org/napi-macros/-/napi-macros-2.0.0.tgz", "integrity": "sha512-A0xLykHtARfueITVDernsAWdtIMbOJgKgcluwENp3AlsKN/PloyO10HtmoqnFAQAcxPkgZN7wdfPfEd0zNGxbg==", "dev": true, + "optional": true, "peer": true }, "node-gyp-build": { @@ -33195,6 +33219,7 @@ "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.1.1.tgz", "integrity": "sha512-dSq1xmcPDKPZ2EED2S6zw/b9NKsqzXRE6dVr8TVQnI3FJOTteUMuqF3Qqs6LZg+mLGYJWqQzMbIjMtJqTv87nQ==", "dev": true, + "optional": true, "peer": true } } diff --git a/package.json b/package.json index 889dfe6..6741b96 100644 --- a/package.json +++ b/package.json @@ -44,7 +44,6 @@ "@nomicfoundation/hardhat-verify": "1.1.1", "@nomiclabs/hardhat-truffle5": "2.0.7", "axios": "1.5.0", - "bignumber.js": "9.1.2", "ora": "5.4.1" }, "peerDependencies": { @@ -69,7 +68,7 @@ "eslint-plugin-import": "^2.28.1", "eslint-plugin-prettier": "^5.0.0", "eslint-plugin-promise": "^6.1.1", - "ethers": "^6.7.1", + "ethers": "^6.8.0", "hardhat": "^2.17.0", "mocha": "^10.0.0", "pinst": "^3.0.0", diff --git a/src/deployer/Deployer.ts b/src/deployer/Deployer.ts index 472859c..e5e194a 100644 --- a/src/deployer/Deployer.ts +++ b/src/deployer/Deployer.ts @@ -2,18 +2,18 @@ import { Signer } from "ethers"; import { HardhatRuntimeEnvironment } from "hardhat/types"; -import { catchError, getSignerHelper, getChainId } from "../utils"; +import { catchError, getChainId, getSignerHelper } from "../utils"; import { MigrateError } from "../errors"; import { Adapter } from "./adapters/Adapter"; -import { PureAdapter } from "./adapters/PureAdapter"; import { EthersAdapter } from "./adapters/EthersAdapter"; -import { TruffleAdapter } from "./adapters/TruffleAdapter"; +import { PureAdapter } from "./adapters/PureAdapter"; import { PureEthersAdapter } from "./adapters/PureEthersAdapter"; +import { TruffleAdapter } from "./adapters/TruffleAdapter"; -import { OverridesAndLibs } from "../types/deployer"; import { Instance, TypedArgs } from "../types/adapter"; +import { OverridesAndLibs } from "../types/deployer"; import { isContractFactory, isEthersFactory, isPureFactory, isTruffleFactory } from "../types/type-checks"; import { TransactionProcessor } from "../tools/storage/TransactionProcessor"; @@ -36,7 +36,20 @@ export class Deployer { return adapter.toInstance(contract, contractAddress, parameters); } - public async deployed(contract: Instance): Promise { + public setAsDeployed( + contract: Instance | (T extends Truffle.Contract ? T : never), + address: string, + ): void { + const adapter = this._resolveAdapter(contract); + + const contractName = adapter.getContractName(contract); + + TransactionProcessor.saveDeploymentTransactionWithContractName(contractName, address); + } + + public async deployed( + contract: Instance | (T extends Truffle.Contract ? T : never), + ): Promise { const adapter = this._resolveAdapter(contract); const contractName = adapter.getContractName(contract); diff --git a/src/deployer/Linker.ts b/src/deployer/Linker.ts index 664a830..7209ffe 100644 --- a/src/deployer/Linker.ts +++ b/src/deployer/Linker.ts @@ -166,6 +166,8 @@ export class Linker { } catch { const artifact = this._mustGetLibraryArtifact(libraryName); + // https://github.com/ethers-io/ethers.js/issues/2431 + // https://github.com/ethers-io/ethers.js/issues/1126 const core = new MinimalContract(hre, artifact.bytecode, Interface.from(artifact.abi), libraryName); Reporter.notifyDeploymentOfMissingLibrary(libraryName); diff --git a/src/deployer/adapters/EthersInjectHelper.ts b/src/deployer/adapters/AbstractEthersAdapter.ts similarity index 69% rename from src/deployer/adapters/EthersInjectHelper.ts rename to src/deployer/adapters/AbstractEthersAdapter.ts index fffc516..240c810 100644 --- a/src/deployer/adapters/EthersInjectHelper.ts +++ b/src/deployer/adapters/AbstractEthersAdapter.ts @@ -1,6 +1,7 @@ import { BaseContract, BaseContractMethod, + ContractFactory, ContractTransaction, ContractTransactionResponse, defineProperties, @@ -10,19 +11,53 @@ import { import { HardhatRuntimeEnvironment } from "hardhat/types"; -import { fillParameters, getMethodString } from "../../utils"; +import { Adapter } from "./Adapter"; -import { MigrateConfig } from "../../types/migrations"; +import { bytecodeToString, fillParameters, getMethodString, getSignerHelper } from "../../utils"; + +import { EthersFactory, PureFactory } from "../../types/adapter"; import { OverridesAndLibs } from "../../types/deployer"; import { Reporter } from "../../tools/reporters/Reporter"; import { TransactionProcessor } from "../../tools/storage/TransactionProcessor"; +import { MinimalContract } from "../MinimalContract"; + +type Factory = EthersFactory | PureFactory | ContractFactory; -export class EthersInjectHelper { - protected _config: MigrateConfig; +export abstract class AbstractEthersAdapter extends Adapter { + private static _processedClasses = new Set(); - constructor(private _hre: HardhatRuntimeEnvironment) { - this._config = _hre.config.migrate; + constructor(_hre: HardhatRuntimeEnvironment) { + super(_hre); + } + + public getRawBytecode(instance: Factory): string { + return bytecodeToString(instance.bytecode); + } + + public async fromInstance(instance: Factory): Promise { + return new MinimalContract( + this._hre, + this.getRawBytecode(instance), + this.getInterface(instance), + this.getContractName(instance), + ); + } + + public async toInstance(instance: Factory, address: string, parameters: OverridesAndLibs): Promise { + const signer = await getSignerHelper(this._hre, parameters.from); + + const contract = new BaseContract(address, this.getInterface(instance), signer); + + const contractName = this.getContractName(instance); + + if (!AbstractEthersAdapter._processedClasses.has(contractName)) { + AbstractEthersAdapter._processedClasses.add(contractName); + + this.overrideConnectMethod(instance, contractName); + } + + return this.insertHandlers(contract, contractName, parameters) as unknown as I; } public insertHandlers(contract: BaseContract, contractName: string, parameters: OverridesAndLibs): BaseContract { @@ -65,6 +100,8 @@ export class EthersInjectHelper { return contract; } + public abstract overrideConnectMethod(instance: Factory, contractName: string): Promise; + private _getContractFunctionFragments(contractInterface: Interface): FunctionFragment[] { const result: FunctionFragment[] = []; @@ -76,8 +113,8 @@ export class EthersInjectHelper { } private _wrapOldMethod( - methodName: string, contractName: string, + methodName: string, methodFragments: FunctionFragment, oldMethod: BaseContractMethod, parameters: OverridesAndLibs, diff --git a/src/deployer/adapters/EthersAdapter.ts b/src/deployer/adapters/EthersAdapter.ts index 6dde7c7..58a69cb 100644 --- a/src/deployer/adapters/EthersAdapter.ts +++ b/src/deployer/adapters/EthersAdapter.ts @@ -1,57 +1,18 @@ -import { Interface, BaseContract } from "ethers"; +import { BaseContract, ContractRunner, Interface } from "ethers"; -import { HardhatRuntimeEnvironment } from "hardhat/types"; - -import { Adapter } from "./Adapter"; -import { EthersInjectHelper } from "./EthersInjectHelper"; - -import { MinimalContract } from "../MinimalContract"; - -import { bytecodeToString, catchError, getSignerHelper } from "../../utils"; +import { catchError, getSignerHelper } from "../../utils"; import { EthersFactory } from "../../types/adapter"; -import { OverridesAndLibs } from "../../types/deployer"; import { ArtifactProcessor } from "../../tools/storage/ArtifactProcessor"; +import { AbstractEthersAdapter } from "./AbstractEthersAdapter"; @catchError -export class EthersAdapter extends Adapter { - private _injectHelper: EthersInjectHelper; - - constructor(_hre: HardhatRuntimeEnvironment) { - super(_hre); - this._injectHelper = new EthersInjectHelper(_hre); - } - - public async fromInstance(instance: EthersFactory): Promise { - return new MinimalContract( - this._hre, - this.getRawBytecode(instance), - this.getInterface(instance), - this.getContractName(instance), - ); - } - - public async toInstance( - instance: EthersFactory, - address: string, - parameters: OverridesAndLibs, - ): Promise { - const signer = await getSignerHelper(this._hre, parameters.from); - - const contract = new BaseContract(address, this.getInterface(instance), signer); - - return this._injectHelper.insertHandlers(contract, this.getContractName(instance), parameters) as unknown as I; - } - +export class EthersAdapter extends AbstractEthersAdapter { public getInterface(instance: EthersFactory): Interface { return Interface.from(instance.abi); } - public getRawBytecode(instance: EthersFactory): string { - return bytecodeToString(instance.bytecode); - } - public getContractName(instance: EthersFactory): string { try { return ArtifactProcessor.tryGetContractName(this.getRawBytecode(instance)); @@ -59,4 +20,16 @@ export class EthersAdapter extends Adapter { return "Unknown Contract"; } } + + public async overrideConnectMethod(instance: EthersFactory, contractName: string) { + const connectMethod = instance.connect; + + const defaultRunner = await getSignerHelper(this._hre); + + instance.connect = (address: string, runner?: ContractRunner): I => { + const contract = connectMethod(address, runner ?? defaultRunner) as BaseContract; + + return this.insertHandlers(contract, contractName, {}) as unknown as I; + }; + } } diff --git a/src/deployer/adapters/PureAdapter.ts b/src/deployer/adapters/PureAdapter.ts index ebba893..1f40ff3 100644 --- a/src/deployer/adapters/PureAdapter.ts +++ b/src/deployer/adapters/PureAdapter.ts @@ -1,52 +1,22 @@ -import { BaseContract, Interface } from "ethers"; +import { Interface } from "ethers"; -import { HardhatRuntimeEnvironment } from "hardhat/types"; - -import { Adapter } from "./Adapter"; -import { EthersInjectHelper } from "./EthersInjectHelper"; - -import { MinimalContract } from "../MinimalContract"; - -import { bytecodeToString, catchError, getSignerHelper } from "../../utils"; +import { catchError } from "../../utils"; import { PureFactory } from "../../types/adapter"; -import { OverridesAndLibs } from "../../types/deployer"; +import { AbstractEthersAdapter } from "./AbstractEthersAdapter"; @catchError -export class PureAdapter extends Adapter { - private _injectHelper: EthersInjectHelper; - - constructor(protected _hre: HardhatRuntimeEnvironment) { - super(_hre); - this._injectHelper = new EthersInjectHelper(_hre); - } - - public async fromInstance(instance: PureFactory): Promise { - return new MinimalContract( - this._hre, - this.getRawBytecode(instance), - this.getInterface(instance), - this.getContractName(instance), - ); - } - - public async toInstance(instance: PureFactory, address: string, parameters: OverridesAndLibs): Promise { - const signer = await getSignerHelper(this._hre, parameters.from); - - const contract = new BaseContract(address, this.getInterface(instance), signer); - - return this._injectHelper.insertHandlers(contract, this.getContractName(instance), parameters) as unknown as I; - } - +export class PureAdapter extends AbstractEthersAdapter { public getInterface(instance: PureFactory): Interface { return Interface.from(instance.abi); } - public getRawBytecode(instance: PureFactory): string { - return bytecodeToString(instance.bytecode); - } - public getContractName(instance: PureFactory): string { return instance.contractName; } + + // eslint-disable-next-line @typescript-eslint/no-unused-vars + public async overrideConnectMethod(_instance: PureFactory, _contractName: string) { + return; + } } diff --git a/src/deployer/adapters/PureEthersAdapter.ts b/src/deployer/adapters/PureEthersAdapter.ts index 764b37a..d437b5a 100644 --- a/src/deployer/adapters/PureEthersAdapter.ts +++ b/src/deployer/adapters/PureEthersAdapter.ts @@ -1,52 +1,16 @@ -import { BaseContract, ContractFactory, Interface } from "ethers"; +import { Addressable, ContractFactory, Interface } from "ethers"; -import { HardhatRuntimeEnvironment } from "hardhat/types"; - -import { Adapter } from "./Adapter"; -import { EthersInjectHelper } from "./EthersInjectHelper"; - -import { MinimalContract } from "../MinimalContract"; - -import { catchError, getSignerHelper } from "../../utils"; - -import { OverridesAndLibs } from "../../types/deployer"; +import { catchError } from "../../utils"; import { ArtifactProcessor } from "../../tools/storage/ArtifactProcessor"; +import { AbstractEthersAdapter } from "./AbstractEthersAdapter"; @catchError -export class PureEthersAdapter extends Adapter { - private _injectHelper: EthersInjectHelper; - - constructor(protected _hre: HardhatRuntimeEnvironment) { - super(_hre); - this._injectHelper = new EthersInjectHelper(_hre); - } - - public async fromInstance(instance: ContractFactory): Promise { - return new MinimalContract( - this._hre, - this.getRawBytecode(instance), - this.getInterface(instance), - this.getContractName(instance), - ); - } - - public async toInstance(instance: ContractFactory, address: string, parameters: OverridesAndLibs): Promise { - const signer = await getSignerHelper(this._hre, parameters.from); - - const contract = new BaseContract(address, this.getInterface(instance), signer); - - return this._injectHelper.insertHandlers(contract, this.getContractName(instance), parameters) as unknown as I; - } - +export class PureEthersAdapter extends AbstractEthersAdapter { public getInterface(instance: ContractFactory): Interface { return instance.interface; } - public getRawBytecode(instance: ContractFactory): string { - return instance.bytecode; - } - public getContractName(instance: ContractFactory): string { try { return ArtifactProcessor.tryGetContractName(this.getRawBytecode(instance)); @@ -54,4 +18,14 @@ export class PureEthersAdapter extends Adapter { return "Unknown Contract"; } } + + public async overrideConnectMethod(instance: ContractFactory, contractName: string) { + const attachMethod = instance.attach; + + instance.attach = (target: string | Addressable): any => { + const contract = attachMethod(target); + + return this.insertHandlers(contract, contractName, {}); + }; + } } diff --git a/src/deployer/adapters/TruffleAdapter.ts b/src/deployer/adapters/TruffleAdapter.ts index fc1fe98..a9bd62c 100644 --- a/src/deployer/adapters/TruffleAdapter.ts +++ b/src/deployer/adapters/TruffleAdapter.ts @@ -8,7 +8,7 @@ import { Adapter } from "./Adapter"; import { MinimalContract } from "../MinimalContract"; -import { bytecodeToString, catchError, fillParameters, getMethodString } from "../../utils"; +import { bytecodeToString, catchError, fillParameters, getMethodString, toJSON } from "../../utils"; import { KeyTransactionFields } from "../../types/tools"; import { EthersFactory, Instance, TruffleFactory } from "../../types/adapter"; @@ -35,12 +35,11 @@ export class TruffleAdapter extends Adapter { ); } - public async toInstance(instance: TruffleFactory, address: string, parameters: OverridesAndLibs): Promise { + // eslint-disable-next-line @typescript-eslint/no-unused-vars + public async toInstance(instance: TruffleFactory, address: string, _parameters: OverridesAndLibs): Promise { const contract = this._hre.artifacts.require(instance.contractName!); - const contractInstance = await contract.at(address); - - return this._insertHandlers(instance, contractInstance, address, parameters); + return contract.at(address); } public getInterface(instance: TruffleContract): Interface { @@ -55,10 +54,21 @@ export class TruffleAdapter extends Adapter { try { return ArtifactProcessor.tryGetContractName(this.getRawBytecode(instance)); } catch { - return "Unknown Contract"; + // It is possible was called abstract contract + return (instance as any).contractName || "Unknown Contract"; } } + public async overrideConnectMethod(instance: TruffleFactory) { + const atMethod = instance.at; + + instance.at = async (address: string): Promise => { + const contract = await atMethod(address); + + return this._insertHandlers(instance, contract, address, {}); + }; + } + protected _insertHandlers(instance: TruffleFactory, contract: I, to: string, parameters: OverridesAndLibs): I { const contractInterface = this.getInterface(instance); const contractName = this.getContractName(instance); @@ -66,7 +76,13 @@ export class TruffleAdapter extends Adapter { for (const methodName of Object.keys((contract as any).contract.methods)) { const oldMethod: BaseTruffleMethod = (contract as any)[methodName]; - const functionStateMutability = contractInterface.getFunction(methodName)?.stateMutability; + let functionStateMutability: string | undefined; + try { + functionStateMutability = contractInterface.getFunction(methodName)?.stateMutability; + } catch { + // Ambiguous function description in ABI + continue; + } if (functionStateMutability === "view" || functionStateMutability === "pure") { continue; } @@ -154,7 +170,7 @@ export class TruffleAdapter extends Adapter { const tx: KeyTransactionFields = { to: to, from: parameters.from! as string, - data: JSON.stringify(args), + data: toJSON(args), chainId: toBigInt(String(parameters.chainId)), value: toBigInt(String(parameters.value)), }; diff --git a/src/index.ts b/src/index.ts index 75de117..d4df606 100644 --- a/src/index.ts +++ b/src/index.ts @@ -3,8 +3,8 @@ import "@nomicfoundation/hardhat-verify"; import { TASK_COMPILE } from "hardhat/builtin-tasks/task-names"; import { extendConfig, extendEnvironment, task, types } from "hardhat/config"; -import { lazyObject } from "hardhat/plugins"; -import { ActionType } from "hardhat/types"; +import { lazyFunction, lazyObject } from "hardhat/plugins"; +import { ActionType, HardhatRuntimeEnvironment } from "hardhat/types"; import "./type-extensions"; @@ -17,9 +17,11 @@ import { Reporter } from "./tools/reporters/Reporter"; import { ArtifactProcessor } from "./tools/storage/ArtifactProcessor"; import { DefaultStorage } from "./tools/storage/MigrateStorage"; +import { TruffleAdapter } from "./deployer/adapters/TruffleAdapter"; import { MigrateConfig } from "./types/migrations"; export { Deployer } from "./deployer/Deployer"; +export { DefaultStorage } from "./tools/storage/MigrateStorage"; export { Verifier } from "./verifier/Verifier"; extendConfig(migrateConfigExtender); @@ -37,6 +39,8 @@ const migrate: ActionType = async (taskArgs, env) => { Reporter.init(env); + overrideTruffleRequire(env); + await new Migrator(env).migrate(); }; @@ -77,3 +81,17 @@ task(TASK_MIGRATE, "Deploy contracts via migration files") ) .addFlag("continue", "The flag indicating whether the previous deployment should be continued.") .setAction(migrate); + +const overrideTruffleRequire = (env: HardhatRuntimeEnvironment) => { + const old = env.artifacts.require; + + env.artifacts.require = lazyFunction(() => { + return (contractPath: string): any => { + const res = old(contractPath); + + new TruffleAdapter(env).overrideConnectMethod(res); + + return res; + }; + }); +}; diff --git a/src/tools/reporters/Reporter.ts b/src/tools/reporters/Reporter.ts index d1824d4..2de3982 100644 --- a/src/tools/reporters/Reporter.ts +++ b/src/tools/reporters/Reporter.ts @@ -1,9 +1,8 @@ /* eslint-disable no-console */ import ora from "ora"; import axios from "axios"; -import BigNumber from "bignumber.js"; -import { Network, TransactionReceipt, TransactionResponse } from "ethers"; +import { Network, TransactionReceipt, TransactionResponse, formatEther, formatUnits } from "ethers"; import { HardhatRuntimeEnvironment } from "hardhat/types"; @@ -192,15 +191,11 @@ export class Reporter { return this._toGWei(value) + " GWei"; } - return this._toEther(value) + ` ${nativeSymbol}`; - } - - private static _toEther(value: bigint): string { - return new BigNumber(value.toString()).div(10 ** 18).toFixed(); + return formatEther(value) + ` ${nativeSymbol}`; } private static _toGWei(value: bigint): string { - return new BigNumber(value.toString()).div(10 ** 9).toFixed(); + return formatUnits(value, "gwei"); } private static _reportMigrationFiles(files: string[]) { diff --git a/src/tools/storage/TransactionProcessor.ts b/src/tools/storage/TransactionProcessor.ts index 6dab2e1..f7fce6a 100644 --- a/src/tools/storage/TransactionProcessor.ts +++ b/src/tools/storage/TransactionProcessor.ts @@ -25,6 +25,10 @@ export class TransactionProcessor { this._saveContractByName(contractName, address); } + public static saveDeploymentTransactionWithContractName(contractName: string, address: string) { + this._saveContractByName(contractName, address); + } + /** * @param tx - Transaction to save. Acts as a key and value at the same time. */ diff --git a/src/utils.ts b/src/utils.ts index f076aff..3c52f1f 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -22,7 +22,7 @@ export async function getSignerHelper( const address = await hre.ethers.resolveAddress(from, hre.ethers.provider); - return hre.ethers.getSigner(address as string); + return hre.ethers.getSigner(address); } export async function fillParameters(hre: HardhatRuntimeEnvironment, parameters: Overrides): Promise { @@ -126,21 +126,21 @@ export function getMethodString( args: any[] = [], ): string { if (methodFragment.inputs === undefined) { - return `${contractName}.${methodName}`; - } - - let argsString = ""; - for (let i = 0; i < args.length; i++) { - argsString += `${methodFragment.inputs[i].name}:${args[i]}${i === args.length - 1 ? "" : ", "}`; + return `${contractName}.${methodName}()`; } + const argsString = args.map((arg, i) => `${methodFragment.inputs[i].name}:${arg}`).join(", "); const methodSting = `${contractName}.${methodName}(${argsString})`; if (methodSting.length > 60) { - return `${contractName}.${methodName}(${args.length} arguments)`; + const shortenMethodString = `${contractName}.${methodName}(${args.length} arguments)`; + + if (shortenMethodString.length > 60) { + return `${contractName.split(":").pop()}.${methodName}(${args.length} arguments)`; + } } - return `${contractName}.${methodName}(${argsString})`; + return methodSting; } export async function waitForBlock(hre: HardhatRuntimeEnvironment, desiredBlock: number) {