Ich versuche, einen supereinfachen Vertrag zu schreiben, der gaseffizient ist und Inline-Montage in Solidität verwendet. Alles, was diese Funktion tun muss, ist, einen intelligenten Kindervertrag mit einer Funktion zu erstellen, der Selbstzerstörung. Die Funktion sollte auch msg.sender überprüfen, um sicherzustellen, dass es sich um den Vertragseigentümer handelt. Dieses GasToken-Projekt tut dies in einer Form, in der sie das effektiv gespeicherte Gas tokenisiert haben. Sie brachten es auf eine andere Ebene, wo sie auch eine Vanity-Adresse verwendeten, um dies noch sparsamer zu machen. Ich habe versucht, eine Vanity-Adresse zu generieren, damit ich ihren Code genau verwenden kann, aber es dauert extrem lange, also habe ich darauf zurückgegriffen, den Code so zu ändern, dass ich es mit einer normalen Adresse und nicht mit einer Vanity-Adresse mit 10 machen kann führende Nullen. Lassen Sie uns für den Zweck dieser Frage also keine Eitelkeitsrede halten.
Vertrag Pseudocode:
if (msg.sender != 0x1234....5678) { throw; }
suicide(msg.sender)
Wie kann ich dies in Inline-Assembly in Solidität schreiben? Hier ist die Quelle für gasToken.io, wo sie die Vanity-Adresse verwendet haben . Ich möchte die Vanity-Adresse vorerst NICHT verwenden, um meinen Code zu vereinfachen, da diese Art von Vanity-Adresse ohne Mining-Hardware schwer zu generieren ist. Ich habe auf Solidity-Opcodes verwiesen , konnte dies jedoch nicht erfolgreich zum Laufen bringen.
// Creates a child contract that can only be destroyed by this contract.
function makeChild() internal returns (address addr) {
assembly {
// EVM assembler of runtime portion of child contract:
// ;; Pseudocode: if (msg.sender != 0x0000000000b3f879cb30fe243b4dfee438691c04) { throw; }
// ;; suicide(msg.sender)
// PUSH15 0xb3f879cb30fe243b4dfee438691c04 ;; hardcoded address of this contract
// CALLER
// XOR
// PC
// JUMPI
// CALLER
// SELFDESTRUCT
// Or in binary: 6eb3f879cb30fe243b4dfee438691c043318585733ff
// Since the binary is so short (22 bytes), we can get away
// with a very simple initcode:
// PUSH22 0x6eb3f879cb30fe243b4dfee438691c043318585733ff
// PUSH1 0
// MSTORE ;; at this point, memory locations mem[10] through
// ;; mem[31] contain the runtime portion of the child
// ;; contract. all that's left to do is to RETURN this
// ;; chunk of memory.
// PUSH1 22 ;; length
// PUSH1 10 ;; offset
// RETURN
// Or in binary: 756eb3f879cb30fe243b4dfee438691c043318585733ff6000526016600af3
// Almost done! All we have to do is put this short (31 bytes) blob into
// memory and call CREATE with the appropriate offsets.
let solidity_free_mem_ptr := mload(0x40)
mstore(solidity_free_mem_ptr, 0x00756eb3f879cb30fe243b4dfee438691c043318585733ff6000526016600af3)
addr := create(0, add(solidity_free_mem_ptr, 1), 31)
}
}
Ich bin kein EVM-Assembler-Assistent, noch habe ich die Umgebung eingerichtet, um dies zu testen und für Sie zu debuggen - aber ich werde versuchen, einige Ratschläge / Ideen zu geben, wie ich dies tun würde. Die Kommentare in der Versammlung sind großartig, um uns durch das zu führen, was vor sich geht, also gehen wir sie durch.
Die Schritte, die ich in den Kommentaren sehe:
Gehen wir also die Schritte durch und sehen, was wir ändern müssen
Bauen Sie das Kind asm
Im ersten Teil (Definition des untergeordneten asm) sehe ich ein paar Dinge, die wir ändern müssen (meine hinzugefügten Kommentare in <>):
// EVM assembler of runtime portion of child contract:
// ;; Pseudocode: if (msg.sender != 0x1234....5678) { throw; }
// ;; suicide(msg.sender)
<It was PUSH15 before because their vanity address only had 15 bytes of non0 data>
<A normal ETH address has 20 bytes (40 hex characters)>
// <OLD>: PUSH15 0xb3f879cb30fe243b4dfee438691c04 ;; hardcoded address of this contract
// <NEW>: PUSH20 0xb3f879cb30fe243b4dfee438691c04 ;; hardcoded address of this contract
// <... The rest of this seems like it should still work>
Untergeordnetes asm in Bytes umwandeln
Sie können diese Site verwenden, um den Bytecode für jeden Opcode abzurufen. Da wir nur den ersten Opcode von PUSH15 (6e) auf PUSH20 (73) und die Bytes danach geändert haben, sollten wir in der Lage sein, diese einfach auszutauschen.
ALT: 6eb3f879cb30fe243b4dfee438691c043318585733ff
NEU: 73<1234....5678>3318585733ff
Beachten Sie, dass Ihre neue untergeordnete Laufzeit-ASM statt 22 Byte 27 Byte groß sein sollte (5 mehr für Ihre längere Adresse).
Schieben Sie untergeordnete ASM-Bytes in den Initcode für den untergeordneten Vertrag
// PUSH27 0x73<1234....5678>3318585733ff
// PUSH1 0
// MSTORE ;; at this point, memory locations mem[10] through
// ;; mem[36] <added 5 bytes to the end here since your runtime is longer> contain the runtime portion of the child
// ;; contract. all that's left to do is to RETURN this
// ;; chunk of memory.
// PUSH1 27 ;; length <since your length is 27 not 22 now>
// PUSH1 10 ;; offset
// RETURN
Wandeln Sie den untergeordneten Initcode in einen Binärcode um
Ähnlich wie Schritt 2:
ALT: 756eb3f879cb30fe243b4dfee438691c043318585733ff6000526016600af3
7a) und ändern Sie PUSH1 22 zu PUSH1 27 (6016 zu 601b) NEU: 7a<73<1234....5678>3318585733ff>600052601b600af3
Jetzt sollten Sie in der Lage sein, dies in den ursprünglichen Code einzufügen mstore
.
Endlich
Auch hier bin ich nicht sicher, ob dies funktioniert, und habe es nicht getestet. Aber hoffentlich hat es Ihnen geholfen, ein Gefühl dafür zu bekommen, wie Sie diese Art von Problem lösen können!
Lampenschirm
Lampenschirm
Markus Toda
Markus Toda
Lampenschirm
Lampenschirm
Markus Toda