How to get Ethers.js response data

Viewed 8514

Solidity:

function ping() public view returns ( uint ) {
    return 999999999;
}
function ping2() public returns ( uint ) {
    return 999999999;
}

Javascript Ethers.js:

(await contract.ping()).toString();  //-> 999999999  ( correct ) 
(await contract.ping2()).toString(); //-> [object Object] ( ?? )

Why does ping2 return [Object Object] ? How to get the data from ping2?

Also:

(await contract.sendTransaction(txObj)).toString(); //-> [object Object] ( ?? )

Why does using sendTransaction also return [object Object] ?

2 Answers

(await contract.ping()).toString(); //-> 999999999 ( correct )

ping() is a view function - you can just call it without creating a transaction. So ethers.js doesn't create a transaction and just returns result of the call.


(await contract.ping2()).toString(); //-> [object Object] ( ?? )

Why does using sendTransaction also return [object Object] ?

ping2() is a regular public function. Which suggests that you need to create a transaction to execute it (even though in this case it doesn't make any state changes so it could be a view function as well).

Ethers.js returns the transaction data instead of the contract function return value, when you're creating a transaction.

There are few ways to read values that the transaction produced using Ethers.js.

  • In this case, ping2() doesn't make any state changes and doesn't even read any blockchain data, so it could be a pure function. If it were reading blockchain data, it would be a view function... In both cases, ethers.js returns the result of the function call (not tx).

  • Transaction to a setter and calling a getter.

    contract MyContract {
        uint256 value;
    
        function setValue(uint256 _value) public {
            value = _value;
        }
    
        function getValue() public view returns (uint256) {
            return value;
        }
    }
    

    First you create a transaction that executes the setValue() function, and then you make a call to getValue() (without transaction, so it returns the value in your JS).

  • Reading event logs that your transaction produced

    event Transfer(address from, address to, uint256 amount);
    
    function transfer(address _to, uint256 _amount) public {
        emit Transfer(msg.sender, _to, _amount);
    }
    

    You can get the transaction receipt that also contains the event logs (in this case, the Transfer event and its values).

Here is a great solution from Force Hero using Events.

In a nutshell:

const tx = await contract.transfer(...args); // 100ms
const rc = await tx.wait(); // 0ms, as tx is already confirmed
const event = rc.events.find(event => event.event === 'Transfer');
const [from, to, value] = event.args;
console.log(from, to, value);
Related