Warum prüft kompilierter Solidity-Code das Argument, mit dem er aufgerufen wurde?

Ich habe den folgenden Solidity-Code kompiliert:

pragma solidity ^0.4.9;
import "./Callee.sol";

contract Caller{
  function call(address callee_address){
    Callee callee = Callee(callee_address);
    callee.callee_function();
  }
}

Daraus wird die folgende EVM: http://pastebin.com/BeUPghsT

Ich verstehe das folgende Code-Snippet nicht. Nur der Code nach der Adresse 0x1c wird bei der Ausführung in das Bytearray des Vertrages kopiert. Daher sollten alle Adressen 0x1c niedriger sein als hier angegeben.

Address 0x1c
  PUSH1 0x60
  PUSH1 0x40
  MSTORE
  PUSH1 0x00
  CALLDATALOAD
Address 0x24
  PUSH29 0x0100000000000000000000000000000000000000000000000000000000
Address 0x42
  SWAP1
  DIV
  PUSH4 0xf55332ab
  EQ
  PUSH1 0x3a
  JUMPI
  JUMPDEST
  UNKNOWN OPCODE "0xFE"

Legt CALLDATALOAD das Adressargument (callee_address) auf den Stack? Wenn dies der Fall ist, wird anscheinend der unbekannte Opcode FE (eine Möglichkeit, die gesamte Ausführung zu stoppen?) aufgerufen, wenn die Adresse nicht die 0xf55332abersten vier Bytes hat. Ist das richtig verstanden?

Warum sollte die Adresse mit beginnen 0xf55332ab? Es gibt keine Prüfsummen in Ethereum-Adressen, richtig?

Verstehe ich richtig, dass hier ein Call-to-Function landet, oder ist das toter Code?

Ich würde vorschlagen, diese Ressource zu besuchen, um Smart Contract in Solidity-ähnlichen Code zu dekompilieren und mehr Informationen über Bytecode zu erhalten: ethervm.io
Diese Website scheint eine wirklich gute Ressource zu sein, wenn Sie die virtuelle Maschine verstehen möchten, die Ethereum Smart Contracts ausführt.

Antworten (1)

Die Codeausführung in EVM beginnt immer mit PC=0. Die aufgerufene Methode wird also in einem Schalter-ähnlichen Codesegment am Anfang des Bytecodes der EVM angesprungen.

CALLDATALOAD ist nicht das Argument, das der Funktion "call" gegeben wird. CALLDATALOAD ist die Funktionssignatur, die wie folgt berechnet wird, web3.sha3('call(address)').substr(0,10)wobei "call" der Name der Funktion in diesem Beispiel ist und "address" der Typ des Arguments (oder, wenn Sie so wollen, der Typ des Parameters) ist, das die Funktion akzeptiert. Und siehe da! web3.sha3('initNumbers()').substr(0,10)=0xf55332ab.

Daher wird 0xFE (der Halt) aufgerufen, wenn Sie etwas anderes als die Methode „call“ mit den richtigen Argumenten für diesen bereitgestellten Vertrag aufrufen. Mit anderen Worten: Der Vertragsstart-EVM fungiert als Switch-Anweisung, die Sie zur richtigen Methode innerhalb des Vertrags leitet. Diese Art von Struktur wird als Sprungtabelle bezeichnet.