From b6fd783d57c1cb06dd98010a905249f9ee51ad7a Mon Sep 17 00:00:00 2001 From: Marko Arambasic Date: Wed, 18 Oct 2023 17:26:42 +0200 Subject: [PATCH] update: added tests for new sdk version --- .../hardhat-zksync-zksync2js/package.json | 4 +- .../hardhat-zksync-zksync2js/src/helpers.ts | 136 +++++---- .../hardhat-zksync-zksync2js/src/index.ts | 10 +- .../hardhat-zksync-zksync2js/src/types.ts | 31 +- .../simple/contracts/IGreeter.sol | 7 + .../fixture-projects/simple/hardhat.config.ts | 9 +- .../hardhat-zksync-zksync2js/test/helpers.ts | 1 - .../hardhat-zksync-zksync2js/test/tests.ts | 288 +++++++++++++----- 8 files changed, 323 insertions(+), 163 deletions(-) create mode 100644 packages/hardhat-zksync-zksync2js/test/fixture-projects/simple/contracts/IGreeter.sol diff --git a/packages/hardhat-zksync-zksync2js/package.json b/packages/hardhat-zksync-zksync2js/package.json index 2acf3d93d..e10179e40 100644 --- a/packages/hardhat-zksync-zksync2js/package.json +++ b/packages/hardhat-zksync-zksync2js/package.json @@ -57,13 +57,13 @@ "sinon": "^9.0.0", "ts-node": "^10.9.1", "typescript": "~5.0.0", - "zksync2-js": "^0.1.0-beta.0", + "zksync2-js": "0.2.0", "@typechain/ethers-v6": "^0.5.0", "rlp": "3.0.0", "ethers": "^6.7.1" }, "peerDependencies": { - "zksync2-js": "^0.1.0-beta.0", + "zksync2-js": "0.2.0", "ethers": "^6.7.1" }, "prettier": { diff --git a/packages/hardhat-zksync-zksync2js/src/helpers.ts b/packages/hardhat-zksync-zksync2js/src/helpers.ts index af468b28b..8c2fd71d7 100644 --- a/packages/hardhat-zksync-zksync2js/src/helpers.ts +++ b/packages/hardhat-zksync-zksync2js/src/helpers.ts @@ -1,5 +1,4 @@ import { Contract, ContractFactory, Provider, Signer, Wallet } from "zksync2-js" -import {ContractFactory as cf} from "zksync-web3" import * as ethers from "ethers"; @@ -37,24 +36,38 @@ function isArtifact(artifact: any): artifact is ZkSyncArtifact { ); } -export async function getSigners( +export function getWallets( + hre: HardhatRuntimeEnvironment, +): Wallet[] { + const accounts: string[] = rich_wallets.map((wallet) => wallet.privateKey); + + const wallets = accounts.map((account) => getWallet(hre, account)) + + return wallets; +} + +export function getWallet( + hre: HardhatRuntimeEnvironment, + privateKey?: string +): Wallet { + return new Wallet(privateKey ? privateKey : rich_wallets[0].privateKey, hre.zksync2js.provider); +} + +export function getSigners( hre: HardhatRuntimeEnvironment -): Promise { +): Signer[] { const accounts: string[] = rich_wallets.map((wallet) => wallet.address); - const signersWithAddress = await Promise.all( - accounts.map((account) => getSigner(hre, account)) - ); + const signersWithAddress = accounts.map((account) => getSigner(hre, account)) return signersWithAddress; } -export async function getSigner( +export function getSigner( hre: HardhatRuntimeEnvironment, address: string -): Promise { - - return new Signer(hre.zksync2js.provider, address); +): Signer { + return Signer.from(new Signer(hre.zksync2js.provider, address), hre.network.config.chainId); } export async function getImpersonatedSigner( @@ -69,7 +82,7 @@ export async function getImpersonatedSigner( export function getContractFactory( hre: HardhatRuntimeEnvironment, name: string, - signerOrOptions?: Signer | FactoryOptions, + walletOrOption?: Wallet | FactoryOptions, ): Promise; @@ -77,7 +90,7 @@ export function getContractFactory( hre: HardhatRuntimeEnvironment, abi: any[], bytecode: ethers.BytesLike, - signer?: Signer, + wallet?: Wallet, deploymentType?: DeploymentType ): Promise; @@ -85,9 +98,9 @@ export async function getContractFactory( hre: HardhatRuntimeEnvironment, nameOrAbi: string | any[], bytecodeOrFactoryOptions?: - | (Signer | FactoryOptions) + | (Wallet | FactoryOptions) | ethers.BytesLike, - signer?: Signer, + wallet?: Wallet, deploymentType?: DeploymentType ): Promise { if (typeof nameOrAbi === "string") { @@ -96,7 +109,7 @@ export async function getContractFactory( return getContractFactoryFromArtifact( hre, artifact, - bytecodeOrFactoryOptions as Signer | FactoryOptions | undefined, + bytecodeOrFactoryOptions as Wallet | FactoryOptions | undefined, deploymentType ); } @@ -105,15 +118,15 @@ export async function getContractFactory( hre, nameOrAbi, bytecodeOrFactoryOptions as ethers.BytesLike, - signer, + wallet, deploymentType ); } function isFactoryOptions( - signerOrOptions?: Signer | FactoryOptions -): signerOrOptions is FactoryOptions { - if (signerOrOptions === undefined || "provider" in signerOrOptions) { + walletOrOptions?: Wallet | FactoryOptions +): walletOrOptions is FactoryOptions { + if (walletOrOptions === undefined || "provider" in walletOrOptions) { return false; } @@ -123,10 +136,10 @@ function isFactoryOptions( export async function getContractFactoryFromArtifact( hre: HardhatRuntimeEnvironment, artifact: ZkSyncArtifact, - signerOrOptions?: Signer | FactoryOptions, + walletOrOptions?: Wallet | FactoryOptions, deploymentType?: DeploymentType ): Promise { - let signer: Signer | undefined; + let wallet: Wallet | undefined; if (!isArtifact(artifact)) { throw new ZkSync2JsPluginError( @@ -134,10 +147,10 @@ export async function getContractFactoryFromArtifact( ); } - if (isFactoryOptions(signerOrOptions)) { - signer = signerOrOptions.signer; + if (isFactoryOptions(walletOrOptions)) { + wallet = walletOrOptions.wallet; } else { - signer = signerOrOptions; + wallet = walletOrOptions; } if (artifact.bytecode === "0x") { @@ -151,7 +164,7 @@ If you want to call a contract using ${artifact.contractName} as its interface u hre, artifact.abi, artifact.bytecode, - signer, + wallet, deploymentType ); } @@ -160,49 +173,49 @@ async function getContractFactoryByAbiAndBytecode( hre: HardhatRuntimeEnvironment, abi: any[], bytecode: ethers.BytesLike, - signer?: Signer, + wallet?: Wallet, deploymentType?: DeploymentType ): Promise { - if (signer === undefined) { - const signers = await hre.zksync2js.getSigners(); - signer = signers[0]; + if (wallet === undefined) { + const wallets = getWallets(hre); + wallet = wallets[0]; } - return new ContractFactory(abi, bytecode, signer, deploymentType); + return new ContractFactory(abi, bytecode, wallet, deploymentType); } export async function getContractAt( hre: HardhatRuntimeEnvironment, nameOrAbi: string | any[], address: string | Address, - signer?: Signer + wallet?: Wallet ) { if (typeof nameOrAbi === "string") { const artifact = await loadArtifact(hre, nameOrAbi); - return getContractAtFromArtifact(hre, artifact, address, signer); + return getContractAtFromArtifact(hre, artifact, address, wallet); } - if (signer === undefined) { - const signers = await hre.zksync2js.getSigners(); - signer = signers[0]; + if (wallet === undefined) { + const wallets = getWallets(hre); + wallet = wallets[0]; } // If there's no signer, we want to put the provider for the selected network here. // This allows read only operations on the contract interface. - const signerOrProvider: Signer | Provider = - signer !== undefined ? signer : hre.zksync2js.provider; + const walletOrProvider: Wallet | Provider = + wallet !== undefined ? wallet : hre.zksync2js.provider; - return new Contract(address, nameOrAbi, signerOrProvider); + return new Contract(address, nameOrAbi, walletOrProvider); } export async function getContractAtFromArtifact( hre: HardhatRuntimeEnvironment, artifact: ZkSyncArtifact, address: string | Address, - signer?: Signer + wallet?: Wallet ) { if (!isArtifact(artifact)) { throw new ZkSync2JsPluginError( @@ -210,12 +223,11 @@ export async function getContractAtFromArtifact( ); } - if (signer === undefined) { - const signers = await hre.zksync2js.getSigners(); - signer = signers[0]; + if (wallet === undefined) { + wallet = hre.zksync2js.getWallet(); } - let contract = new Contract(address, artifact.abi, signer); + let contract = new Contract(address, artifact.abi, wallet); if (contract.runner === null) { contract = contract.connect(hre.zksync2js.provider) as Contract; @@ -227,21 +239,17 @@ export async function getContractAtFromArtifact( export async function deployContract( hre: HardhatRuntimeEnvironment, artifact: ZkSyncArtifact, - signer?: Signer | Wallet, + wallet?: Wallet, constructorArguments: any[] = [], overrides?: ethers.Overrides, - additionalFactoryDeps?: ethers.BytesLike[], - deploymentType?: DeploymentType + additionalFactoryDeps?: ethers.BytesLike[] ): Promise { - if(signer === undefined) { - const signers = await hre.zksync2js.getSigners(); - signer = Signer.from(signers[0], 1); + if(wallet === undefined) { + wallet = getWallet(hre); } - let w = new Wallet(rich_wallets[0].privateKey, hre.zksync2js.provider); - - const factory = new ContractFactory(artifact.abi, artifact.deployedBytecode, w, "create"); + const factory = new ContractFactory(artifact.abi, artifact.bytecode, wallet); const baseDeps = await extractFactoryDeps(hre, artifact); const additionalDeps = additionalFactoryDeps @@ -252,19 +260,19 @@ export async function deployContract( const { customData, ..._overrides } = overrides ?? {}; // Encode and send the deploy transaction providing factory dependencies. - const contract = await factory.deploy(...constructorArguments, { - from: w.address, - //gasLimit: 13919861n, - ..._overrides, - customData: { - ...customData, - factoryDeps, - }, - }); - - await contract.deployed(); + const contract = await factory.deploy(...constructorArguments, { + ..._overrides, + customData: { + ...customData, + salt: ethers.ZeroHash, + factoryDeps, + }, + } +); - return contract; + await contract.waitForDeployment(); + + return contract as Contract; } diff --git a/packages/hardhat-zksync-zksync2js/src/index.ts b/packages/hardhat-zksync-zksync2js/src/index.ts index acbea47f8..b48c46ff4 100644 --- a/packages/hardhat-zksync-zksync2js/src/index.ts +++ b/packages/hardhat-zksync-zksync2js/src/index.ts @@ -11,10 +11,12 @@ import { getContractFactory, getContractFactoryFromArtifact, getImpersonatedSigner, + getWallet, getSigner, getSigners, loadArtifact, - deployContract + deployContract, + getWallets } from "./helpers"; import { ZkSyncArtifact } from "./types"; import { ethers } from "ethers"; @@ -29,6 +31,8 @@ import { ethers } from "ethers"; return { ...zksync2js, provider, + getWallet: (privateKey?: string) => getWallet(hre, privateKey), + getWallets: () => getWallets(hre), getSigner: (address: string) => getSigner(hre, address), getSigners: () => getSigners(hre), getImpersonatedSigner: (address: string) => getImpersonatedSigner(hre, address), @@ -40,10 +44,10 @@ import { ethers } from "ethers"; loadArtifact: (name: string) => loadArtifact(hre, name), deployContract: (artifact: ZkSyncArtifact, constructorArguments: any[], - signer?: Signer | Wallet, + wallet?: Wallet, overrides?: ethers.Overrides, additionalFactoryDeps?: ethers.BytesLike[]) => - deployContract(hre, artifact, signer, constructorArguments = [], overrides, additionalFactoryDeps) + deployContract(hre, artifact, wallet, constructorArguments = [], overrides, additionalFactoryDeps) }; }); }); diff --git a/packages/hardhat-zksync-zksync2js/src/types.ts b/packages/hardhat-zksync-zksync2js/src/types.ts index c7e5a942b..d224cbce6 100644 --- a/packages/hardhat-zksync-zksync2js/src/types.ts +++ b/packages/hardhat-zksync-zksync2js/src/types.ts @@ -16,70 +16,61 @@ export interface ZkSyncArtifact extends Artifact { sourceMapping: string; } -export class ZkSyncContractFactory extends ContractFactory { - // The factory dependencies of the contract. - factoryDeps: FactoryDeps; - constructor(abi: ethers.Interface | ethers.InterfaceAbi, bytecode: ethers.BytesLike, runner?: ethers.ContractRunner, deploymentType?: DeploymentType, factoryDeps?: FactoryDeps) { - super(abi, bytecode, runner, deploymentType); - this.factoryDeps = factoryDeps ?? {}; - } -} - export interface FactoryOptions { - signer?: Signer; + wallet?: Wallet; } -export type DeployContractOptions = FactoryOptions & ethers.Overrides; - export declare function getContractFactory( name: string, - signerOrOptions?: Signer | FactoryOptions, + wallet?: Wallet, deploymentType?: DeploymentType ): Promise; export declare function getContractFactory( abi: any[], bytecode: ethers.BytesLike, - signer?: Signer, + wallet?: Wallet, deploymentType?: DeploymentType ): Promise; export declare function deployContract( contractFactoryOrArtifact: ContractFactory | ZkSyncArtifact, constructorArguments: any[], + wallet?: Wallet, overrides?: ethers.Overrides, additionalFactoryDeps?: ethers.BytesLike[], ): Promise; export declare function getContractFactoryFromArtifact( artifact: ZkSyncArtifact, - signerOrOptions?: Signer | FactoryOptions, + wallet?: Wallet, deploymentType?: DeploymentType ): Promise; export interface HardhatZksync2jsHelpers { provider: Provider; + getWallet: (privateKey?: string) => Wallet; getContractFactory: typeof getContractFactory; getContractFactoryFromArtifact: typeof getContractFactoryFromArtifact; getContractAt: ( nameOrAbi: string | any[], address: string | Address, - signer?: Signer + wallet?: Wallet ) => Promise; getContractAtFromArtifact: ( artifact: ZkSyncArtifact, address: string, - signer?: Signer + wallet?: Wallet ) => Promise; - getSigner: (address: string) => Promise; - getSigners: () => Promise; + getSigner: (address: string) => Signer; + getSigners: () => Signer[]; getImpersonatedSigner: (address: string) => Promise; extractFactoryDeps: (artifact: ZkSyncArtifact) => Promise; loadArtifact: (name: string) => Promise; deployContract: (artifact: ZkSyncArtifact, constructorArguments: any[], - signer?: Signer | Wallet, + wallet?: Wallet, overrides?: ethers.Overrides, additionalFactoryDeps?: ethers.BytesLike[]) => Promise; } diff --git a/packages/hardhat-zksync-zksync2js/test/fixture-projects/simple/contracts/IGreeter.sol b/packages/hardhat-zksync-zksync2js/test/fixture-projects/simple/contracts/IGreeter.sol new file mode 100644 index 000000000..e14937886 --- /dev/null +++ b/packages/hardhat-zksync-zksync2js/test/fixture-projects/simple/contracts/IGreeter.sol @@ -0,0 +1,7 @@ +// SPDX-License-Identifier: MIT + +pragma solidity ^0.8.9; + +interface IGreeter { + function greet() external view returns (string memory); +} \ No newline at end of file diff --git a/packages/hardhat-zksync-zksync2js/test/fixture-projects/simple/hardhat.config.ts b/packages/hardhat-zksync-zksync2js/test/fixture-projects/simple/hardhat.config.ts index 45878aacd..d8919cbb7 100644 --- a/packages/hardhat-zksync-zksync2js/test/fixture-projects/simple/hardhat.config.ts +++ b/packages/hardhat-zksync-zksync2js/test/fixture-projects/simple/hardhat.config.ts @@ -1,5 +1,5 @@ -import '@matterlabs/hardhat-zksync-solc'; -import '@matterlabs/hardhat-zksync-deploy'; +import '../../../../hardhat-zksync-solc/src/index' +import '../../../../hardhat-zksync-deploy/src/index'; import '../../../src/index'; import { HardhatUserConfig } from 'hardhat/types'; @@ -10,16 +10,17 @@ const config: HardhatUserConfig = { settings: {}, }, networks: { + "hardhat": { + zksync: true + }, zkSyncNetwork: { allowUnlimitedContractSize: true, url: 'http://localhost:8011', - ethNetwork: 'http://localhost:8545', zksync: true, }, zkSyncTestnet:{ allowUnlimitedContractSize: true, url: "https://zksync2-testnet.zksync.dev", - ethNetwork: "goerli", zksync: true, // verifyURL: "https://zksync2-testnet-explorer.zksync.dev/contract_verification", }, diff --git a/packages/hardhat-zksync-zksync2js/test/helpers.ts b/packages/hardhat-zksync-zksync2js/test/helpers.ts index 9020b4304..0c1025670 100644 --- a/packages/hardhat-zksync-zksync2js/test/helpers.ts +++ b/packages/hardhat-zksync-zksync2js/test/helpers.ts @@ -13,7 +13,6 @@ export function useEnvironment(fixtureProjectName: string, networkName = 'zkSync beforeEach('Loading hardhat environment', async function () { process.chdir(path.join(__dirname, 'fixture-projects', fixtureProjectName)); process.env.HARDHAT_NETWORK = networkName; - this.env = require('hardhat'); await this.env.run(TASK_COMPILE); }); diff --git a/packages/hardhat-zksync-zksync2js/test/tests.ts b/packages/hardhat-zksync-zksync2js/test/tests.ts index 4a9e3c428..2e1c77682 100644 --- a/packages/hardhat-zksync-zksync2js/test/tests.ts +++ b/packages/hardhat-zksync-zksync2js/test/tests.ts @@ -1,5 +1,7 @@ import { assert } from 'chai'; import { useEnvironment } from './helpers'; +import { Contract, ContractFactory, Wallet } from 'zksync2-js'; +import { rich_wallets } from '../src/rich-wallets'; describe('Plugin tests', async function () { @@ -12,6 +14,8 @@ describe('Plugin tests', async function () { assert.containsAllKeys(this.env.zksync2js, [ "provider", "getSigners", + "getWallet", + "getWallets", "getImpersonatedSigner", "getContractFactory", "getContractAt", @@ -25,78 +29,224 @@ describe('Plugin tests', async function () { describe("Provider", function () { it("the provider should handle requests", async function () { - const blockNumber = await this.env.zksync2js.provider.send("eth_blockNumber", []); - assert.strictEqual("0x0", blockNumber); + const gasPrice = await this.env.zksync2js.provider.send("eth_gasPrice", []); + + assert.strictEqual("0xee6b280", gasPrice); + }); + it("should return fee data", async function () { + const feeData = await this.env.zksync2js.provider.getFeeData(); + + assert.typeOf(feeData.gasPrice, "bigint"); + }); + it("should get the gas price", async function () { + const feeData = await this.env.zksync2js.provider.getFeeData(); + + assert.isNotNull(feeData.gasPrice); + assert.isTrue(feeData.gasPrice > 0); + }); + }); + + describe("getSigners", function () { + it("should return the signers", async function () { + const sigs = await this.env.zksync2js.getSigners(); + + assert.strictEqual( + await sigs[0].getAddress(), + "0x36615Cf349d7F6344891B1e7CA7C72883F5dc049" + ); + }); + it("should expose the address synchronously", async function () { + const sigs = await this.env.zksync2js.getSigners(); + + assert.strictEqual( + sigs[0].address, + "0x36615Cf349d7F6344891B1e7CA7C72883F5dc049" + ); + }); + }); + + describe("getImpersonatedSigner", function () { + it("should return the working impersonated signer", async function () { + const address = `0x${"ff".repeat(20)}`; + const impersonatedSigner = + await this.env.zksync2js.getImpersonatedSigner(address); + + assert.strictEqual( + impersonatedSigner.address, + "0xFFfFfFffFFfffFFfFFfFFFFFffFFFffffFfFFFfF" + ); + }); + }); + + describe("signer", function () { + it("should allow to use the estimateGas method", async function () { + const [sig] = await this.env.zksync2js.getSigners(); + + const Greeter = await this.env.zksync2js.getContractFactory("Greeter"); + const tx = await Greeter.getDeployTransaction(); + + const result = await sig.estimateGas(tx); + + assert.isTrue(result > 0n); + }); + it("should return the balance of the account", async function () { + // we use the second signer because the first one is used in previous tests + const [, secondSigner] = await this.env.zksync2js.getSigners(); + + assert.strictEqual( + await this.env.zksync2js.provider.getBalance(secondSigner.address), + 1000000000000000000000000000000n + ); + }); + it("should return the transaction count of the account", async function () { + // we use the second signer because the first one is used in previous tests + const [, secondSigner] = await this.env.zksync2js.getSigners(); + + assert.strictEqual( + await this.env.zksync2js.provider.getTransactionCount(secondSigner), + 0 + ); + }); + }); + + describe("wallet", function () { + it("get default wallet", async function () { + const wallet = this.env.zksync2js.getWallet(); + + assert.isDefined(wallet); + assert.equal((await wallet.getAddress()).length, 42); + assert.equal((await wallet.getAddress()), "0x36615Cf349d7F6344891B1e7CA7C72883F5dc049"); + }); + it("get specific wallet", async function () { + const wallet = this.env.zksync2js.getWallet(rich_wallets[6].privateKey); + + assert.isDefined(wallet); + assert.equal((await wallet.getAddress()).length, 42); + assert.equal((await wallet.getAddress()), "0xbd29A1B981925B94eEc5c4F1125AF02a2Ec4d1cA"); + }); + it("should send a transaction", async function () { + const wallet = this.env.zksync2js.getWallet(); + + const Greeter = await this.env.zksync2js.getContractFactory("Greeter"); + const tx = await Greeter.getDeployTransaction(); + + const response = await wallet.sendTransaction(tx); + + const receipt = await response.wait(); + + if (receipt === null) { + assert.fail("receipt shoudn't be null"); + } + assert.strictEqual(receipt.status, 1); + }); + it("should deploy with wallet", async function () { + const artifact = await this.env.zksync2js.loadArtifact("Greeter"); + const contract: Contract = await this.env.zksync2js.deployContract(artifact, []); + + assert.isDefined(contract); + assert.equal((await contract.getAddress()).length, 42); + }); + it("should allow to use the call method", async function () { + const wallet = await this.env.zksync2js.getWallet(); + + const Greeter = await this.env.zksync2js.getContractFactory("Greeter"); + const tx = await Greeter.getDeployTransaction(); + + const result = await wallet.call(tx); + + assert.isString(result); + }); + it("should populate a transaction", async function () { + const wallet = await this.env.zksync2js.getWallet(); + + const Greeter = await this.env.zksync2js.getContractFactory("Greeter"); + const tx = await Greeter.getDeployTransaction(); + + const populatedTransaction = await wallet.populateTransaction(tx); + + assert.strictEqual(populatedTransaction.from, wallet.address); + assert.strictEqual(tx.type, 113); + assert.strictEqual(tx.to, "0x0000000000000000000000000000000000008006"); }); }); - describe("Signers and contracts helpers", function () { - describe("getSigners", function () { - it("should return the signers", async function () { - const sigs = await this.env.zksync2js.getSigners(); - assert.strictEqual( - await sigs[0].getAddress(), - "0x36615Cf349d7F6344891B1e7CA7C72883F5dc049" - ); - }); - it("should expose the address synchronously", async function () { - const sigs = await this.env.zksync2js.getSigners(); - assert.strictEqual( - sigs[0].address, - "0x36615Cf349d7F6344891B1e7CA7C72883F5dc049" - ); - }); - }); - describe("getImpersonatedSigner", function () { - it("should return the working impersonated signer", async function () { - const address = `0x${"ff".repeat(20)}`; - const impersonatedSigner = - await this.env.zksync2js.getImpersonatedSigner(address); - - assert.strictEqual( - impersonatedSigner.address, - "0xFFfFfFffFFfffFFfFFfFFFFFffFFFffffFfFFFfF" - ); - - }); - }); - describe("signer", function () { - // `signer.getBalance` is not present in ethers v6; we should re-enable - // this test when/if it's added back - it.skip("should return the balance of the account", async function () { - const [sig] = await this.env.zksync2js.getSigners(); - assert.strictEqual( - (await sig.getBalance()).toString(), - "100000000000000000000" - ); - }); - - it("should return the balance of the account", async function () { - // we use the second signer because the first one is used in previous tests - const [, secondSigner] = await this.env.zksync2js.getSigners(); - assert.strictEqual( - await this.env.zksync2js.provider.getBalance(secondSigner.address), - 1000000000000000000000000000000n - ); - }); - - it("should return the transaction count of the account", async function () { - // we use the second signer because the first one is used in previous tests - const [, secondSigner] = await this.env.zksync2js.getSigners(); - assert.strictEqual( - await this.env.zksync2js.provider.getTransactionCount(secondSigner), - 0 - ); - }); - - it("should deploy with signer", async function () { - const [signer] = await this.env.zksync2js.getSigners(); - - const artifact = await this.env.zksync2js.loadArtifact("Greeter"); - const contract = await this.env.zksync2js.deployContract(artifact, []); - assert.isDefined(contract); - assert.equal(contract.address.length, 42); - }); + describe("getContractFactory", function () { + it("should return a contract factory", async function () { + const contract = await this.env.zksync2js.getContractFactory("Greeter"); + + assert.isNotNull(contract.interface.getFunction("greet")); + + // non-existent functions should be null + assert.isNull(contract.interface.getFunction("doesntExist")); + }); + it("should fail to return a contract factory for an interface", async function () { + try { + await this.env.zksync2js.getContractFactory("IGreeter"); + } catch (err: any) { + assert.equal(err.message, "You are trying to create a contract factory for the contract IGreeter, which is abstract and can't be deployed.\nIf you want to call a contract using IGreeter as its interface use the \"getContractAt\" function instead."); + } + }); + it("should return a contract factory", async function () { + const artifact = await this.env.zksync2js.loadArtifact("Greeter"); + const contract = await this.env.zksync2js.getContractFactory( + artifact.abi, + artifact.bytecode + ); + + assert.isNotNull(contract.interface.getFunction("greet")); + }); + it("Should be able to send txs and make calls", async function () { + const artifact = await this.env.zksync2js.loadArtifact("Greeter"); + + const Greeter: ContractFactory = await this.env.zksync2js.getContractFactory(artifact.abi, artifact.bytecode); + const greeter: Contract = await Greeter.deploy() as Contract; + + assert.strictEqual(await greeter.greet(), "Hello, World!"); + }); + }); + + describe("getContractAt", function () { + let deployedGreeter: Contract; + + beforeEach(async function () { + const Greeter = await this.env.zksync2js.getContractFactory("Greeter"); + deployedGreeter = await Greeter.deploy() as Contract; + }); + it("Should return an instance of a contract", async function () { + const wallet = this.env.zksync2js.getWallet(); + const contract = await this.env.zksync2js.getContractAt( + "Greeter", + deployedGreeter.target.toString(), + ); + + assert.exists(contract.greet); + + assert.strictEqual( + await (contract.runner as Wallet).getAddress(), + await wallet.getAddress() + ); + }); + it("Should return an instance of an interface", async function () { + const wallet = this.env.zksync2js.getWallet(); + const contract = await this.env.zksync2js.getContractAt( + "IGreeter", + deployedGreeter.target.toString() + ); + + assert.isNotNull(contract.interface.getFunction("greet")); + + assert.strictEqual( + await (contract.runner as Wallet).getAddress(), + await wallet.getAddress() + ); + }); + it("Should be able to send txs and make calls", async function () { + const greeter = await this.env.zksync2js.getContractAt( + "Greeter", + deployedGreeter.target.toString() + ); + + assert.strictEqual(await greeter.greet(), "Hello, World!"); }); }); });