In the process of developing smart contracts with Hardhat, writing tests and scripts is a crucial step. In these tests and scripts, it is sometimes necessary to simulate different external accounts (addresses) calling functions in the contract to mimic real-world interactions of different users. Hardhat provides several methods to achieve this. I will demonstrate how to call functions with different addresses in Hardhat through the following steps:
1. Getting Test Accounts
In the Hardhat environment, a set of shared accounts is created by default for your use. You can obtain these accounts using Hardhat's ethers plugin. Here is an example of how to retrieve accounts:
javascriptconst { ethers } = require("hardhat"); async function main() { // Get all test accounts const accounts = await ethers.getSigners(); // Access the first account const owner = accounts[0]; const user1 = accounts[1]; const user2 = accounts[2]; // Output account addresses for verification console.log("Owner address:", owner.address); console.log("User1 address:", user1.address); console.log("User2 address:", user2.address); } main().catch((error) => { console.error(error); process.exitCode = 1; });
2. Calling Functions with Different Accounts
Once you have the accounts, you can use them to call functions in the smart contract. This can be achieved by using the connect method, which connects the contract to different signers (i.e., different accounts). Here is an example:
javascript// Assume we have a deployed contract instance `myContract` async function interactWithContract() { const accounts = await ethers.getSigners(); const user1 = accounts[1]; // Call a function in the contract using user1's account const tx = await myContract.connect(user1).myFunction(); await tx.wait(); console.log(`Function has been called by ${user1.address}`); } interactWithContract().catch((error) => { console.error(error); process.exitCode = 1; });
3. Writing Tests
When writing tests, you can use the same approach to simulate interactions of different accounts with the contract. For example, using Hardhat's testing framework, you can write:
javascriptconst { expect } = require("chai"); describe("Contract Test", function () { let accounts; let myContract; before(async function () { accounts = await ethers.getSigners(); const ContractFactory = await ethers.getContractFactory("MyContract"); myContract = await ContractFactory.deploy(); await myContract.deployed(); }); it("should allow user1 to call myFunction", async function () { const user1 = accounts[1]; await expect(myContract.connect(user1).myFunction()).to.not.be.reverted; console.log(`myFunction was successfully called by ${user1.address}`); }); });
By doing this, you can ensure that different test scenarios are simulated and tested, thereby enhancing the contract's robustness and security. This is one of the key steps in writing effective smart contract tests and scripts.