Read from a testnet (rinkeby) contract with hardhat script

Hi there,
I am trying to read state variables (using hardhat scripts) from a contract deployed on the Rinkeby network. I use the script below but it returns ‘undefined’ as if it can’t read from the contract.

const hre = require("hardhat");
const { expect } = require("chai");


async function main() {

  const [deployer] = await ethers.getSigners();

  console.log("Deployed contracts with the account:", deployer.address);

  console.log("Account balance:", (await deployer.getBalance()).toString());

  const abi = [ { "anonymous": false, "inputs": [ { "indexed": true, "internalType": "address", "name": "previousOwner", "type": "address" }, { "indexed": true, "internalType": "address", "name": "newOwner", "type": "address" } ], "name": "OwnershipTransferred", "type": "event" }, { "inputs": [], "name": "owner", "outputs": [ { "internalType": "address", "name": "", "type": "address" } ], "stateMutability": "view", "type": "function" }, { "inputs": [], "name": "renounceOwnership", "outputs": [], "stateMutability": "nonpayable", "type": "function" }, { "inputs": [ { "internalType": "address", "name": "newOwner", "type": "address" } ], "name": "transferOwnership", "outputs": [], "stateMutability": "nonpayable", "type": "function" } ];
 
  let provider = ethers.getDefaultProvider('rinkeby');
  
  const designManager = await new ethers.Contract(0x3EB0A404f33eCacfd4e57c8De791e03588eE065C, abi, provider);


  console.log("DesignManager address:", designManager.address);
  console.log("DesignManager project Name:", await designManager.projectName());
  console.log("DesignManager project ID", await designManager.projectID());

}

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

When I run the script using npx hardhat run scripts/logs.js --network rinkeby I am getting the terminal output:

Deployed contracts with the account: 0x17*******
Account balance: 1959160072709728500
DesignManager address: 5.528590342605352e+47
DesignManager project Name: undefined
DesignManager project ID undefined

Could you please advise what is wrong in my script and why can’t I read the DesignManager and project ID variables from the contract ?

are you sure that the contract has those methods?

it looks like that ABI doesn’t contain those methods

Thank you for your reply,
projectName (string) and projectID (uint) are not methods but variables.

If I instead use the code:

  console.log("DesignManager project Name:", await designManager.projectName);
  console.log("DesignManager project ID", await designManager.projectID);

I also get the below output:

Deployed contracts with the account: 0x17****
Account balance: 1959160072709728500
DesignManager address: 3.5789664704537014e+47
DesignManager project Name: undefined
DesignManager project ID undefined

Any idea why this script can’t read these variables from the contract?

it may depend how those variables were defined, it they are public or not, not all variables can be read

Thank you for your reply,
the variables were declared as public as follows:

   string public projectName;
   uint public projectID;

where from did you get that abi? that abi doesn’t have those functions associated with those variables

Thank you very much for your reply, indeed you are correct the abi was incorrect, I have replaced the abi with the correct one but I am still unable to read the variables as shown below:

const hre = require("hardhat");
const { expect } = require("chai");

async function main() {

  const [deployer] = await ethers.getSigners();

  console.log("Deployed contracts with the account:", deployer.address);

  console.log("Account balance:", (await deployer.getBalance()).toString());

  const abi = [ 
    { "inputs": [ { "internalType": "string", "name": "_projectName", "type": "string" }, { "internalType": "uint256", "name": "_projectID", "type": "uint256" } ], "stateMutability": "nonpayable", "type": "constructor" }, 
    { "anonymous": false, "inputs": [ { "indexed": true, "internalType": "address", "name": "previousOwner", "type": "address" }, { "indexed": true, "internalType": "address", "name": "newOwner", "type": "address" } ], "name": "OwnershipTransferred", "type": "event" }, 
    { "inputs": [ { "internalType": "address", "name": "_packageLead", "type": "address" }, { "internalType": "string", "name": "_packageName", "type": "string" }, { "internalType": "string", "name": "_packageId", "type": "string" } ], "name": "createDesignPackage", "outputs": [ { "internalType": "address", "name": "", "type": "address" } ], "stateMutability": "nonpayable", "type": "function" }, 
    { "inputs": [ { "internalType": "uint256", "name": "", "type": "uint256" } ], "name": "designPackages", "outputs": [ { "internalType": "address", "name": "", "type": "address" } ], "stateMutability": "view", "type": "function" }, 
    { "inputs": [], "name": "owner", "outputs": [ { "internalType": "address", "name": "", "type": "address" } ], "stateMutability": "view", "type": "function" }, 
    { "inputs": [], "name": "packagesID", "outputs": [ { "internalType": "uint256", "name": "", "type": "uint256" } ], "stateMutability": "view", "type": "function" }, 
    { "inputs": [], "name": "projectID", "outputs": [ { "internalType": "uint256", "name": "", "type": "uint256" } ], "stateMutability": "view", "type": "function" }, 
    { "inputs": [], "name": "projectName", "outputs": [ { "internalType": "string", "name": "", "type": "string" } ], "stateMutability": "view", "type": "function" }, 
    { "inputs": [], "name": "renounceOwnership", "outputs": [], "stateMutability": "nonpayable", "type": "function" }, 
    { "inputs": [ { "internalType": "address", "name": "newOwner", "type": "address" } ], "name": "transferOwnership", "outputs": [], "stateMutability": "nonpayable", "type": "function" } 
  ];

  let provider = ethers.getDefaultProvider('rinkeby');
  
  const designManager = await new ethers.Contract(0x3EB0A404f33eCacfd4e57c8De791e03588eE065C, abi, provider);

  console.log("DesignManager address:", designManager.address);
  console.log("DesignManager project Name:", await designManager.projectName);
  console.log("DesignManager project ID", await designManager.projectID);
}

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

When I enter npx hardhat run scripts/logs.js --network rinkeby in the terminal, I get the below output:

Deployed contracts with the account: 0x17****
Account balance: 1959160072709728500
DesignManager address: 3.5789664704537014e+47
DesignManager project Name: [Function (anonymous)]
DesignManager project ID [Function (anonymous)]

Note that the contract was deployed so that projectName should be equal to “Project 1” and projectID should be 1. I am able to audit these values correctly when I enter the contract address on Remix on the Rinkeby network. I just can’t figure out why hardhat doesn’t let me get these variables from the script above.

this works fine:

import json
from web3 import Web3

b = 'https://speedy-nodes-nyc.moralis.io/adfadf/eth/rinkeby'
web3 = Web3(Web3.HTTPProvider(b))
print(web3.isConnected())

contract = "0x3eb0a404f33ecacfd4e57c8de791e03588ee065c"
contract = web3.toChecksumAddress(contract)
abi = json.loads(open("abi5.txt", 'rt').read())
contract = web3.eth.contract(address=contract, abi=abi)
x = contract.functions.projectName().call();
print(repr(x))

=>

Project1

Thanks a lot for trying and getting the correct output.
Would you mind giving me the full content of your script.js file so that I can try too.

Also do you know how could I make this work with ethers instead of web3.js.
This is because all my hardhat tests are done with ethers so far.

that is a python script, but you can make it work with any other library or programming language, you can make it work how you would call any other function for a contract

Ok I’ll play around with it, thanks very much for your help

You can also use Moralis.runContractFunction from Moralis sdk