When I send a transaction to call my contract, it's causing a bad JUMPDEST error. The Ethereum wiki says this error is caused when a JUMP instruction jumps to a location that wasn't marked as a jump destination. Since I wrote my contract in Solidity, shouldn't it be impossible to generate bad code?
2 Answers
Malformed instructions are only one cause of bad JUMPDEST errors. The far more likely cause is an exception while calling another contract. When you call another contract in Solidity, it compiles in a check to see if an error occurred in the call. If an error occurred, the transaction needs to be rolled back by causing another error. The Solidity compiler intentionally forces a bad JUMPDEST error when contract calls fail.
The particular error in the failed call could be any VM exception. The most common exception is running out of gas. (When you get a transaction error, you should always retry with the maximum amount of gas. Don't use any less gas until you're preparing for people to use your code with real money.) Other likely possibilities are stack overflow and stack underflow. In rare cases, it could be an invalid instruction or an actual bad JUMPDEST, but those shouldn't happen if you're using Solidity to generate your bytecode.
For more details on why and how Solidity forces a bad JUMPDEST when a contract call fails, Martin Swende's explanation is the source of my information.
In addition to out of gas, from Solidity 0.4 onwards a common cause is sending ether to a contract that's missing the payable
modifier:
Functions that want to receive Ether have to specify the new payable modifier (otherwise they throw).
Examples of specifying payable
:
function() payable {...}
.function foo() payable returns (uint) {...}
.