Wie konvertiert man eine Adresse in Solidity in Bytes?

Was ist der empfohlene Weg, um ein addressin bytesSolidity umzuwandeln?

Antworten (6)

Um noch effizienter zu sein:

function toBytes(address a) public pure returns (bytes memory b){
    assembly {
        let m := mload(0x40)
        a := and(a, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF)
        mstore(add(m, 20), xor(0x140000000000000000000000000000000000000000, a))
        mstore(0x40, add(m, 52))
        b := m
   }
}

Benötigt nur 695 Gas gegenüber 2500 für Gokulnaths Antwort und 5000 für Eths

Bearbeiten für Solidität ^ 0.5.0:

Dies ist fast genauso effizient und viel besser lesbar:

function toBytes(address a) public pure returns (bytes memory) {
    return abi.encodePacked(a);
}
Das ist großartig!
Funktioniert das immer noch in Solidity ^0.5.0?
Mit einigen geringfügigen Syntaxänderungen, ja

Hier ist mein winziger Einzeiler für addressdie bytes32Konvertierung:

bytes32(uint256(uint160(addr)) << 96);

Wenn Sie bytesanstelle von benötigen bytes32:

abi.encodePacked(addr)
Dies beantwortet eine andere Frage, weil bytessich von unterscheidet bytes32.
Beachten Sie auch, dass dadurch die bytes32 rechts aufgefüllt werden . Normalerweise paddeln wir in Ethereum nach links . Lassen << 96Sie dazu einfach das aus.
Diese Antwort funktioniert heute nicht. Es sagt, dass der Adresstyp nicht in uint konvertiert werden kann.
@YulePale, behoben!

Es gibt keine aktuellen Verknüpfungen und Sie müssen Ihre eigene Funktion schreiben.

Hier ist die vom Autor von Solidity, Chriseth, vorgeschlagene Funktion:

function toBytes(address x) returns (bytes b) {
    b = new bytes(20);
    for (uint i = 0; i < 20; i++)
        b[i] = byte(uint8(uint(x) / (2**(8*(19 - i)))));
}
Wenn Sie eine Adresse in einen String konvertieren möchten, können Sie die Bytes einfach durch explizite Konvertierung in einen String konvertieren, asstring(b)
Diesen Fehler in der Browsersolidität erhalten:Error: Type string memory is not implicitly convertible to expected type string storage pointer.
@koampapapa Ich habe mir das angesehen und Ihre Frage beantwortet ethereum.stackexchange.com/questions/8346/… Wenn es wirklich nötig ist, ziehen Sie in Betracht, Konvertierungen in der Benutzeroberfläche/im Frontend/Javascript anstelle von Solidity durchzuführen, um Gas zu sparen.
Können wir später bytes(b) konvertieren bytes32, um es im bytes32Format zu speichern? @eth
@alper Es wäre besser, die Adresse direkt in a umzuwandeln bytes20, was überall dort funktioniert, wo Sie es verwenden möchten bytes32.
Um es als zu bytes32verwenden, könnte ich so etwas tun: bytes memory b = toBytes(a); assembly { result := mload(add(b, 32)) } @eth

Hier ist eine einzeilige Lösung.

abi.encodePacked(addr)

Es ist einfach und kostet wenig

Willkommen beim Ethereum Stack Exchange! Es ist verlockend, eine kurze Antwort zu schreiben, aber zu kurz ist nicht hilfreich. Was bedeutet zum Beispiel „wenig kosten“? Gibt es einen Vergleich von Gas im Vergleich zur akzeptierten Antwort? Für welche Versionen von Solidity kann dies verwendet werden?

Dies ähnelt der oben gegebenen Antwort, ist jedoch gaseffizienter als bei der Montage.

  function addressToBytes(address i)  returns (bytes by) { 
    by = new bytes(20); 
    assembly { 
      let count := 0 
      let byptr := add(by, 32) 
      loop: 
          jumpi(end, eq(count, 20)) 
          mstore8(byptr, byte(add(count,12), i)) 
          byptr := add(byptr, 1) 
          count := add(count, 1) 
          jump(loop) 
      end: 
    } 
    return by; 
  }
Es ist wirklich überhaupt keine Schleife erforderlich, da wir es mit < 32 Bytes zu tun haben
Ja, es ist keine Schleife erforderlich. Gut.

Anstatt zu versuchen, die Adresse in Rohbytes umzuwandeln, ist es oft einfacher, die ABI-Codierung zu verwenden. Die ABI-Codierung ist keine rohe Byte-zu-Byte-Übersetzung, sondern fügt ihre eigenen Markierungsbytes zu separaten Feldern hinzu. Sie können dies jedoch mit einer integrierten Funktion durchführen.

In Solidität


 /**
   * A test method exposed to be called from clients to compare that ABI packing and hashing
   * is same across different programming languages.
   *
   * Does ABI encoding for an address and then calculates KECCAK-256 hash over the bytes.
   *
   * https://web3js.readthedocs.io/en/v1.2.0/web3-utils.html#soliditysha3
   *
   */
  function calculateAddressHash(address a) public pure returns (bytes32 hash, bytes memory data) {

    // First we ABI encode the address to bytes.
    // This is so called "tight packing"
    // https://web3js.readthedocs.io/en/v1.2.0/web3-utils.html#soliditysha3
    bytes memory packed = abi.encodePacked(a);

    // Then we calculate keccak256 over the resulting bytes
    bytes32 hashResult = keccak256(packed);

    return(hashResult, packed);
  }


In JavaScript/TypeScript

  import { soliditySha3 } from 'web3-utils';

  // Sign address
  const { signature, v, r, s } = signAddress(user2);

  // This is an address is a hexadecimal format
  const ourData = user2.toLowerCase();

  // https://web3js.readthedocs.io/en/v1.2.0/web3-utils.html#id23
  // Convert address to bytes using "tight packing"
  // and them calculates keccak-256 over the resulting bytes
  const ourHash = soliditySha3({t: 'address', v: user2 });

  // We hash data in similar in TypeScript and Solidity
  const { hash, data } = await tokenSwap.calculateAddressHash(user2);
  assert(ourData.toLowerCase() == data.toLowerCase());
  assert(ourHash.toLowerCase() == hash.toLowerCase());
Dies mag für diejenigen klar sein, die bereits wissen, was Sie tun, aber das Hinzufügen einiger Beispiele würde dazu beitragen, dies für diejenigen klarer zu machen, die dies nicht tun.