Zugriff auf eine Zuordnungsvariable von web3

Gibt es eine Möglichkeit, auf eine Zuordnungsvariable zuzugreifen, z. B.:

mapping(bytes => bool) myMappingVar;

was NICHT ist:

  • Ausdrücklich öffentlich erklärt
  • ohne Verwendung einer indizierten ID
  • Auch wird keine entsprechende öffentliche Getter-Methode gesetzt

Zum Beispiel von web3:

contract.instance.methods.myMappingVar('somevalue').call();

Antworten (3)

Nicht bequem, aber Sie können über auf jeden Wert im Speicher eines Smart Contracts zugreifen web3.eth.getStorageAt. Unter https://solidity.readthedocs.io/en/develop/miscellaneous.html#layout-of-state-variables-in-storage finden Sie Einzelheiten zum Layout des Speichers.

Wenn Ihr mappingdie erste Zustandsvariable im Vertrag ist, also an Steckplatz 0, ruft dieser Code den Wert für den Schlüssel ab 0x123456.

var slot = "0".repeat(64);  // hex uint256 representation of 0
var key = "0x123456";  // hex representation of the key

web3.eth.getStorageAt(
  contractAddress,  // address of the contract to read from
  web3.sha3(key+slot, { encoding: 'hex' }),  // keccak256(k . p)
  function (err, result) {
    console.log(result);  // 00...0 for false, 00...1 for true, both 32 bytes wide
  }
);
Was ist der Steckplatz? Handelt es sich um einen Index der Mapping-Variablen?
"Slot" ist der Name, der der Position im Speicher gegeben wird, an der sich ein Wert befindet.
Ich verstehe nicht. Wie bekomme ich einen Slot für ein Mapping mit Schlüssel 'height' wie: ``` ['age': true, 'name': true, 'height': true] ``` siehe auch, meine Frage besagt ohne Verwendung oder unter der Annahme, dass Indizes ein bekannter Wert sind
Verwenden Sie einfach key = web3.fromAscii('height')den obigen Code.
Ich werde es versuchen! Danke. Aber was sollte der Wert für Slot sein? 0?
Es hängt davon ab, wo mappingsich das in Ihrem Solidity-Code befindet. Wenn es die erste Variable ist, dann ist der Steckplatz 0. Wenn nicht, müssen Sie wirklich die Dokumentation lesen, auf die ich verlinkt habe, um die Details zu erfahren.
OK habe es. Ich war in der Annahme, dass Slot sich auf einen Index für die Zuordnungsvariable bezieht

Sie können auf eine öffentliche Zuordnungsvariable wie auf eine normale öffentliche Variable zugreifen, mit der Ausnahme, dass Sie den Indexwert für die Zuordnung bereitstellen müssen .

Ich habe das folgende Beispiel gemacht, und es hat für mich funktioniert

In meinem Vertrag geschrieben mit Solidity


address public owner; 
mapping(uint8 => address) public incomingQueue;
mapping(address => string) public assignedName;

Nachdem ich die Vertragsadresse erhalten habe:

const contract = web3.eth.contract(abiArray).at(contract_address);

Ich kann auf diese Variablen mit dem folgenden web3-Javascript-Code zugreifen:


contract.owner.call(function(err, result){
     if(!err)
         alert(result)
 });
contract.incomingQueue.call(0, function(err, result){
     if(!err){
        alert(result)
     }
 });
contract.assignedName.call(web3.eth.accounts[0], function(err, result){
     if(!err){
        alert(result)
     }
 });
Mit dieser Methode erhalte ich den Fehler Kann Eigenschaft 'Aufruf' von undefiniert nicht lesen
Dies gilt für ältere Versionen von web3. Auf web3 Version 1.2 sollten Sie es als contract.methods.incomingQueue(0).call();

Aus Sicht des Information Hiding können Sie nicht von außen auf Felder zugreifen. Du brauchst eine Getter-Funktion. Wenn Sie den öffentlichen Modifikator im Mapping angeben, generiert Solidity eine Getter-Funktion für Sie.

Wie smarx in seiner Antwort erklärt, schützt dies Ihre Daten jedoch nicht davor, direkt aus dem Speicher gelesen zu werden.

Von außerhalb des EVM können Sie alles lesen, was in einem Smart Contract gespeichert ist.
Oh ... Sie gehen davon aus, dass die Frage aus der Perspektive der Datensicherung gestellt wird? Dann ist "Sie können von außen nicht auf Felder zugreifen" natürlich falsch.
Ich bin mir nicht sicher, was die Perspektive ist ... die Frage sagt nur "Gibt es einen Weg."
Ich stimme Ihrer Antwort zu, sobald ich mich von "Vox Populi" erholt habe. ;-)
Die Antwort von @smarx neigt eher zu einer möglichen Antwort.