Ethereum Virtual Machine (EVM) Environmental Instructions
Table of Contents
Introduction
Implementations of the EVM environment related instructions.
Module Contents
Functions
Pushes the address of the current executing account to the stack. |
|
Pushes the balance of the given account onto the stack. |
|
Pushes the address of the original transaction sender to the stack. |
|
Pushes the address of the caller onto the stack. |
|
Push the value (in wei) sent with the call onto the stack. |
|
Push a word (32 bytes) of the input data belonging to the current |
|
Push the size of input data in current environment onto the stack. |
|
Copy a portion of the input data in current environment to memory. |
|
Push the size of code running in current environment onto the stack. |
|
Copy a portion of the code in current environment to memory. |
|
Push the gas price used in current environment onto the stack. |
|
Push the code size of a given account onto the stack. |
|
Copy a portion of an account’s code to memory. |
|
Pushes the size of the return data buffer onto the stack. |
|
Copies data from the return data buffer code to memory |
|
Returns the keccak256 hash of a contract’s bytecode |
|
Pushes the balance of the current address to the stack. |
Module Details
address
- address(evm)
Pushes the address of the current executing account to the stack.
- Parameters
evm – The current EVM frame.
def address(evm: Evm) -> None:
# STACK
pass
# GAS
charge_gas(evm, GAS_BASE)
# OPERATION
push(evm.stack, U256.from_be_bytes(evm.message.current_target))
# PROGRAM COUNTER
evm.pc += 1
balance
- balance(evm)
Pushes the balance of the given account onto the stack.
- Parameters
evm – The current EVM frame.
def balance(evm: Evm) -> None:
# STACK
address = to_address(pop(evm.stack))
# GAS
charge_gas(evm, GAS_BALANCE)
# OPERATION
# Non-existent accounts default to EMPTY_ACCOUNT, which has balance 0.
balance = get_account(evm.env.state, address).balance
push(evm.stack, balance)
# PROGRAM COUNTER
evm.pc += 1
origin
- origin(evm)
Pushes the address of the original transaction sender to the stack. The origin address can only be an EOA.
- Parameters
evm – The current EVM frame.
def origin(evm: Evm) -> None:
# STACK
pass
# GAS
charge_gas(evm, GAS_BASE)
# OPERATION
push(evm.stack, U256.from_be_bytes(evm.env.origin))
# PROGRAM COUNTER
evm.pc += 1
caller
- caller(evm)
Pushes the address of the caller onto the stack.
- Parameters
evm – The current EVM frame.
def caller(evm: Evm) -> None:
# STACK
pass
# GAS
charge_gas(evm, GAS_BASE)
# OPERATION
push(evm.stack, U256.from_be_bytes(evm.message.caller))
# PROGRAM COUNTER
evm.pc += 1
callvalue
- callvalue(evm)
Push the value (in wei) sent with the call onto the stack.
- Parameters
evm – The current EVM frame.
def callvalue(evm: Evm) -> None:
# STACK
pass
# GAS
charge_gas(evm, GAS_BASE)
# OPERATION
push(evm.stack, evm.message.value)
# PROGRAM COUNTER
evm.pc += 1
calldataload
- calldataload(evm)
Push a word (32 bytes) of the input data belonging to the current environment onto the stack.
- Parameters
evm – The current EVM frame.
def calldataload(evm: Evm) -> None:
# STACK
start_index = pop(evm.stack)
# GAS
charge_gas(evm, GAS_VERY_LOW)
# OPERATION
value = buffer_read(evm.message.data, start_index, U256(32))
push(evm.stack, U256.from_be_bytes(value))
# PROGRAM COUNTER
evm.pc += 1
calldatasize
- calldatasize(evm)
Push the size of input data in current environment onto the stack.
- Parameters
evm – The current EVM frame.
def calldatasize(evm: Evm) -> None:
# STACK
pass
# GAS
charge_gas(evm, GAS_BASE)
# OPERATION
push(evm.stack, U256(len(evm.message.data)))
# PROGRAM COUNTER
evm.pc += 1
calldatacopy
- calldatacopy(evm)
Copy a portion of the input data in current environment to memory.
This will also expand the memory, in case that the memory is insufficient to store the data.
- Parameters
evm – The current EVM frame.
def calldatacopy(evm: Evm) -> None:
# STACK
memory_start_index = pop(evm.stack)
data_start_index = pop(evm.stack)
size = pop(evm.stack)
# GAS
words = ceil32(Uint(size)) // 32
copy_gas_cost = GAS_COPY * words
extend_memory = calculate_gas_extend_memory(
evm.memory, [(memory_start_index, size)]
)
charge_gas(evm, GAS_VERY_LOW + copy_gas_cost + extend_memory.cost)
# OPERATION
evm.memory += b"\x00" * extend_memory.expand_by
value = buffer_read(evm.message.data, data_start_index, size)
memory_write(evm.memory, memory_start_index, value)
# PROGRAM COUNTER
evm.pc += 1
codesize
- codesize(evm)
Push the size of code running in current environment onto the stack.
- Parameters
evm – The current EVM frame.
def codesize(evm: Evm) -> None:
# STACK
pass
# GAS
charge_gas(evm, GAS_BASE)
# OPERATION
push(evm.stack, U256(len(evm.code)))
# PROGRAM COUNTER
evm.pc += 1
codecopy
- codecopy(evm)
Copy a portion of the code in current environment to memory.
This will also expand the memory, in case that the memory is insufficient to store the data.
- Parameters
evm – The current EVM frame.
def codecopy(evm: Evm) -> None:
# STACK
memory_start_index = pop(evm.stack)
code_start_index = pop(evm.stack)
size = pop(evm.stack)
# GAS
words = ceil32(Uint(size)) // 32
copy_gas_cost = GAS_COPY * words
extend_memory = calculate_gas_extend_memory(
evm.memory, [(memory_start_index, size)]
)
charge_gas(evm, GAS_VERY_LOW + copy_gas_cost + extend_memory.cost)
# OPERATION
evm.memory += b"\x00" * extend_memory.expand_by
value = buffer_read(evm.code, code_start_index, size)
memory_write(evm.memory, memory_start_index, value)
# PROGRAM COUNTER
evm.pc += 1
gasprice
- gasprice(evm)
Push the gas price used in current environment onto the stack.
- Parameters
evm – The current EVM frame.
def gasprice(evm: Evm) -> None:
# STACK
pass
# GAS
charge_gas(evm, GAS_BASE)
# OPERATION
push(evm.stack, U256(evm.env.gas_price))
# PROGRAM COUNTER
evm.pc += 1
extcodesize
- extcodesize(evm)
Push the code size of a given account onto the stack.
- Parameters
evm – The current EVM frame.
def extcodesize(evm: Evm) -> None:
# STACK
address = to_address(pop(evm.stack))
# GAS
charge_gas(evm, GAS_EXTERNAL)
# OPERATION
# Non-existent accounts default to EMPTY_ACCOUNT, which has empty code.
codesize = U256(len(get_account(evm.env.state, address).code))
push(evm.stack, codesize)
# PROGRAM COUNTER
evm.pc += 1
extcodecopy
- extcodecopy(evm)
Copy a portion of an account’s code to memory.
- Parameters
evm – The current EVM frame.
def extcodecopy(evm: Evm) -> None:
# STACK
address = to_address(pop(evm.stack))
memory_start_index = pop(evm.stack)
code_start_index = pop(evm.stack)
size = pop(evm.stack)
# GAS
words = ceil32(Uint(size)) // 32
copy_gas_cost = GAS_COPY * words
extend_memory = calculate_gas_extend_memory(
evm.memory, [(memory_start_index, size)]
)
charge_gas(evm, GAS_EXTERNAL + copy_gas_cost + extend_memory.cost)
# OPERATION
evm.memory += b"\x00" * extend_memory.expand_by
code = get_account(evm.env.state, address).code
value = buffer_read(code, code_start_index, size)
memory_write(evm.memory, memory_start_index, value)
# PROGRAM COUNTER
evm.pc += 1
returndatasize
- returndatasize(evm)
Pushes the size of the return data buffer onto the stack.
- Parameters
evm – The current EVM frame.
def returndatasize(evm: Evm) -> None:
# STACK
pass
# GAS
charge_gas(evm, GAS_BASE)
# OPERATION
push(evm.stack, U256(len(evm.return_data)))
# PROGRAM COUNTER
evm.pc += 1
returndatacopy
- returndatacopy(evm)
Copies data from the return data buffer code to memory
- Parameters
evm – The current EVM frame.
def returndatacopy(evm: Evm) -> None:
# STACK
memory_start_index = pop(evm.stack)
return_data_start_position = pop(evm.stack)
size = pop(evm.stack)
# GAS
words = ceil32(Uint(size)) // 32
copy_gas_cost = GAS_RETURN_DATA_COPY * words
extend_memory = calculate_gas_extend_memory(
evm.memory, [(memory_start_index, size)]
)
charge_gas(evm, GAS_VERY_LOW + copy_gas_cost + extend_memory.cost)
# OPERATION
ensure(
Uint(return_data_start_position) + Uint(size) <= len(evm.return_data),
OutOfBoundsRead,
)
evm.memory += b"\x00" * extend_memory.expand_by
value = evm.return_data[
return_data_start_position : return_data_start_position + size
]
memory_write(evm.memory, memory_start_index, value)
# PROGRAM COUNTER
evm.pc += 1
extcodehash
- extcodehash(evm)
Returns the keccak256 hash of a contract’s bytecode :param evm: The current EVM frame.
def extcodehash(evm: Evm) -> None:
# STACK
address = to_address(pop(evm.stack))
# GAS
charge_gas(evm, GAS_CODE_HASH)
# OPERATION
account = get_account(evm.env.state, address)
if account == EMPTY_ACCOUNT:
codehash = U256(0)
else:
codehash = U256.from_be_bytes(keccak256(account.code))
push(evm.stack, codehash)
# PROGRAM COUNTER
evm.pc += 1
self_balance
- self_balance(evm)
Pushes the balance of the current address to the stack.
- Parameters
evm – The current EVM frame.
def self_balance(evm: Evm) -> None:
# STACK
pass
# GAS
charge_gas(evm, GAS_FAST_STEP)
# OPERATION
# Non-existent accounts default to EMPTY_ACCOUNT, which has balance 0.
balance = get_account(evm.env.state, evm.message.current_target).balance
push(evm.stack, balance)
# PROGRAM COUNTER
evm.pc += 1