View Source Signet.Assembly (Signet v1.0.0-echo6)
A for-fun assembler of EVM assembly code from a simple lisp-like language used to construct Quark scripts.
This is really for fun and testing, so mostly feel free to ignore.
Usage
You can build EVM assembly, via:
Signet.Assembly.build([
{:log1, 0, 0, 55}
])
That results in the EVM compiled script 0x603760006000a1
.
If you view that here https://ethervm.io/decompile you see that it decompiles to:
log(memory[0x00:0x00], [0x37]);
via the assembly:
0000 60 PUSH1 0x37
0002 60 PUSH1 0x00
0004 60 PUSH1 0x00
0006 A1 LOG1
Overall, scripts can get more complex, e.g. we use a script
to revert if tx.origin
is zero (e.g. during an eth_estimateGas
).
Signet.Assembly.build([
{:mstore, 0, 0x01020304},
{:if, :origin, {:revert, 28, 4}, {:return, 0, 0}}
])
There's no real goal for this assembler. Just a fun experiment and useful in testing.
Summary
Functions
Assmbles opcodes into raw evm bytecode
Compiles and assembles assembly operations.
Compiles operations into assembly, which can then be compiled.
Returns a simple EVM program that returns the input code as the output of an Ethereum "initCode" constructor.
Disassembles opcodes from raw evm bytecode to opcodes.
Types
Functions
Assmbles opcodes into raw evm bytecode
Examples
iex> [{:push, 0, ""}, {:push, 4, <<0x11, 0x22, 0x33, 0x44>>}, :mstore, {:push, 1, <<4>>}, {:push, 1, <<28>>}, :revert]
...> |> Signet.Assembly.assemble()
<<95, 99, 17, 34, 51, 68, 82, 96, 4, 96, 28, 253>>
iex> [
...> {:push, 2, <<0x01, 0x02>>},
...> {:push, 1, <<0>>},
...> :mstore,
...> :callvalue,
...> {:push, 1, <<0>>},
...> :sub,
...> {:jump_ptr, 0},
...> :jumpi,
...> {:push, 1, <<2>>},
...> {:push, 1, <<30>>},
...> :revert,
...> {:jump_dest, 0},
...> {:push, 1, <<2>>},
...> {:push, 1, <<31>>},
...> :revert
...> ]
...> |> Signet.Assembly.assemble()
...> |> Signet.Hex.to_hex()
"0x6101026000523460000362000014576002601efd5b6002601ffd"
iex> [
...> {:dup, 2},
...> {:swap, 3},
...> {:invalid, ~h[0x010203]}
...> ]
...> |> Signet.Assembly.assemble()
...> |> Signet.Hex.to_hex()
"0x8192fe010203"
Compiles and assembles assembly operations.
Examples
iex> use Signet.Hex
...> [
...> {:mstore, 0, ~h[0x11223344]},
...> {:revert, 28, 4}
...> ]
...> |> Signet.Assembly.build()
...> |> to_hex()
"0x63112233446000526004601cfd"
Compiles operations into assembly, which can then be compiled.
Examples
iex> use Signet.Hex
...> [
...> {:mstore, 0, ~h[0x11223344]},
...> {:revert, 4, 28}
...> ]
...> |> Signet.Assembly.compile()
[{:push, 4, ~h[0x11223344]}, {:push, 1, <<0>>}, :mstore, {:push, 1, <<28>>}, {:push, 1, <<0x04>>}, :revert]
Returns a simple EVM program that returns the input code as the output of an Ethereum "initCode" constructor.
Examples
iex> use Signet.Hex
...> Signet.Assembly.constructor(~h[0xaabbcc])
...> |> to_hex()
"0x60036200000e60003960036000f3aabbcc"
Disassembles opcodes from raw evm bytecode to opcodes.
Examples
iex> Signet.Assembly.disassemble(~h[0x6101026000523460000362000014576002601efd5b6002601ffd])
[
{:push, 2, <<0x01, 0x02>>},
{:push, 1, <<0>>},
:mstore,
:callvalue,
{:push, 1, <<0>>},
:sub,
{:push, 3, <<0, 0, 20>>},
:jumpi,
{:push, 1, <<2>>},
{:push, 1, <<30>>},
:revert,
:jumpdest,
{:push, 1, <<2>>},
{:push, 1, <<31>>},
:revert
]
iex> Signet.Assembly.disassemble(~h[0x8192fe010203])
[
{:dup, 2},
{:swap, 3},
{:invalid, ~h[0x010203]}
]