100

There are two aspects to consider when choosing between assert() and require() Gas efficiency Bytecode analysis 1. Gas efficiency assert(false) compiles to 0xfe, which is an invalid opcode, using up all remaining gas, and reverting all changes. require(false) compiles to 0xfd which is the REVERT opcode, meaning it will refund the remaining gas. The ...


29

With an exception, as with throw, all effects (including events) of a transaction are reverted, except for the payment to the miner. So there would be no benefit in firing an event before a throw. Possible Alternative If full reversion via an exception isn't required, an error code might be usable. Example: contract C { function foo() returns(int) { ...


22

All gas is consumed because the EVM essentially only has 1 exception: Out of Gas. To see this clearer, take a look at the difference between a "pure" exception, and an error due to bad/buggy/invalid EVM code. Out of Gas is the former. Now there are errors such as stack underflow, invalid JUMP, and invalid opcode: they can be called "exceptions" but they ...


19

I'm using require for input validation as it's a little more efficient that if/throw. function foo(uint amount) { require(amount < totalAmount); ... } Where as assert should be used more for runtime error catching: function foo(uint amount) { ... __check = myAmount; myAmount -= amount; assert(myAmount < __check); ... }...


19

I went down this rabbit hole and got a proof of concept to work at the end. I can not recommend the journey. There's impedance mismatches on many levels, requiring lots of format conversions. In the end, my implementation still does not handle cross-contract calls. (There seems to be no way to figure out which contract address a particular program counter ...


15

In Solidity, by default, yes. On the EVM-level, a throw (bad jump, out-of-gas, or any other exception) only reverts the call it is inside. Solidity helpfully continues the exception down the stack until everything is undone. It is possible, using lower-level code (specifically, address.call()), to prevent this. Here is an example of this being used as an ...


15

I'll leave the precise interpretation of the OpCodes to someone else and just point out that they are different instructions so different implementations are to be expected. According to this: http://solidity.readthedocs.io/en/develop/control-structures.html#error-handling-assert-require-revert-and-exceptions Starting with Metropolis, revert; will return ...


11

In part I believe this was a security decision to ensure spamming the network with bogus transactions cost the sender gas. For instance, if gas was refunded after a throw, a malicious actor could create a contract that consumed some gas and then would throw. That actor could then send one or many transactions with a high gas price and a lot of gas, making ...


11

The Solidity throw instruction gets compiled to an invalid JUMP instruction (i.e. a jump to an invalid location). The section 9.4.2 of the Yellow Paper explains how exceptional halting works, in chapter 8 it explains that no gas is refunded in this case. In chapter 8 it states: Just as with contract creation, if the execution halts in an exceptional ...


11

To complement @Matthew's answer, it depends on how the call is made in Solidity. If C calls D.foo(), and foo does a throw, then yes the entire transaction is reverted. If C does a "lower-level raw call" like D.call(bytes4(sha3('foo()'))), and foo does a throw, then only foo and its subcalls are reverted. This is because a raw call does not propagate any ...


9

All the considerations in the question are helpful. throw is safer since it ensures that there are no side effects that remain, but another consideration is error reporting. With throw there's currently no way to get more information about the error whereas Events and error codes could be used with return to convey a more granular reason about the error. ...


7

The throw instruction is a EVM hack that reverts all changes made by current contract execution. It exploits exceptional termination of EVM which also consumes all gas.


6

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: ...


5

"bad jump" is just the way "throw" is modeled, so it is expected behaviour.


5

The ether value that was sent along with the transaction (or call if the exception is caught) is returned to the sender if you use throw in Solidity.


5

In the case of an exception, the state is rolled back, and all value remains with the sender. In the case of an exception, it is as if the transaction never happened, except that the gas is all given to the miner. See Exceptions in Solidity for more.


5

Just thought I would chime in, in case this Q&A is useful to others. For brevity, just imagine I prefixed everything with in my opinion. It's a very general question. I would segregate the situations into two cases: "No" is a valid answer to a question Something is wrong with the transaction In the first case, return false might be the way to go. For ...


5

The revert is often referred to as cheap throw as it refunds unused gas to the sender. If you are interested in the detailed design of this feature please look at the original EIP-140 discussion.


4

In soldidity mappings exist as if all keys were present with their values set to 0x0. For structs this means that all of the fields will be in their 0x0 state. Since voters is a mapping, you can access any key and it will return the Voter struct that corresponds to that key. Only arrays throw when you access unset indices.


4

Yes, all funds are returned to the sender, except the gas. https://github.com/ethereum/wiki/wiki/Solidity-Features#throw


4

It turns out that in solidity, you can't go passing around strings from contract to contract. When I removed the two string values my code compiled without a hitch.


4

Currently there are no custom exceptions in Ethereum Virtual Machine code. All failure conditions are "out of gas" as exception is modelled as consuming all the remaining gas. eth.debug.traceTransaction API may give you some insight, but it doesn't implement human readable error mechanisms at the moment as far as I know.


4

From Solidity 0.4 onwards: Functions that want to receive Ether have to specify the new payable modifier (otherwise they throw). A throw consumes all gas, so function buy() payable returns (uint amount).


4

1. Yes B will not be created if the transaction containing the creation of B has an exception. Example: pragma solidity ^0.4.8; contract A { B public b; function foo() { b = new B(); throw; } function getXfromB() returns (uint) { return b.x(); } } contract B { uint public x; function B() { x =...


4

I think none of the answers is correct. assert is reserved for conditions for with it is expected that static code analysis tools (maybe Solidity compiler in future versions) will be able to detect the error warning the developer at compile time. require is reserved for error-conditions of incorrect input data to functions (when compared to expected/valid ...


3

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.


3

You may also want to consider why not to use throw / return: Why not use throw All gas is consumed, everything reverted Impossible to tell callers why the call failed Errors cannot be caught, so they cannot be handled gracefully Why not use return It may not be clear to callers that the function can unsuccessfully run. This can lead to disastrous ...


3

Since I have only 2300 gas available I can't call another contract that will make a log. Is it correct? The basic cost for calling another contract is 700 gas (cost of CALL opcode). So it's probably possible to call another contract to do the logging, but that extra level of indirection might just be clutter. What's not possible is writing to storage, ...


3

The modifier inState(State _state) is basically an assertion insuring that before the actual function runs (represented by the _ in the modifier's code), the current state of the contract is in the state given. It sounds to me like it's operating exactly as it should. It's another way of saying "this function (payOut) should only run if the contracts state ...


3

This discussion mostly matters in the context of a contract calling another contract. If the callee contract throws there is no catch in the caller contract in current EVM versions. Thus, throw error is impossible to recover if needed. But this is rarely needed in usual use cases. Using throw make it easier to see if the transaction had any error in a ...


Only top voted, non community-wiki answers of a minimum length are eligible