solidity – Should External Non-Pure Functions Have Return Values?

interfacessolidity

Does it make sense for a non-pure/non-view external function to return any values at all? This is especially when this external function is likely going to be called off-chain.

Since they are likely to be called off-chain, whatever value is returned cannot really be returned to the off-chain caller. These functions in the contract are going to run some operations, perhaps updating some states, and then return some calculated values from the new state and also emit an event of that calculated value. When calling these functions off-chain, I could only rely on the event for that value. The returned value directly from the function is not going to be available to me.

Then, when making design decisions for an interface with external functions, should external non-pure/non-view functions even have any return values since they can't be accessed? Otherwise, in what cases should these external functions should and should not have return values?

Best Answer

An external function with mutability that is not view or pure (i.e. it is payable or non-payable) may or may not have a returns. This is an example of one that does, from UniswapV1:

function ethToTokenSwapInput(uint256 min_tokens, uint256 deadline)
    external
    payable
    returns (uint256 tokens_bought);

You send it an amount of ETH and specify the minimum amount of ERC-20 tokens to buy with those ETH, and it updates the blockchain state to reflect the new token and Ether balances after the swap, it emits a TokenPurchase event (that has a tokens_bought field), and it also returns the tokens_bought as a return value.

It this particular case, since the exact amount of tokens your ETH will buy you will depends on the market conditions at the moment of the swap, it is useful to be able to know tokens_bought, the exact number of tokens you actually ended up with after the swap.

If you’re calling this function from an externally-owned account (from “outside”, from a “normal” non-contract account, which you control with a private key), you will not have access to the return value, but you can read tokens_bought from the emitted TokenPurchase event.

If on the other hand you’re buying these tokens with ETH on Uniswap from within a contract, the contract will not be able to see the TokenPurchase event, but it will receive the amount of tokens bought via the return value, and can then go on to do something useful with it.

So if your function will be called from a contract, and you would like your function to do an action and then return to the calling contract some value resulting from that action, then declare returns, otherwise there is no need to.

Related Topic