Search code examples
soliditysmartcontractshardhat

Calling smart contract with hardhat can return either value or dictionary


I have a simple function in a smart contract

function getBalance() external view returns (uint) {
    requireMembership(msg.sender);
    return coins[msg.sender];
}

When I call it from hardhat Contract object it returns a number. On the other hand, when I call this

function vote(bytes32 merkleHash, bytes32 randomHash) external votePeriod returns (uint) {
    votes.push(Vote (msg.sender, merkleHash, randomHash));
    return votes.length - 1;
}

it returns more data

{
  hash: '0x80edd9baca248c121bdd026343c842f9b608ac1827c63998dde48d2c3a87b2c6',
  type: 2,
  accessList: [],
  blockHash: '0xcc1a5d8ac8d92f98e4f1247c4d76e83e27b167cdc29d2fe962f10ee773eaa509',
  blockNumber: 4,
  transactionIndex: 0,
  confirmations: 1,
  from: '0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266',
  gasPrice: BigNumber { value: "1590942713" },
  maxPriorityFeePerGas: BigNumber { value: "1000000000" },
  maxFeePerGas: BigNumber { value: "2181885426" },
  gasLimit: BigNumber { value: "29025624" },
  to: '0x5FbDB2315678afecb367f032d93F642f64180aa3',
  value: BigNumber { value: "0" },
  nonce: 2,
  data: '0xeeaaf19ded2380097cd5db2b14288f4081b387c78bb556bba20557ee9580b19c4c77aa01e57feaac04642d236597ea01c4f788ded7c59047121e4d1a42fa2daaaa22350a',
  r: '0xdddc05db4d271a1a4c7e1d31bf56fc7e052a5e0d0f15a9309e8ce492a3e46da1',
  s: '0x2968ea8648e0102437efa9c710ecc2188d72e0bb9afab5343b2062a4d5a5ee5b',
  v: 0,
  creates: null,
  chainId: 31337,
  wait: [Function (anonymous)]
}

Is this because getBalance is just a view?


Solution

  • Is this because getBalance is just a view?

    Yes, with combination that you're using Hardhat (and what I'm assuming from the context, Ethers.js).

    Ethers.js and some other libraries use the contract ABI (specifically the stateMutability property of each function) to decide on default behavior when invoking a function. Whether to invoke it using a read-only call or a read-write transaction.

    EVM by design exposes returned values for calls, but does not expose them for transactions.

    Since your script operates outside of EVM, it does not have access to return values from a function invoked by a transaction. And Ethers.js authors have decided in such case to return the transaction data instead of nothing.