Wo wird String im Solidity-Speicher gespeichert?

Ich versuche zu überprüfen, wo eine Zeichenfolge im Speicher in Solidity gespeichert ist .

Zum Testen verwende ich diesen Code:

pragma solidity 0.5.4;

contract AssemblyString {
    string s; // slot 0

    function set(string calldata _s) external {
        s = _s;
    }

    function get(uint i) public view returns (bytes32){
        bytes32 r;
        assembly {
            r := sload(i) //we load the slot number i
        }
        return r;
    }
}

Wenn ich eine Zeichenfolge auf weniger als 31 Bytes setze, funktioniert dies einwandfrei, wie die Solidity angibt:

  1. Vertrag bereitstellen
  2. set("Äther")
  3. erhalten (0)

Ausgabe: 0x657468657200000000000000000000000000000000000000000000000000a

Der erste Teil steht für den codierten String : 0x6574686572 entspricht "ether".
Der zweite Teil ist die Größe*2 : 0xA entspricht 10 in Dezimalzahl. (Äther hat 5 Buchstaben, dann ist 5 mal 2 gleich 10)
Alle Nullen dazwischen werden aufgefüllt, um eine Länge von 32 Bytes zu erreichen.


Aber! Wenn ich eine Zeichenfolge mit mehr als 31 Bytes einstelle, kann ich die Zeichenfolge nicht finden.
Wie die Spezifikation sagt, sind die Daten des Strings im keccak256(slot) enthalten.

When I search for keccak256(0) = 044852b2a670ade5407e78fb2863c51de9fcb96542a07186fe3aeda6bb8a116d
To decimal : 1937035142596246788172577232054709726386880441279550832067530347910661804397

Ausgabe: 0x0

But if I debug the contract in Remix IDE , I found that the data is stored always in key 0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e563,
dec: 18569430475105882587588266137607568536673111973893317399460219858819262702947 and the string is stored at that position.

Was mache ich falsch?

Vielen Dank für Ihre Zeit.

Antworten (1)

Ich habe die Lösung gefunden!

Führen Sie dies in Javascript aus:

const utils = require('web3-utils'); // npm install web3
console.log(utils.soliditySha3(0x0))
>> 290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e563

Auch mit diesem Code in Solidität:

function test() public pure returns(bytes32){
    bytes memory a = new bytes(32);
    return keccak256(a);
}

Es klappt!