There currently isn't a clear signal that you've run out of gas. A log message is being added to some future release.
Currently what I do is check to see if gasSent == gasUsed. This requires your code to remember the amount of gas you sent on a particular transaction and wait for the transaction to be mined. If gasSent == gasUsed, you most likely ran out of gas. In my javascript code I throw an exception. This has saved me several embarrassing forum posts and quite a bit of time.
In theory the transaction might be mined if it takes exactly the amount of gas used. There's no way I can think of to figure that out right now, perhaps someone could add to this answer. If you are running that close to the edge of running out of gas you should probably be sending more gas anyways.
I offer gratis some code I used to extend web3 functionality that waits for a transaction to be mined by a local node. It uses promises but adapting it to callback style shouldn't be difficult if you don't want to use promises. I plan on extending this in the future to await consensus from a plurality of nodes but I probably won't share that.
You won't be able to copy and paste this code in your code if you haven't instantiated a log or made a helper function to see if a var is set. If you haven't done those already, you should...
It should be much smaller code to write this for contract-contract calls, so I won't show that example. Same concept - just check to see if gasSent == gasUsed.
(And yes, Promise aficionados, I'm using a promise anti-pattern. I just haven't gotten around to rewriting it. The functionality is correct.)
Object.getPrototypeOf(web3.eth).awaitConsensus = function(txhash, gasSent) {
var deferred = Promise.pending();
ethP = this;
filter = this.filter('latest'); // XXX make async
callstack = new Error().stack;
filter.watch(function(error, result) {
// this callback is called multiple times, so can't promise-then it
ethP.getTransactionReceiptAsync(txhash).then(function(receipt) {
// XXX should probably only wait max 2 events before failing XXX
if (receipt && receipt.transactionHash == txhash) {
filter.stopWatching();
log.info({txreceipt: receipt});
if (js.isSet(gasSent)) {
// note corner case of gasUsed == gasSent. It could
// mean used EXACTLY that amount of gas and succeeded.
// this is a limitation of ethereum. Hopefully they fix it
if (receipt.gasUsed >= gasSent) {
log.error({ badReceipt: receipt });
log.error({ originalStack: callstack });
throw(Error("ran out of gas, transaction likely failed!"
+ callstack));
}
}
deferred.resolve(receipt);
}
});
});
return deferred.promise.timeout(60000, "awaitConsensus timed out after 60000ms")
.catch(function(e) {
log.error(e);
process.exit(1);
});
}
An easier to interpret trace can be seen here at ether.camp.
What happened is that the contract tried to call another contract, specifying a gas quantity of self.gas - 34050
. Since your execution had less than that much gas remaining at the time it was called, the result was a negative number, which translates into a very large positive number in unsigned arithmetic. It then attempted to make a call with that, and the EVM threw an exception because it was attempting to spend more gas than was available.
EVM exceptions result in all gas being consumed, and the transaction being rolled back.
Best Answer
Using etherscan blockchain explorer
In etherscan, look for the
TxReceipt Status
which will haveFail
in red, orSuccess
in green.Example of a failure: https://ropsten.etherscan.io/tx/0x67a5f6442f49a5da6ff8682250a8eef899d9dc0c5adf20b683709433902b5956
Using the receipt
eth.getTransactionReceipt(transactionHash)
will return astatus
field that has a value of0
when a transaction has failed and1
when the transaction has succeeded.Here's an example showing the
status
field:More details here.
Historical
To see if a transaction ran out of gas, you can input the transaction (hash) in https://live.ether.camp and then click on "VM Trace". (For the testnet Morden, use https://morden.ether.camp)
Or plug in the transactionHash in this url:
https://live.ether.camp/transaction/<transactionHash>/vmtrace#0
For the transaction mentioned in the question,
022f440fa96eb469363804d7b6c52321d4f409fa76578cdbdc5f04ff494b1321
here is the output https://live.ether.camp/transaction/022f440fa96eb469363804d7b6c52321d4f409fa76578cdbdc5f04ff494b1321/vmtrace#0
This transaction was out of gas immediately. Some transactions may run out of gas after doing some computations, and clicking on the Operations will show each step being performed and when the out of gas happens.