Solidity – How to Handle Unexpected Object Returned from Basic Solidity Contract Using Hardhat and Ethers.js

ethers.jshardhatsolidity

I can't work out what i'm doing wrong here. Why can't i get a simple uint to return from my contract when running using hardhat tests?

Contract.sol:

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;

import "@openzeppelin/contracts/utils/math/SafeMath.sol";
import 'hardhat/console.sol';
import "@openzeppelin/contracts/access/AccessControl.sol";

contract Contract is AccessControl {
    using SafeMath for uint256;

    constructor() {
        _grantRole(DEFAULT_ADMIN_ROLE, msg.sender);
    }

    function doIt() public returns (uint256) {
        console.log("Returning 1 from contract");
        return 1;
    }

}

Test.js

const { expect, assert } = require("chai");
const { ethers, upgrades } = require("hardhat");

describe("Contract", function () {  
  let acontract;

  beforeEach(async function () {
    // Deploying contract
    const aContract = await ethers.getContractFactory("Contract");
    acontract = await aContract.deploy();
    await acontract.deployed();
    console.log(`Contract deployed to ${acontract.address}`);
  });

  describe("test contract", function () {
    it("doIt", async function () {
        console.log(JSON.stringify(await acontract.doIt()));
    });
  });
});

Output:

npx hardhat test test-test/test.js

  Contract
    test contract
Contract deployed to 0x5FbDB2315678afecb367f032d93F642f64180aa3
Returning 1 from contract
{"hash":"0x2e7cd7d48db5bf437d117ca6c2de3d067c4299fba02b55b69d7a0037a01de74f","type":2,"accessList":[],"blockHash":"0xb15cbb79171f086b59bfa277aa643510022bc787098c4e3a77309c939ae36885","blockNumber":2,"transactionIndex":0,"confirmations":1,"from":"0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266","gasPrice":{"type":"BigNumber","hex":"0x6978bc25"},"maxPriorityFeePerGas":{"type":"BigNumber","hex":"0x3b9aca00"},"maxFeePerGas":{"type":"BigNumber","hex":"0x9756ae4a"},"gasLimit":{"type":"BigNumber","hex":"0x01bad458"},"to":"0x5FbDB2315678afecb367f032d93F642f64180aa3","value":{"type":"BigNumber","hex":"0x00"},"nonce":1,"data":"0xb29f0835","r":"0x1c77fabb8795afe562dd6772bd3c26db9b73f94d0be5774dfc3488a3a1e6d299","s":"0x30a98924f50a02f6f06698edf29b14d1be2f3fddea60cba276a4e60a3198e33d","v":0,"creates":null,"chainId":31337}
      ✓ doIt

Any help appreciated. Thanks

Best Answer

When you call a non view/pure function, ethers creates and signs a transaction. Ethers then returns the transaction data and not the value returned by your solidity function (the value is actually encoded in the transaction hash). You can get the returned value by:

  • emitting an event,
  • changing the type of your function to view if it does not change the state of the contract, or to pure if it does not access state variables

A more detailed explanation is available here

Related Topic