web3.eth.getStorageAt für die Zuordnung

Wie erhalte ich Contract-Mapping-Speicher?

In Anbetracht dieses einfachen Vertrages

contract Currency{
 mapping(address=>uint) public balances;

   function deposit(){
      balances[tx.origin]++;
   }
}

Nach dem Bereitstellen und Aufrufen der Einzahlung möchte ich einen Vertragsspeicher erhalten

eth.getStorageAt("0x681afcc842a1a01f34ffb2c091e576aa78175d55",0)

aber immer das gleiche Ergebnis: 0x000000000000000000000000000000000000000000000000000000000000

auch wenn currency.balances.call(...) den korrekten Kontostand zurückgibt

Gibt es eine Möglichkeit, die gesamte Saldenkarte abzurufen?

Antworten (5)

Guthaben ist öffentlich, Sie erhalten das Guthaben von dort.

Über die Speicherung: Die Adresse ist nicht der Schlüssel (obwohl es eine Geschichte zu diesem speziellen Problem gibt: https://www.pivotaltracker.com/story/show/85010830 ). Dokumente zum Abrufen der Speicheradresse einer Variablen finden Sie hier: http://solidity.readthedocs.org/en/latest/miscellaneous.html#layout-of-state-variables-in-storage

Über das Iterieren über die Karte: Sie können dies nicht tun, ohne Code hinzuzufügen, wie es hier getan wird: https://github.com/ethereum/dapp-bin/blob/master/library/iterable_mapping.sol

Die andere Alternative ist, wenn es keinen anderen Speicher gibt, können Sie technisch alle Werte abrufen, indem Sie den Zustand versuchen, aber es hasht jetzt standardmäßig alle Schlüssel (glaube ich), also wären Schlüssel schwierig.

Mit der Inline-Assemblierung können Sie an eine beliebige Speicheradresse schreiben, was bedeutet, dass es viel einfacher ist, direkt aus dem Speicher zu lesen.

Abruf über Vertrag

Ich bin mir nicht sicher, ob dies die gesuchte Antwort ist, aber Sie können eine Methode schreiben, die ein Array zurückgibt. Der Abruf (und keine Transaktion) des Vertrags ist derzeit kostenlos, und in Zukunft können Sie immer noch Speichereinträge abrufen und Ihre eigene VM ausführen.

Eindimensionale Arrays funktionieren gut, 2D-Arrays kommen später, denke ich. Sie können entscheiden, wie es formatiert werden soll – ein einfacher Weg könnte sein: [ address1, balance1, address2, balance2, ... ]

Es ist wichtig zu beachten, dass es keine Vorstellung gibt, dass eine bestimmte Zuordnung leer ist. Sie müssen basierend auf Ihren Bedingungen entscheiden, wie Sie das Mapping iterieren. Weitere Informationen finden Sie in der Solidity-Dokumentation .

Speicher direkt parsen

Sie können Speichereinträge über RPC mit dem getStorageAt -Aufruf abrufen. Es besteht keine Notwendigkeit, manuell mit dem Trie zu interagieren.

Um die Speicherung (Einträge) direkt zu analysieren, müssten Sie wissen, wie die verwendete Sprache die Speicherung organisiert, und dies hängt vom Quellcode und möglicherweise auch von der Compiler-Version ab.

Dieser mittlere Artikel erklärt sehr gut, wie man auf ein Mapping zugreift, siehe Abschnitt Index 5 — uints1 :

Mappings haben eine andere Indizierung und sollten anders gelesen werden. Um den Zuordnungswert zu lesen, sollten Sie den Schlüsselwert kennen. Andernfalls ist das Lesen des Zuordnungswerts nicht möglich.

index = '0000000000000000000000000000000000000000000000000000000000000005'
key =  '00000000000000000000000xbccc714d56bc0da0fd33d96d2a87b680dd6d0df6'
let newKey =  web3.sha3(key + index, {"encoding":"hex"})
console.log(web3.eth.getStorageAt(contractAddress, newKey))
console.log('DEC: ' + web3.toDecimal(web3.eth.getStorageAt(contractAddress, newKey)))
result:
0x0000000000000000000000000000000000000000000000000000000000000058
DEC: 88

Quelle: https://medium.com/aigang-network/how-to-read-ethereum-contract-storage-44252c8af925

Angenommen, Ihr Code wurde mit Standard-Solidity kompiliert (keine Nachoptimierung oder Verschleierung), werden die Werte in balancesunter der Speicheradresse gespeichert KECCAK256(CONCAT(N, key_in_balances)). (Hier ist N=0, weil balancesdas erste Vertragsattribut ist.)

Daher wird getStorageAt()Ihnen nicht geholfen, es sei denn, Sie kennen die Adresse der Brieftasche, die Sie abfragen möchten. balancesDas bedeutet auch, dass Sie mit dieser Methode nicht aufzählen können.

Wie Andreas in seiner Antwort sagte, besteht die einzige Möglichkeit, dies möglicherweise zu tun, darin, den Zustandsversuch des Vertrags manuell zu analysieren. Der beste Ausgangspunkt ist wahrscheinlich, einen bestehenden Client zu forken. Die einfachere Python-Implementierung ist wahrscheinlich am besten für diese Art von Experimenten geeignet.

Ab sofort, um Mapping aus dem Speicher abzurufen,

    // . symbols that hash together. do not put . between
    hashValue= keccak256(key . slot) // hashed together

In Ihrem Vertrag wird die Zuordnung im ersten Slot gespeichert, sodass der Index 0 ist.

Sie können den Its Keccak von Online-Keccak erhalten. Stellen Sie sicher, dass der Eingabetyp Hex sein muss.

  web3.eth.getStorageAt('addressOfContract','hashValue')