41

I can deploy a contract using ethers and Hardhat with the following:

const myContract = await hre.ethers.getContractFactory("SomeContract");
const deployedContract = await myContract.deploy();

I can even interact with the methods from that deployed contract if I use that deployedContract variable. However what if the contract has already been deployed and I want to interact with it? From what I've read, I need to create an instance of that contract. And I've tried to do that like this:

const provider = new ethers.providers.JsonRpcProvider();
const fs = require('fs');
const abi = JSON.parse(fs.readFileSync('./abi/SomeContract.json', 'utf8'));
const contractInstance = new ethers.Contract('contract address goes here', abi, provider);

I believe an instance is created on that contractInstance variable, but if I try to call methods on that instance in the console or from a script, I get a WARNING: Calling an account which is not a contract error.

Maybe I'm misunderstanding something about how contract instances are supposed to work?

11 Answers 11

56

I ran into the same question and stumbled upon a section in the OpenZeppelin docs that may work for you (it did for me):

For example:

const MyContract = await ethers.getContractFactory("MyContract");
const contract = await MyContract.attach(
  "0x..." // The deployed contract address
);

// Now you can call functions of the contract
await contract.doTheThing();
17

hardhat-ethers ^2.0.0 has a special function getContractAt for exactly this purpose:

const contractAddress = "0x...",
const myContract = await hre.ethers.getContractAt("MyContract", contractAddress);
5

I will give a full example for interaction with the already deployed contract. We call mint method and send some ether as well to the contract

async function main() {
    const contractAddress = "0xC47Fd6ec9bb45115e89E76aC914F6EEe19501c15";
    const myContract = await hre.ethers.getContractAt("NameOfContract", contractAddress);
    
    const mintToken = await myContract.mint(1, { value: ethers.utils.parseEther("0.3") });

    console.log("Trx hash:", mintToken.hash);

}

main()
    .then(() => process.exit(0))
    .catch((error) => {
        console.error(error);
        process.exit(1);
    });

Then we call that main function with async/await pattern. Whole code is called from CLI like

npx hardhat run scripts/interact.js --network  rinkeby
4

Assuming

import { Contract, providers, utils, Wallet } from "ethers";

and

    const rpc =  await new providers.JsonRpcProvider( process.env.RPC_ENDPOINT ) ;
    const wallet = new Wallet( process.env.PRIVATE_KEY, rpc);

Then using the ABI...

import { testTokenAbi } from "./abi/token.js";

where the abi file in the format of:

export const testTokenAbi =[*abi json here*];

...You can also link the json in a .json file, or just assign the abi json for relevant functions to a variable directly...such as

const testTokenAbi = [ *abi json here*];

now we can instantiate the deployed contract with a signer using:

const testTokenContract = new Contract(testTokenAddress, testTokenAbi, wallet);

then use our contract object to do things, like approve a transfer

testTokenContract.approve( exchangeRouterAddress, amountToken);

Now if you deploy to the wrong chain, then this won't work.

When you run the deploy script make sure the --network [network] flag is pointing to the same rpc that you are running your script against..

I just had this come up where I deployed without the flag, which was just creating a temporary node and then deleting it so that all my contract calls failed because I didn't deploy to the forked node I was running my scripts against.

2

This is how I use to instantiate contract at a specific address in Hardhat:

const accounts = await hre.ethers.getSigners()
const MyContract = await ethers.getContractFactory("MyContract");
const myContract = new ethers.Contract(MyContract, MyContract.interface, accounts[0]);

Hope it helps! :)

2
  • 1
    How does hardhat know the previously deployed address? Also I think it might be accounts[0].address
    – NickJ
    Apr 25, 2021 at 23:00
  • ethers.Contract first argument must be an address. So for example const contract = await MyContract.deploy(); contract.address Sep 9, 2021 at 2:55
1

@Chris answer helped me!

const myContract = ethers.getContractAt("MyContract", contractAddress);
console.log("Live Address:\t" + myContract.address);
await myContract.callFunctions();
0

This would seem like a wrong chain issue. Are you sure that Hardhat is pointed at the same chain as the contract? You can change the chain Hardhat runs on by either changing the value of defaultNetwork in hardhat.config or by running with the --network flag (for example --network rinkeby), provided there is a corresponding object in networks in hardhat.config.

Incidentally, you don't need to use fs to import the ABI. You can import it using an import or require.

const someContractAbi = require("./abi/SomeContract.json");

Depending on the setup, you may need to select the abi object from the ABI, though that doesn't seem to be your issue. For importing, you'd likely want a separate file that you copy-paste the abi object into.

const someContractAbi = require("./abi/SomeContract.json").abi;
0
const contract = await (await ethers.getContractFactory("MyContract")).attach("0xAddress")
1
  • It will be nicer if you include a little explanation for the code.
    – Ismael
    Nov 30, 2021 at 5:43
0

None of these answers worked for me until I used the following, including the provider, the signer, and getting the contract instance:

const provider = new ethers.providers.JsonRpcProvider() // using default http://localhost:8545
const signer = new ethers.Wallet(privkey, provider)
const myContract = await ethers.getContractAt('MyContract', contractAddress, signer)
const out = await myContract.balanceOf(walletAddress)
console.log(out)
0

Use

deployedContract = await ethers.getContractAt("ContractName", ContractAddress);
0

Both getContractAt and attach work for me: I will share the code.

    this.CollectionMinter = await ethers.getContractFactory("CollectionMinter")
    this.CollectionMinter = await this.CollectionMinter.deploy()
    await this.CollectionMinter.deployed()
    console.log(`           CollectionMinter Deployed at:${this.CollectionMinter.address}`)

    await this.CollectionMinter.createNewCollection("CryptoOwl Collection", "COC", "HTTPS://Empire/collections/COC/") 
    const CryptoOwlAddress = await this.CollectionMinter.collectionAddress()
    console.log(`           CryptoOwl Collection deployed at:${CryptoOwlAddress}`)

   //1.using getContractAt
   this.COC = await ethers.getContractAt("LaunchpadCollection",CryptoOwlAddress)
   //2. using attach
   this.COC = await ethers.getContractFactory("LaunchpadCollection"); 
   this.COC = this.COC.attach(CryptoOwlAddress)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.