[Ethereum] Error encountered during contract execution [Bad jump destination]

arrayscontract-debuggingcontract-developmentmapping

When calling to start() function in a Smart Contract, transaction fails with this message:

Warning! Error encountered during contract execution [Bad jump destination]

According to Error During Token Contract Execution … an invalid array index definitely generates this message. So I have been thinking about it, trying to figure out when my code is using an invalid index, but I can't find it.

This is the method requested:

function start(address seller, address thirdParty) returns (uint escrowId) {
    escrowId = numEscrows;
    numEscrows++;
    escrow e;
    e.thirdParty = thirdParty;
    e.seller = seller;
    e.buyer = msg.sender;
    e.amount = msg.value;
    e.recipient = seller;
    e.status = 1; // started

    escrows[escrowId] = e;

    return escrowId;
}

The only array there is escrows[] declared as mapping (uint => escrow) escrows;

After trying different things, I came to conclusion that problem surely is located at last line: escrows[escrowId] = e;

Is not possible to make such an assignment escrows[0] = e;? Why not?

What am I doing wrong? How can I debug it?

Best Answer

start(...) and start1(...) are two ways you can rewrite your function to work as expected:

pragma solidity ^0.4.0;
contract Ballot {
    struct Escrow {
        address thirdParty;
        address seller;
        address buyer;
        uint amount;
        address recipient;
        uint status;
    }
    uint numEscrows;
    mapping (uint => Escrow) escrows;

    function start(address seller, address thirdParty) returns (uint escrowId) {
        escrowId = numEscrows;
        numEscrows++;
        Escrow memory e;
        e.thirdParty = thirdParty;
        e.seller = seller;
        e.buyer = msg.sender;
        e.amount = msg.value;
        e.recipient = seller;
        e.status = 1; // started

        escrows[escrowId] = e;

        return escrowId;
    }

    function start1(address seller, address thirdParty) returns (uint escrowId) {
        escrows[numEscrows].thirdParty = thirdParty;
        escrows[numEscrows].seller = seller;
        escrows[numEscrows].buyer = msg.sender;
        escrows[numEscrows].amount = msg.value;
        escrows[numEscrows].recipient = seller;
        escrows[numEscrows].status = 1; // started
        numEscrows++;
        return numEscrows;
    }
}

And here is the Solidity realtime compiler and runtime screen showing that both start(...) and start1(...) execute without throwing an exception:

enter image description here

Note that start1(...) costs less gas than start(...).

In start(...), I added the memory keyword - see What is the memory keyword? What does it do?, Difference between Memory and Storage? and What does the keyword "memory" do exactly? for further information.

In your question, you mentioned "The only array there is escrows[] declared as mapping (uint => escrow) escrows;". Note that arrays are different from mappings - see Arrays vs Mappings and Store data in mapping vs. array.