InstructionErrors
Set of common errors when running indivual instructions.
Allocator.Error || error{ StackUnderflow, StackOverflow, Overflow } || GasTracker.Error
AllInstructionErrors
Set of all possible errors of interpreter instructions.
InstructionErrors || Memory.Error || error{
UnexpectedError,
InvalidJump,
InstructionNotEnabled,
}
InterpreterRunErrors
Set of possible errors when running the interpreter.
AllInstructionErrors || error{
OpcodeNotFound,
InvalidInstructionOpcode,
InterpreterReverted,
InvalidOffset,
CallWithValueNotAllowedInStaticCall,
CreateCodeSizeLimit,
}
InterpreterStatusErrors
Set of possible errors that can be returned depending on the interpreter's current state.
error{
OpcodeNotFound,
CallWithValueNotAllowedInStaticCall,
InvalidInstructionOpcode,
InterpreterReverted,
CreateCodeSizeLimit,
InvalidOffset,
InvalidJump,
}
InterpreterActions
The set of next interpreter actions.
Properties
union(enum) {
/// Call action.
call_action: CallAction
/// Create action.
create_action: CreateAction
/// Return action.
return_action: ReturnAction
/// No action for the interpreter to take.
no_action
}
Deinit
Clears any memory with the associated action.
Signature
pub fn deinit(self: @This(), allocator: Allocator) void
InterpreterStatus
The status of execution for the interpreter.
Properties
enum {
call_or_create
call_with_value_not_allowed_in_static_call
create_code_size_limit
invalid
invalid_jump
invalid_offset
opcode_not_found
returned
reverted
running
self_destructed
stopped
}
InterpreterInitOptions
Set of default options that the interperter needs for it to be able to run.
Properties
struct {
/// Maximum amount of gas available to perform the operations
gas_limit: u64 = 30_000_000
/// Tells the interperter if it's going to run as a static call
is_static: bool = false
/// Sets the interperter spec based on the hardforks.
spec_id: SpecId = .LATEST
}
Init
Sets the interpreter to it's expected initial state.
Copy's the contract's bytecode independent of it's state.
Exampleconst contract_instance = try Contract.init(
testing.allocator,
&.{},
.{ .raw = @constCast(&[_]u8{ 0x60, 0x01, 0x60, 0x02, 0x01 }) },
null,
0,
[_]u8{1} ** 20,
[_]u8{0} ** 20,
);
defer contract_instance.deinit(testing.allocator);
var plain: PlainHost = undefined;
defer plain.deinit();
plain.init(testing.allocator);
var interpreter: Interpreter = undefined;
defer interpreter.deinit();
try interpreter.init(testing.allocator, contract_instance, plain.host(), .{});
Signature
pub fn init(
self: *Interpreter,
allocator: Allocator,
contract_instance: Contract,
evm_host: Host,
opts: InterpreterInitOptions,
) Allocator.Error!void
AdvanceProgramCounter
Moves the program_counter
by one.
Signature
pub fn advanceProgramCounter(self: *Interpreter) void
RunInstruction
Runs a single instruction based on the program_counter
position and the associated bytecode. Doesn't move the counter.
Signature
pub fn runInstruction(self: *Interpreter) AllInstructionErrors!void
Run
Runs the associated contract bytecode.
Depending on the interperter final status
this can return errors.
The bytecode that will get run will be padded with STOP
instructions
at the end to make sure that we don't have index out of bounds panics.
const contract_instance = try Contract.init(
testing.allocator,
&.{},
.{ .raw = @constCast(&[_]u8{ 0x60, 0x01, 0x60, 0x02, 0x01 }) },
null,
0,
[_]u8{1} ** 20,
[_]u8{0} ** 20,
);
defer contract_instance.deinit(testing.allocator);
var plain: PlainHost = undefined;
defer plain.deinit();
plain.init(testing.allocator);
var interpreter: Interpreter = undefined;
defer interpreter.deinit();
try interpreter.init(testing.allocator, contract_instance, plain.host(), .{});
const result = try interpreter.run();
defer result.deinit(testing.allocator);
Signature
pub fn run(self: *Interpreter) (AllInstructionErrors || InterpreterStatusErrors)!InterpreterActions
Resize
Resizes the inner memory size. Adds gas expansion cost to the gas tracker.
Signature
pub fn resize(self: *Interpreter, new_size: usize) (Allocator.Error || GasTracker.Error || Memory.Error)!void