Array-Werte testen, wenn Schlüssel/Wert vorhanden ist - Funktioniert nicht

Ich habe ein Problem mit folgendem Vertrag. Wenn ich es einsetze, sollte es normalerweise beim Aufrufen der Funktion addBalance() in den Wert false gehen. Aber stattdessen funktioniert es überhaupt nicht und ich bekomme die folgende Meldung. Was ist falsch?

VM-Fehler: Ungültiger Opcode. ungültiger opcode Die Ausführung wurde möglicherweise ausgelöst. Debuggen Sie die Transaktion, um weitere Informationen zu erhalten.


Wie kann ich herausfinden, ob ein Schlüssel nicht existiert?

Vertrag:

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;
        }
    }


}

Antworten (3)

Schau mal hier: Gibt es gut gelöste und einfache Speichermuster für Solidity?

Sie könnten.

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

In den meisten Situationen ist es vorzuziehen, bei einer inakzeptablen Zustandsänderung einen Fehler auszulösen, anstatt false zurückzugeben . So ...

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

Wenn es einen guten Grund gibt, falsch zurückzugeben und fortzufahren:

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

Meiner Meinung nach ist es fast immer besser, die Mitgliedsadresse als Schlüssel zu verwenden, anstatt die Strukturen in nummerierten Zeilen zu speichern. Verwenden Sie stattdessen beliebige Beträge msg.valuewie in Ihrem Beispiel:

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;
    }
}

Ich hoffe es hilft.

Ich habe bereits die Antwort gepostet, die meine Probleme gelöst hat. In meinem Fall wurde es benötigt, um weiterzuarbeiten, wenn kein Schlüssel vorhanden war. Dann würde ich einfach das Array pushen. Aber da das nicht funktioniert, habe ich es mit Mappings versucht und das hat perfekt funktioniert. Ich wusste nicht, dass nur beim Mapping jeder mögliche Schlüssel einen Wert hat und dass Arrays einen Fehler werfen, wenn sie nicht existieren. Trotzdem danke! :)

Der Array-Zugriff wird in Solidity geschützt. Wenn Sie versuchen, über das Ende des Arrays hinaus zu lesen, erhalten Sie einen ungültigen Opcode-Fehler.

Wenn Sie diese Bedingung selbst abfangen möchten, können Sie zuerst eine Begrenzungsprüfung durchführen:

if (members.length > 1 && members[1].exists) {
    ...
}

Perfekte Lösung gefunden:

pragma solidity ^0.4.24;

contract MembersContract {

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

    mapping(uint => Member) public members;
    uint membersLength;

    constructor() public {
        members[0] = Member(100, 0x0, true);
    }

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


}

Bei Mappings bekomme ich für jede Zahl einen Wert. Danke!

Was macht membersLengthda drin?