07月24, 2020

Ethereum Virtual Machine Opcodes

Resource: https://ethervm.io/

Overview:

The Ethereum VM is a stack-based, big-endian VM with a word size of 256-bits and is used to run the smart contracts on the Ethereum blockchain.
Smart contracts are just like regular accounts, except they run EVM bytecode when receiving a transaction, allowing them to perform calculations and further transactions.
Transactions can carry a payload of 0 or more bytes of data, which is used to specify the type of interaction with a contract and any additional information.

Contract execution starts at the beginning of the bytecode.
Each opcode is encoded as one byte, except for the PUSH opcodes, which take a immediate value.
All opcodes pop their operands from the top of the stack and push their result.

PUSH1  -->uint8 # pushes a 1-byte value onto the stack
PUSH2 -->unit 16 # pushes a 2-byte value onto the stack
...
PUSH32 --> uint256 # pushes a 32-byte value onto the stack

1. Contract Creation

The data payload of a transaction creating a smart contract is itself bytecode that runs the contract constructor, sets up the initial contract state and returns the final contract bytecode.
ie. constructors are not present in the contract once deployed.

2. Contract Interaction

Typically contracts expose a public ABI, which is a list of supported ways a user can interact with a contract.
To interact with a contract, a user will submit a transaction carrying any amount of wei (including 0) and a data payload formatted according to the ABI, specifying the type of interaction and any additional parameters.

When the contract runs there are 4 main ways it handles data.

a) Call Data

This is the data associated with a transaction to a smart contract. It usually contains a 4-byte method identifier followed by serialized arguments.

Function calls in the Ethereum Virtual Machine are specified by the first four bytes of data sent with a transaction. These 4-byte signatures are defined as the first four bytes of the Keccak hash (SHA3) of the canonical representation of the function signature. Since this is a one-way operation, it is not possible to derive the human-readable representation of the function from the 4-byte signature. 

This database is meant to allow mapping those 4-byte signatures back to their human-readable versions. https://www.4byte.directory/

details: 
CALLDATALOAD --> msg.data[i : i+32]  #reads a (u)int256 from message data
CALLDATASIZE --> msg.data.size #message data length in bytes
CALLDATACOPY--> memory[destOffset:destOffset+length] =
    msg.data[offset:offset+length] #copy message data

b) Stack

The EVM maintains a stack of uint256s used to hold local variables, function call arguments and return addresses.
Distinguishing between return addresses and other variables is tricky.

On this page, the top of the stack is denoted stack[-1], followed by stack[-2], ...:

PUSH1, 
DUP1, PUSH(value) # clones the last value on the stack
DUP2, PUSH(value) # clones the 2nd last value on the stack
DUP16, PUSH(value) # clones the 16th last value on the stack
SWAP1, a, b = b, a # swaps the last two values on the stack
SWAP16, a, b = b, a #swaps the top of the stack with the 17th last element
POP, POP() # pops a (u)int256 off the stack and discards it

alt

c) Memory

Memory is an array of uint8s used to hold transient data while a contract is being executed.

It is not persisted across transactions
MLOAD, value = memory[offset:offset+32] # reads a (u)int256 from memory
MSTORE, memory[offset:offset+32] = value # writes a (u)int256 to memory
MSTORE8, memory[offset] = value & 0xFF # writes a uint8 to memory

d) Storage

Storage is a persistent associative map, with uint256s as keys and uint256s as values.

All contract fields and mappings are saved in storage.

Storage fields can be inspected using web3.eth.getStorageAt(address, key).

See: 
SLOAD, value = storage[key] # reads a (u)int256 from storage
SSTORE, storage[key] = value # writes a (u)int256 to storage

3. Opcodes

ADD, a + b # (u)int256 addition modulo 2**256
SUB, a - b # (u)int256 subtraction modulo 2**256
SHA3, hash = keccak256(memory[offset:offset+length]) # input offset + length, output hash.

从现在起,你的选择就是答案。 找到答案那一刻,你就是人生的巨浪。 你应该抬起头来,不给未完成的事再找借口,等风来根本不是你的风格。

本文链接:https://harry.ren/post/ethereumOpcodes.html

-- EOF --

Comments