Das Folgende ist eine Vereinfachung des Problems, mit dem ich konfrontiert bin;
pragma solidity 0.4.18;
contract ValueSetter {
struct BasicValue {
uint256 value;
}
address my_address; // Just for the require later
BasicValue fixed_value;
mapping(address => BasicValue) fixed_values;
function ValueSetter(address init_address) public {
my_address = init_address;
fixed_values[init_address] = fixed_value;
}
function set_value(uint256 my_value) external {
// Just to prove that the bug isn't in my calling params
require(msg.sender == my_address && my_value != 0);
fixed_values[msg.sender].value = my_value;
assert(fixed_value.value != 0);
}
}
set_value
Wenn ich mit einem Wert ungleich Null anrufe , drücke ich auf die Bestätigung. Es sieht so aus, als ob das Problem darin besteht, dass in dieser Zeile
fixed_values[msg.sender].value = my_value;
Mein Versuch, der Struktur innerhalb der Zuordnung zuzuweisen, weist nicht der in gespeicherten Struktur zu fixed_value
. Ich habe stattdessen auch Folgendes versucht;
BasicValue storage basic_val = fixed_values[msg.sender];
basic_val.value = my_value;
Das ändert aber nichts am Ergebnis. Ich habe in der Solidity-Dokumentation gelesen , dass
Zuweisungen zwischen Speicher und Speicher und auch zu einer Zustandsvariablen (auch von anderen Zustandsvariablen) erzeugen immer eine unabhängige Kopie
Wenn das der Fall ist, wie kann ich dann die Struktur "aus" der Zuordnung herausholen, um sie lokal zu verwenden?
(Anmerkungen: Der obige Vertrag sieht so aus, als würde er lächerlich kompliziertere Dinge tun, als er müsste, weil der echte Vertrag mehr Anforderungen hat. Zum Beispiel gibt es mehr als ein Attribut in der Struktur, es wird mehr als eine Struktur bei der Initialisierung deklariert, es gibt mehr als eine Struktur in der Zuordnung, und ich muss Logik ausführen, die mehr als eine von ihnen umfasst.)
Diese Zeilen sind unnötig
BasicValue fixed_value;
fixed_values[my_address] = fixed_value;
aber das eigentliche problem wäre diese linie
assert(fixed_values[msg.sender].value != 0);
weil Sie die Struktur an diesem Index wollen.
pragma solidity 0.4.18;
contract ValueSetter {
struct ValueStruct {
uint256 value;
}
address public my_address; // Just for the require later
mapping(address => ValueStruct) public valueStructs;
function ValueSetter() public {
my_address = msg.sender;
}
function set_value(uint256 my_value) external {
// this shows the function is called by the deployer account
require(msg.sender == my_address && my_value != 0);
// this stores a uint in the .value element of the ValueStruct
// stored in the mapping at the index which is the sender
valueStructs[msg.sender].value = my_value;
// this just gets confirms the value is where we put it
assert(valueStructs[msg.sender].value != 0);
}
}
Ich hoffe es hilft.
Ja, alle Zustandsvariablen werden vorehelich in der Blockchain gespeichert. Aber um zu Ihrem qus zu kommen, warum:
function ValueSetter(address init_address) public {
my_address = init_address;
fixed_values[init_address] = fixed_value;
}
Im obigen Code initialisieren Sie fixed_values[init_address] = fixed_value;
also intern fixed_value = BasicValue(0)
und dies wird zugewiesenfixed_values[init_address] = fixed_value;
Intern sieht Ihr Code so aus:
function ValueSetter(address init_address) public {
fixed_value = BasicValue(0);
my_address = init_address;
fixed_values[init_address] = fixed_value;
}
Und zu Ihnen kommend gibt es einen Logikfehler:
function set_value(uint256 my_value) external {
// Just to prove that the bug isn't in my calling params
require(msg.sender == my_address && my_value != 0);
fixed_values[msg.sender].value = my_value;
assert(fixed_value.value != 0);
}
Gemäß meiner Erklärung ist fixed_value.value Null. Assert wird fehlschlagen. Und Ihre Transaktionen werden auf den vorherigen Zustand zurückgesetzt. Der aktuelle Wert wird nicht in der Blockchain gespeichert. Die Transaktion wird jedoch als Fehler in der Kette aufgezeichnet.
Also modifizierter Code: Pragma solidity 0.4.18;
contract ValueSetter {
struct BasicValue {
uint256 value;
}
address my_address; // Just for the require later
BasicValue fixed_value;
mapping(address => BasicValue) fixed_values;
function ValueSetter(address init_address) public {
my_address = init_address;
fixed_values[init_address] = BasicValue(1000);
}
function set_value(uint256 my_value) external {
// Just to prove that the bug isn't in my calling params
require(msg.sender == my_address && my_value != 0);
fixed_values[msg.sender].value = my_value;
//assert(fixed_value.value != 0);
}
}