Wie kann ich eine Zuweisung zu einer Struktur in einem Mapping beibehalten?

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_valueWenn 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.)

Antworten (2)

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