diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index cddb3a3..080d64a 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -15,8 +15,8 @@ jobs: strategy: matrix: node: - - 16 - 18 + - 20 steps: - uses: actions/setup-node@v3 with: diff --git a/CHANGELOG.md b/CHANGELOG.md index d0d2c6b..303d4c5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,13 @@ # Changelog +## Version 2.1.5 + +* Fixed behaviour of connect method in Ethers Adapter. + +## Version 2.1.4 + +* Deleted `pinst` package. + ## Version 2.1.3 * Added the `verificationDelay` parameter, which defines the time in milliseconds that must pass before the verification process starts. diff --git a/README.md b/README.md index 6d652e1..bacc2ab 100644 --- a/README.md +++ b/README.md @@ -296,4 +296,4 @@ If verification fails, the `attempts` parameter indicates how many additional re - This plugin, as well as the [Hardhat Toolbox](https://hardhat.org/hardhat-runner/plugins/nomicfoundation-hardhat-toolbox) plugin, use the [@nomicfoundation/hardhat-verify](https://www.npmjs.com/package/@nomicfoundation/hardhat-verify) plugin internally, so both of these plugins cannot be imported at the same time. A quick fix is to manually import the needed plugins that ToolBox imports. - Adding, removing, moving or renaming new contracts to the hardhat project or reorganizing the directory structure of contracts after deployment may alter the resulting bytecode in some solc versions. See this [Solidity issue](https://github.com/ethereum/solidity/issues/9573) for further information. -- This plugin does not function properly with native Truffle methods, such as in `contract.deployed()`, unless otherwise specified above at the instance level. For example, instead of using `contract.deployed()`, it is necessary to use the `deployer.deploy()` method. +- This plugin does not function properly with native Truffle or Ethers factories methods, such as `contract.deployed()`, `factory.at()`, or in case of ethers `factory.attach()`. So, instead of using mentioned methods, it is necessary to use the `deployer.deployed()`. diff --git a/package-lock.json b/package-lock.json index f8c4cfd..2cbca33 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@solarity/hardhat-migrate", - "version": "2.1.4", + "version": "2.1.5", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@solarity/hardhat-migrate", - "version": "2.1.4", + "version": "2.1.5", "license": "MIT", "workspaces": [ "test/fixture-projects/*" @@ -5913,6 +5913,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", @@ -5945,6 +5946,7 @@ "url": "https://feross.org/support" } ], + "optional": true, "peer": true, "dependencies": { "base64-js": "^1.3.1", @@ -7301,6 +7303,7 @@ "resolved": "https://registry.npmjs.org/catering/-/catering-2.1.1.tgz", "integrity": "sha512-K7Qy8O9p76sL3/3m7/zLKbRkyOlSZAgzEaLhyj2mXS8PsCud2Eo4hAb8aLtZqHh0QGqLcb9dlJSu6lHRVENm1w==", "dev": true, + "optional": true, "peer": true, "engines": { "node": ">=6" @@ -8525,6 +8528,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" @@ -14994,6 +14998,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": { @@ -15180,6 +15185,7 @@ "url": "https://feross.org/support" } ], + "optional": true, "peer": true, "engines": { "node": ">=4" @@ -15931,6 +15937,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" @@ -16046,6 +16053,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" @@ -16068,6 +16076,7 @@ "integrity": "sha512-iB8O/7Db9lPaITU1aA2txU/cBEXAt4vWwKQRrrWuS6XDgbP4QZGj9BL2aNbwb002atoQ/lIotJkfyzz+ygQnUQ==", "dev": true, "hasInstallScript": true, + "optional": true, "peer": true, "dependencies": { "abstract-leveldown": "~6.2.1", @@ -16083,6 +16092,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", @@ -16100,6 +16110,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" @@ -16110,6 +16121,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" @@ -16123,6 +16135,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", @@ -16920,6 +16933,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/natural-compare": { diff --git a/package.json b/package.json index 9c141ee..391d20a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@solarity/hardhat-migrate", - "version": "2.1.4", + "version": "2.1.5", "description": "Automatic deployment and verification of smart contracts", "main": "dist/src/index.js", "types": "dist/src/index.d.ts", diff --git a/src/deployer/adapters/AbstractEthersAdapter.ts b/src/deployer/adapters/AbstractEthersAdapter.ts index caf3cde..fa6e4b0 100644 --- a/src/deployer/adapters/AbstractEthersAdapter.ts +++ b/src/deployer/adapters/AbstractEthersAdapter.ts @@ -2,6 +2,7 @@ import { BaseContract, BaseContractMethod, ContractFactory, + ContractRunner, ContractTransaction, ContractTransactionReceipt, ContractTransactionResponse, @@ -31,8 +32,6 @@ import { TransactionProcessor } from "../../tools/storage/TransactionProcessor"; type Factory = EthersContract | BytecodeFactory | ContractFactory; export abstract class AbstractEthersAdapter extends Adapter { - private static _processedClasses = new Set(); - public getRawBytecode(instance: Factory): string { return bytecodeToString(instance.bytecode); } @@ -48,18 +47,13 @@ export abstract class AbstractEthersAdapter extends Adapter { public async toInstance(instance: Factory, address: string, parameters: OverridesAndLibs): Promise { const signer = await getSignerHelper(parameters.from); - - const contract = new BaseContract(address, this.getInterface(instance), signer); - const contractName = this.getContractName(instance, parameters); - if (!AbstractEthersAdapter._processedClasses.has(contractName)) { - AbstractEthersAdapter._processedClasses.add(contractName); + let contract = new BaseContract(address, this.getInterface(instance), signer); - await this._overrideConnectMethod(instance, contractName); - } + contract = this._insertAddressGetter(contract, address); + contract = await this._overrideConnectMethod(contract, this.getInterface(instance), contractName); - this._insertAddressGetter(contract, address); return this._insertHandlers(contract, contractName) as unknown as I; } @@ -103,10 +97,26 @@ export abstract class AbstractEthersAdapter extends Adapter { return contract; } - protected abstract _overrideConnectMethod(instance: Factory, contractName: string): Promise; + protected async _overrideConnectMethod( + contract: BaseContract, + contractInterface: Interface, + contractName: string, + ): Promise { + const defaultRunner = await getSignerHelper(); + + contract.connect = (runner: ContractRunner | null): BaseContract => { + const newContract = new BaseContract(contract.target, contractInterface, runner ?? defaultRunner); - private _insertAddressGetter(contract: BaseContract, contractAddress: string): void { + return this._insertHandlers(newContract, contractName) as any; + }; + + return contract; + } + + private _insertAddressGetter(contract: BaseContract, contractAddress: string): BaseContract { (contract as any).address = contractAddress; + + return contract; } private _getContractFunctionFragments(contractInterface: Interface): FunctionFragment[] { diff --git a/src/deployer/adapters/BytecodeAdapter.ts b/src/deployer/adapters/BytecodeAdapter.ts index 69dfaa6..2179115 100644 --- a/src/deployer/adapters/BytecodeAdapter.ts +++ b/src/deployer/adapters/BytecodeAdapter.ts @@ -19,9 +19,4 @@ export class BytecodeAdapter extends AbstractEthersAdapter { public getContractName(instance: BytecodeFactory): string { return instance.contractName; } - - // eslint-disable-next-line @typescript-eslint/no-unused-vars - protected async _overrideConnectMethod(_instance: BytecodeFactory, _contractName: string) { - return; - } } diff --git a/src/deployer/adapters/EthersContractAdapter.ts b/src/deployer/adapters/EthersContractAdapter.ts index 1dc89b3..587437d 100644 --- a/src/deployer/adapters/EthersContractAdapter.ts +++ b/src/deployer/adapters/EthersContractAdapter.ts @@ -1,8 +1,8 @@ -import { BaseContract, ContractRunner, Interface } from "ethers"; +import { Interface } from "ethers"; import { AbstractEthersAdapter } from "./AbstractEthersAdapter"; -import { catchError, getInstanceNameFromClass, getSignerHelper } from "../../utils"; +import { catchError, getInstanceNameFromClass } from "../../utils"; import { EthersContract } from "../../types/adapter"; import { OverridesAndName } from "../../types/deployer"; @@ -34,16 +34,4 @@ export class EthersContractAdapter extends AbstractEthersAdapter { return getInstanceNameFromClass(instance); } } - - protected async _overrideConnectMethod(instance: EthersContract, contractName: string) { - const connectMethod = instance.connect; - - const defaultRunner = await getSignerHelper(); - - 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/EthersFactoryAdapter.ts b/src/deployer/adapters/EthersFactoryAdapter.ts index 52bb34c..7251fd9 100644 --- a/src/deployer/adapters/EthersFactoryAdapter.ts +++ b/src/deployer/adapters/EthersFactoryAdapter.ts @@ -1,4 +1,4 @@ -import { Addressable, ContractFactory, Interface } from "ethers"; +import { ContractFactory, Interface } from "ethers"; import { AbstractEthersAdapter } from "./AbstractEthersAdapter"; @@ -33,14 +33,4 @@ export class EthersFactoryAdapter extends AbstractEthersAdapter { return getInstanceNameFromClass(instance); } } - - protected 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 a3520ea..d52e7df 100644 --- a/src/deployer/adapters/TruffleAdapter.ts +++ b/src/deployer/adapters/TruffleAdapter.ts @@ -53,11 +53,11 @@ export class TruffleAdapter extends Adapter { public async toInstance(instance: TruffleFactory, address: string, _: OverridesAndName): Promise { const contract = this._hre.artifacts.require(instance.contractName!); - await this._overrideConnectMethod(contract); - const contractInstance = await contract.at(address); (instance as any).setAsDeployed(contractInstance); + this._insertHandlers(instance, contractInstance, address); + return contractInstance; } @@ -93,16 +93,6 @@ export class TruffleAdapter extends Adapter { } } - protected 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, address: string): I { const contractName = this.getContractName(instance, {}); const ethersBaseContract: BaseContract = new BaseContract(address, this.getInterface(instance)); diff --git a/test/integration/deployer/base-contract-interaction.ts b/test/integration/deployer/base-contract-interaction.ts index 3678786..d6b1421 100644 --- a/test/integration/deployer/base-contract-interaction.ts +++ b/test/integration/deployer/base-contract-interaction.ts @@ -1,3 +1,5 @@ +import { HardhatRuntimeEnvironment } from "hardhat/types"; + import { expect } from "chai"; import { useEnvironment } from "../../helpers"; @@ -17,14 +19,18 @@ import { TransactionStorage } from "../../../src/tools/storage/MigrateStorage"; describe("deployer", () => { let deployer: Deployer; - describe("default interaction with contracts", () => { + describe("default interaction with contracts (Ethers)", () => { useEnvironment("typechain-ethers"); + let hre: HardhatRuntimeEnvironment; + beforeEach("setup", async function () { await Migrator.buildMigrateTaskDeps(this.hre); deployer = new Deployer(this.hre); + hre = this.hre; + TransactionStorage.clear(); }); @@ -65,5 +71,21 @@ describe("deployer", () => { expect(await ethersProvider!.provider.getBalance(contract.getAddress())).to.equal(toPay); }); + + it("should connect to different signer and send transaction", async function () { + const [signer1, signer2] = await hre.ethers.getSigners(); + + const contract = await deployer.deploy(PayableReceive__factory); + + let tx = await contract.pay({ value: 100n }); + let receipt = await tx.wait(); + + expect(receipt!.from).to.equal(signer1.address); + + tx = await contract.connect(signer2).pay({ value: 110n }); + receipt = await tx.wait(); + + expect(receipt!.from).to.equal(signer2.address); + }); }); });