2

I have a simple contract that contains a struct. First, I initialize it using certain values and at some point I want to change them, in this case with setCompleted. However, the changes do not get stored permanently and completed property is still stored as false even after setting it to true in setCompleted function. What could be the issue?

pragma solidity ^0.4.15;

contract MyStructExample {
    struct MyStruct {
        address addr;
        string description;
        bool completed;
    }

    address owner;
    mapping (address => mapping(string => MyStruct)) myStructs;

    // MyStructExample.deployed().then(function(instance) {app=instance;})
    function MyStructExample() {
        owner = msg.sender;
    }

    // app.setMyStruct("0xe38d0b841dd19802b429b85c41d597e4c29d88e1", "Blah blah")
    function setMyStruct(address _addr, string _description) {
        MyStruct storage myStruct;

        myStruct.addr = _addr;
        myStruct.description = _description;
        myStruct.completed = false;

        myStructs[myStruct.addr][myStruct.description] = myStruct;
    }

    // app.getMyStruct.call("0xe38d0b841dd19802b429b85c41d597e4c29d88e1", "Blah blah")
    function getMyStruct(address _addr, string _description) constant returns (address, string, bool) {
        MyStruct memory myStruct = myStructs[_addr][_description];
        return (myStruct.addr, myStruct.description, myStruct.completed);
    }

    // app.setCompleted.call("0xe38d0b841dd19802b429b85c41d597e4c29d88e1", "Blah blah")
    function setCompleted(address _addr, string _description) onlyOwner returns (bool) {
        myStructs[_addr][_description].completed = true;

        return myStructs[_addr][_description].completed;
    }

    modifier onlyOwner() {
        assert(msg.sender != owner);
        _;
    }

    function kill() onlyOwner { 
        selfdestruct(owner);
    }
}
  • 2
    Try removing the .call in setCompleted. Otherwise it only calls it in local EVM instead of sending a TX – libertylocked Nov 13 '17 at 11:25
  • 1
    Replace .call with this app.setCompleted("0xe38d0b841dd19802b429b85c41d597e4c29d88e1","Blah blah"); call does not changes the state / it will not persist your changes . – Rangesh Nov 13 '17 at 11:28
5

Your problem is that you're calling setCompleted with .call. It runs the function in your local EVM instead of sending a TX to call the contract. If you replace that with just .setCompleted it should work.

Some details on calling functions in web3, as copied from one of my previous answers


Currently there are 3 ways to "call" a contract function in web3.

  • You can call it with myContractInstance.foo.call(), which web3 will execute the contract code locally (since the bytecode is visible to all blockchain participants). It returns you the return value by running the function locally. It won't craft a tx, won't submit anything to the network. There is no message.
  • You can call it with myContractInstance.foo.sendTransaction(), which web3 will send a tx to call the function. It returns you a tx hash. You will have to pay for gas, wait for the tx to be mined, then you get your tx receipt. Note that this way you won't get the return value of the function, because they aren't included in the tx receipt. However logs are in the tx receipt.
  • You can just call with myContractInstance.foo(). If your function is constant, then web3 will use .call. If it's not constant, it will use .sendTransaction

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.