5

I have a contract that breaks after I add only the word "public" to a mapping. For reference, my contract is below:

contract VendingMachine {

event Unlocked(address machineID, address unlocker);
event MachinePayed(address machineID, uint amount);
event CustomerPayed(address customer, uint amount);

address admin;

struct Machine {
    bool exists;
    bool isFunded;
    address owner;
    address currentBuyer;
    uint minFunding;
    uint escrowBalance;
}

mapping(address => Machine) public machines;

modifier onlyMachines() {
    if (machines[msg.sender].exists)
    _
}

modifier onlyAdmin() {
    if (msg.sender==admin)
    _
}

function () { throw; }

function VendingMachine() {

    admin=msg.sender;
}

function fundMachine(address _machineID) {
    if (msg.value < machines[_machineID].minFunding)
    throw;
    machines[_machineID].currentBuyer=msg.sender;
    machines[_machineID].isFunded = true;
    machines[_machineID].escrowBalance = msg.value;
    Unlocked(_machineID, msg.sender);
}

function executePayment(uint _price) onlyMachines {
    machines[msg.sender].escrowBalance -= _price;
    machines[msg.sender].currentBuyer.call.value(machines[msg.sender].escrowBalance)();
    CustomerPayed(machines[msg.sender].currentBuyer, machines[msg.sender].escrowBalance);
    msg.sender.call.value(_price)();
    MachinePayed(msg.sender, _price);

    //reset machine
    machines[msg.sender].escrowBalance = 0;
    machines[msg.sender].isFunded = false;

}

function registerMachine(address _machineID, address _owner, uint _minFunding) onlyAdmin {
    machines[_machineID].exists = true;
    machines[_machineID].owner = _owner;
    machines[_machineID].minFunding = _minFunding;
}

function checkAdmin() returns (address){
return admin;
}
}

After deploying and getting the contract address in context with:

var myContract = contract.at(<returned address>)

I first register a contract:

myContract.registerMachine(eth.accounts[1],eth.accounts[2],400000000000,{from:eth.coinbase,gas:4000000})

This should set machines[eth.accounts[1]].exists to true, and set some of the other struct values...but intsead nothing happens and the rest of my contract can't execute. When I take change the mapping to remove the "public" visibility, it works perfectly and I am able to execute the rest of the calls and move ether around as needed.

If anyone can help explain why adding public breaks my contract so badly I'd be very grateful. Thanks

  • If you have the transaction hash returned from registerMachine you can try debug.traceTransaction (ethereum.stackexchange.com/a/4289). – Ismael Jul 1 '16 at 20:49
  • 1
    Thanks for the suggestion. I just did this and discovered that execution stopped after an error: error: "invalid jump destination (DUP2) 1197", – joeb000 Jul 1 '16 at 21:36
  • Maybe it is a bug in solidity, try with a different version of solc. Are you using a library? I'd get similar error when my contract and library didn't link correctly. – Ismael Jul 1 '16 at 21:40
  • 1
    "Invalid jump destination" typically means that the contract called "throw". – bortzmeyer Jul 2 '16 at 15:13
2

I've executed your contract with public on browser-solidity and had no errors. You should check if your tools are up to date...

enter image description here

  • My contract deploys just fine, the problem is running the registerMachine() method. I suspect that the admin address var isn't being set appropriately for some reason and its throwing on the call to onlyAdmin(). – joeb000 Jul 3 '16 at 2:41
  • And tested it out again with an added function to return admin address...it works (sets the admin properly) before I add public to the mapping, then it doesn't work after I add it (returns "0x" ) when i call for the admin. Please try this and let me know if it does the same for you! (I've edited the original source code to add the checkAdmin() method) – joeb000 Jul 3 '16 at 3:07

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.