Environment#
These opcodes give you access to the Ethereum environment
Address#
Returns the address of the account currently executing this program
def address(evm):
evm.stack.push(evm.sender)
evm.pc += 1
evm.gas_dec(3)
Balance#
Get the balance of the given address. We only mock this, so we always return the same value for every address.
def balance(evm):
address = evm.stack.pop()
evm.stack.push(99999999999)
evm.pc += 1
evm.gas_dec(2600) # 100 if warm
Origin#
The address that originally triggered the execution. This is tx.origin
in Solidity.
For us tx.origin
is always equal to msg.sender
. That is why we simply return the sender
.
def origin(evm):
evm.stack.push(evm.sender)
evm.pc += 1
evm.gas_dec(2)
Caller#
def caller(evm):
evm.stack.push("0x414b60745072088d013721b4a28a0559b1A9d213")
evm.pc += 1
evm.gas_dec(2)
Callvalue#
Returns the value of Ether (wei) provided for this execution
def callvalue(evm):
evm.stack.push(evm.value)
evm.pc += 1
evm.gas_dec(2)
Calldataload#
Pushes the current input data (32 bytes) on the stack
def calldataload(evm):
i = evm.stack.pop()
delta = 0
if i+32 > len(evm.calldata):
delta = i+32 - len(evm.calldata)
# always has to be 32 bytes
# if its not we append 0x00 bytes until it is
calldata = evm.calldata[i:i+32-delta]
calldata += 0x00*delta
evm.stack.push(calldata)
evm.pc += 1
evm.gas_dec(3)
Calldatasize#
Pushes the size of the calldata on the stack
def calldatasize(evm):
evm.stack.push(len(evm.calldata))
evm.pc += 1
evm.gas_dec(2)
Calldatacopy#
Stores a specified part of the calldata in memory
def calldatacopy(evm):
destOffset = evm.stack.pop()
offset = evm.stack.pop()
size = evm.stack.pop()
calldata = evm.calldata[offset:offset+size]
memory_expansion_cost = evm.memory.store(destOffset, calldata)
static_gas = 3
minimum_word_size = (size + 31) // 32
dynamic_gas = 3 * minimum_word_size + memory_expansion_cost
evm.gas_dec(static_gas + dynamic_gas)
evm.pc += 1
Codesize#
Puts the size of the currently running program on the stack
def codesize(evm):
evm.stack.push(len(evm.program))
evm.pc += 1
evm.gas_dec(2)
Codecopy#
Stores a specified part of the program in memory
def codecopy(evm):
destOffset = evm.stack.pop()
offset = evm.stack.pop()
size = evm.stack.pop()
code = evm.program[offset:offset+size]
memory_expansion_cost = evm.memory.store(destOffset, code)
static_gas = 3
minimum_word_size = (size + 31) / 32
dynamic_gas = 3 * minimum_word_size + memory_expansion_cost
evm.gas_dec(static_gas + dynamic_gas)
evm.pc += 1
Gas Price#
The current gas price. Because we are running everything locally, the gas price is simply 0.
def gasprice(evm):
evm.stack.push(0x00)
evm.pc += 1
evm.gas_dec(2)
External Code Size#
The size of another program given by its address. There are no other programs in our simplified world so we simply return 0.
def extcodesize(evm):
address = evm.stack.pop()
evm.stack.push(0x00)
evm.gas_dec(2600) # 100 if warm
evm.pc += 1
External Code Copy#
Stores a specified part of another program in memory
def extcodecopy(evm):
address = evm.stack.pop()
destOffset = evm.stack.pop()
offset = evm.stack.pop()
size = evm.stack.pop()
extcode = [] # no external code
memory_expansion_cost = evm.memory.store(destOffset, extcode)
# refactor this in seperate method
minimum_word_size = (size + 31) / 32
dynamic_gas = 3 * minimum_word_size + memory_expansion_cost
address_access_cost = 100 if warm else 2600
evm.gas_dec(dynamic_gas + address_access_cost)
evm.pc += 1
Return Data Size#
Get size of output data from the previous call from the current environment. As our execution is the only one running, there is no previous return data. Therefore we can simply return 0.
def returndatasize(evm):
evm.stack.push(0x00) # no return data
evm.pc += 1
evm.gas_dec(2)
Return Data Copy#
Stores a specified part of the previous return data in memory
def returndatacopy(evm):
destOffset = evm.stack.pop()
offset = evm.stack.pop()
size = evm.stack.pop()
returndata = evm.program[offset:offset+size]
memory_expansion_cost = evm.memory.store(destOffset, returndata)
minimum_word_size = (size + 31) / 32
dynamic_gas = 3 * minimum_word_size + memory_expansion_cost
evm.gas_dec(3 + dynamic_gas)
evm.pc += 1
External Code Hash#
The hash of another program given by its address. There are no other programs in our simplified world so we simply return 0.
def extcodehash(evm):
address = evm.stack.pop()
evm.stack.push(0x00) # no code
evm.gas_dec(2600) # 100 if warm
evm.pc += 1
Block Hash#
Get the hash of one of the 256 most recent complete blocks and push it on the stack.
def blockhash(evm):
blockNumber = evm.stack.pop()
if blockNumber > 256: raise Exception("Only last 256 blocks can be accessed")
evm.stack.push(0x1cbcfa1ffb1ca1ca8397d4f490194db5fc0543089b9dee43f76cf3f962a185e8)
evm.pc += 1
evm.gas_dec(20)
Coinbase#
Get the address of the miner for this block
def coinbase(evm):
evm.stack.push(0x1cbcfa1ffb1ca1ca8397d4f490194db5fc0543089b9dee43f76cf3f962a185e8)
evm.pc += 1
evm.gas_dec(2)