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;
}
}
}
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.value
wie 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.
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!
membersLength
da drin?
dkb