Array Testing in Ethereum – Issues with Key/Value Existence

erroretherexceptionsinvalid-opcode

I have a problem with the following contract.
When I deploy it, normally on calling the function addBalance() it should go into the false. But instead, it completely does not work and I get the following message. What's wrong?

VM error: invalid opcode. invalid opcode The execution might have
thrown. Debug the transaction to get more information.

How can I find out if a key does not exist?

Contract:

pragma solidity ^0.4.24;

contract MembersContract {

    struct Member {
        uint balance;
        address member;
        bool exists;
    }

    Member[] public members;

    constructor() public {
        members.push(Member(0, 0x0, true));
    }

    function addbalance(uint _balance) public returns(bool _success){
        if(members[1].exists == true) {
            members[1].balance = 400;
        }
        else {
            return false;
        }
    }


}

Best Answer

Have a look here: Are there well-solved and simple storage patterns for Solidity?

You could.

function isMember(uint index) public view returns(bool isIndeed) {
  return members[index].exists;
}

It's preferable to throw an error on an unacceptable state change rather than return false in most situations. So ...

function addBalance(uint index) public returns(bool success) {
  require(isMember(index);
  members[index] += msg.value; // (or _balance if you prefer)
  return true;
}

If there is a good reason to return false and carry on:

function addBalance(uint index) public returns(bool success) {
  if(!isMember(index) return false;
  if(isMember(index)) member[index] += msg.value;
  return true;
}

In my opinion it's almost always better to use the member address as the key instead of storing the structs in numbered rows. Like that, using arbitrary amounts instead msg.value as in your example:

pragma solidity ^0.4.24;

contract MembersContract {

    struct Member {
        uint balance;
        bool exists;
    }

    mapping(address => Member) public members;

    function isMember(address member) public view returns(bool isIndeed) {
        return members[member].exists;
    }

    function addMember(address member) public returns(bool success) {
        require(!isMember(member));
        members[member].exists = true;
        return true;
    }

    function addBalance(address member, uint amount) public returns(bool success){
        require(isMember(member));
        members[member].balance += amount;
        return true;
    }
}

Hope it helps.

Related Topic