Solidity – How to Log a Returned Variable Instead of Entire Transaction Receipt in Hardhat (TypeScript)

ethers.jshardhatsoliditytypescript

I have a function, fn(), in a contract that returns a variable. I am then testing said function's returned variable value in a Hardhat unit test written in TypeScript. However, when I console.log the output of calling fn(), it logs the entire transaction receipt.

If I then alter the function to be either a view or pure function, it logs the actual value of the returned variable. The problem is that I need to test that the function actually alters a state variable. How do I remedy this?

function that logs tx receipt:

fn() public returns(uint8) {
    uint8 numberLogged = 1;
    return numberLogged;
}

function that logs variable's value:

fn() public pure /*or view*/ returns(uint8) {
    uint8 numberLogged = 1;
    return numberLogged;
}

unit test:

import { FnContract } from "../typechain/FnContract";

describe("FnContract contract test", function () {
    let fnContract: FnContract;

    it("logs the output of fn()", async function() {
        const fnContractFactory = await ethers.getContractFactory("FnContract");

        const accounts = await ethers.getSigners();

        const accountOne = accounts[0];
        const accountTwo = accounts[1];

        fnContract = (await fnContractFactory.deploy()) as FnContract;

        const numberLogged = await fnContract.fn();
        await numberLogged.wait();

        console.log(numberLogged);
    })

Lastly, I am currently learning TypeScript, so could it possibly be in how I set up the TypeScript test file?

Best Answer

Unfortunately, it's not possible to get the return value of a state-changing function outside the off-chain. It's only possible to get it on-chain, in other contracts which call your contract.

What is usually done is that you emit events with the required data, and listen to those events. Or then you save the required data in the contract and have another view function which you call to return the data.