Skip to content

How To Use Different Addresses To Call Functions in Hardhat Scripts?

Using different addresses to call functions in Hardhat tests and scripts can be crucial for various scenarios, such as testing contract behavior with different users, simulating transactions from multiple parties, or verifying contract functionalities under various conditions. In this guide, I’ll walk you through the process of managing multiple addresses effectively within your Hardhat tests and scripts.

1. Understanding Ethereum addresses

Ethereum addresses are alphanumeric identifiers representing user accounts or smart contracts on the Ethereum blockchain. These addresses are derived from public-private key pairs and are used to send and receive Ether or interact with smart contracts.

2. Generating multiple Ethereum addresses

In Ethereum, you can generate multiple addresses easily. Typically, each Ethereum address corresponds to a unique private key. Hardhat provides utilities for generating Ethereum addresses programmatically. For instance, you can use the ethers library to create multiple accounts:

const { ethers } = require('hardhat');

async function generateAccounts(numAccounts) {
    const accounts = [];
    for (let i = 0; i < numAccounts; i++) {
        const wallet = ethers.Wallet.createRandom();
        accounts.push(wallet);
    }
    return accounts;
}

const numAccounts = 5;
const accounts = await generateAccounts(numAccounts);

This code will generate five Ethereum addresses along with their corresponding private keys.

🔥 Check this course out: Build a One Piece Personality dApp With Solidity

3. Deploying contracts with different accounts

Hardhat allows you to deploy contracts using different Ethereum addresses. This is useful for testing contract deployment and initialization logic from various perspectives.

const { ethers } = require('hardhat');

async function deployContractWithAccount(contractName, account) {
    const Contract = await ethers.getContractFactory(contractName);
    const contract = await Contract.connect(account).deploy();
    return contract;
}

const contractName = 'MyContract';
const deployedContracts = [];
for (let i = 0; i < numAccounts; i++) {
    const contract = await deployContractWithAccount(contractName, accounts[i]);
    deployedContracts.push(contract);
}

This code deploys the contract MyContract using each of the generated Ethereum addresses.

4. Interacting with contracts using different accounts

Once contracts are deployed, you can interact with them using different accounts. This allows you to test various scenarios, such as different users accessing specific functionalities.

const contract = deployedContracts[0]; // Using the first deployed contract
const signer = accounts[1]; // Using the second generated account for interaction

await contract.connect(signer).someFunction(); // Call contract function with the second account

5. Managing balances and transactions

In Ethereum, each transaction requires gas fees to be paid. When testing contracts with multiple accounts, you need to ensure each account has sufficient Ether balance for executing transactions.

const { ethers } = require('hardhat');

async function fundAccount(account, amount) {
    await ethers.provider.sendTransaction({
        to: account.address,
        value: ethers.utils.parseEther(amount)
    });
}

const amountToFund = '10'; // Ether amount to fund
for (let i = 0; i < numAccounts; i++) {
    await fundAccount(accounts[i], amountToFund);
}

This code funds each generated account with a specified amount of Ether.

🔥 Check this course out: Build Hogwarts Sorting Hat dApp on Polygon

6. Handling events and assertions

In your tests, you might need to verify certain events emitted by contracts or assert specific conditions after function calls. Hardhat provides utilities for listening to events and making assertions.

// Example: Listening to an event
const tx = await contract.someFunction();
await tx.wait(); // Ensure the transaction is mined
const receipt = await ethers.provider.getTransactionReceipt(tx.hash);
const event = contract.interface.parseLog(receipt.logs[0]);

// Example: Assertion
assert(event.name === 'SomeEvent', 'Event not emitted');

7. Cleaning up

After testing or executing scripts, it’s essential to clean up any state changes, such as reverting transactions or resetting contract states. Hardhat allows you to revert transactions or reset blockchain state easily.

// Example: Reverting transactions
await expect(
    contract.someFunctionThatShouldFail()
).to.be.revertedWith('Revert reason');

// Example: Resetting blockchain state
await hre.network.provider.request({
    method: "hardhat_reset",
    params: [],
});

🔥 Check this course out: Build a Semi-Fungible ERC404 Tokens’ Marketplace

Conclusion

Managing multiple addresses effectively in Hardhat tests and scripts enables you to thoroughly test smart contracts under various conditions, ensuring their robustness and reliability. By generating addresses, deploying contracts, interacting with contracts, managing balances, handling events, and cleaning up, you can conduct comprehensive testing and simulation of Ethereum-based applications.

Remember to consider gas fees, state changes, and contract behaviors meticulously to ensure accurate and reliable testing outcomes. With the right approach and tools provided by Hardhat, you can streamline the testing process and improve the quality of your Ethereum smart contracts.

Try it out, ask us questions, and tell us how it went by tagging Metaschool on Social Media.

Follow us on –

🔮Twitter – https://twitter.com/0xmetaschool

🔗LinkedIn – https://www.linkedin.com/company/0xmetaschool/