Most of the code I read out in the wild follow the precondition pattern if (condition) throw;

But this approach is cumbersome for clients to read. For example, with web3js you would have to check if the full consumption of gas means that a throw happend or you ran out of gas. With Geth at least you can examine the callstack for an invalid jump via debug.traceTransaction()

It seems much more appropiate to follow this approach:

if (condition) 
 return ERRCODE;

By doing that you are capable getting the exception right.

Since using throw is so common in the codes I examined, what are possible drawbacks of my proposition, beside that you have to handle the error in all parts of the callstack correctly?


For example with web3js you would have to guestimate if the full consumtion of gas means that a throw happend or you ran out of gas

Guesstimation is unnecessary, you can get the estimated gas cost with:

let contract_instance = web3.eth.contract(abi).at(address); web3.eth.estimateGas( { from: web3.eth.defaultAccount, to: contract.address, data: contract_instance[method].getData.apply(null, args) });

beside that you have to handle the error in all parts of the callstack correctly

This IS the drawback. Especially once you get into inter-contract dependencies reverting every state-changing action is nearly impossible. And in an environment where the resulting state of the contract must always be known, throwing an exception is the best practice in this situation.

  • thanks, guestimating was clearly the wrong word. I wanted to express that I don't want to know what happened by comparing gas consumption alone, this is not a clean way. Also in many situations, it's preferable to know why an intent didn't succeed. And with multiple throws it's impossible to know. So manual graceful error handling FTW! – Roland Kofler Dec 19 '16 at 15:22

Throwing an exception makes it easier to reason about the resulting state on error. It's too easy to accidentally not revert all changes that were made on error if you return a value.

Future versions of the EVM will allow a throw construct which lets you read a value out even if state is reverted, and doesn't drain gas for the sub-call.

  • I come to the conclusion I should have read only assertion functions that are making the conditions testable before a state changing function call. that would allow me to know the reason why it would fail + having the state reverted without potential holes. – Roland Kofler Dec 20 '16 at 13:41

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.