Rufen Sie Rückdaten von Delegatecall ab

Ich verwende einen Delegiertenruf auf niedriger Ebene, um meine Anrufe an eine Bibliothek weiterzuleiten.

Ich muss (in dieser Reihenfolge):

  1. Lade bytes4 sig aus dem Speicher in _message

  2. Kopfgeld (STRUCT) aus dem Speicher in _message laden

  3. Lade Bytes _data in _message

  4. Delegiertenruf mit der neuen Nachricht

  5. Rückgabewerte abrufenDer Vertrag funktioniert (z. B. die getBounty-Funktion wird funktionieren), aber ich habe Probleme mit der Assemblierung in meiner forwarder()-Funktion. https://ethfiddle.com/po3wHGQraJ

Ich habe jedoch Probleme damit, dass mein Forwarder (in der Montage) richtig funktioniert.

  function forward(bytes32 _sig, bytes memory _data) public payable {
    bytes memory data = _data;
    bytes4 sig = bytes4(_sig);
    address _impl = impl;
    require(_impl != address(0));
    assembly {
      let _message := mload(0x40) //find empty memory location
      mstore(_message, sig) //place sig at beginning of empty storage
      //add _bounty
      mstore(add(_message, 4), sload(bounty_slot))
      //add _data
      calldatacopy(add(_message, 36), 100, sub(calldatasize,100))
      //mstore(add(_message, 36), data)
      let size := returndatasize
      let result := delegatecall(gas, _impl, _message, msize, 0, 0)
      //return data ??????
      returndatacopy(_message, 0, size)
      switch result
      case 0 {revert(_message, size) }
      default { return(_message, size) }
    }
  }

So sieht der Speicher aus:

0x00
0x687474703a2f2f6170692e6269746275636b65742e636f6d2f33303433303430
0xe1bb4acb579f780cbaf21cef9ac3641b8e3fcd69
0x5b7eaef7
0x3334303330340000000000000000000000000000000000000000000000000000
0x012a05f200
0x00
0x00
0x059ce9161d4fb0
0x00
0x00
0x00
0x00
0x00
0x00
0x00
0x00
0x00

Antworten (1)

Das returndatacopyist der richtige Ansatz, aber Sie haben ein Problem mit _data.

Die _dataVariable ist ein Zeiger auf den Speicher, da byteses sich um einen Array-Typ handelt. Sie müssen die Daten in den Meldepuffer kopieren.

Dies kann entweder erfolgen, indem Sie die Funktion extern machen und dann verwenden calldatacopy, oder Sie können eine Schleife verwenden, um Wort für Wort zu kopieren, oder Sie können den vorkompilierten Identitätsvertrag unter Adresse verwenden0x04

Das Problem mit calldatacopy ist, dass ich meinen Speicher vor den calldata noch verschlüsseln müsste. Ich bin mir nicht sicher, ob das so möglich ist? Ich muss also im Wesentlichen eine neue Nachricht in meiner Weiterleitungsfunktion erstellen, die aus Signature + Storage + Calldata besteht
calldatacopy kann überall im Speicher kopieren, einschließlich Kopieren direkt nach dem Speichern
Aber ich kann nicht einfach calldatacopy(_message, 0, calldatasize) machen, oder? Würde das nicht die dort bereits gespeicherten _sig und _bounty überschreiben? Hier sind alle Verträge für etwas mehr Kontext: gist.github.com/kyriediculous/fd070786ce981a64a981e73487ba73ec
calldatacopy(add(_message, 36), 100, sub(calldatasize,100))oder etwas ähnliches funktionieren sollte
Danke, ich glaube, jetzt komme ich zurecht. Cool, das hilft mir auf meinem Weg! Ich muss nur calldatacopy am 4. Byte (Ende der Signatur) aufteilen und meine _bounty dazwischen setzen. Ich werde heute Abend versuchen, etwas herauszufinden. Danke für die Hilfe!
Es wird immer noch ein leeres Array zurückgegeben :( ethfiddle.com/p0PdFSXF4v && ethfiddle.com/7_7N8SuhF2
sload(<position>) funktioniert also nicht, weil es eine Struktur ist. Das habe ich, glaube ich, herausgefunden.
Wenn Sie das Ganze herausgefunden haben, wäre es schön, wenn Sie eine Antwort mit dem, was Sie herausgefunden haben, posten könnten, um zukünftigen Benutzern zu helfen
Immer noch kämpfend :)
hast du das schon mal rausgefunden, hast das selbe problem?