-
-
Notifications
You must be signed in to change notification settings - Fork 41
Frame refactor #1668
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Frame refactor #1668
Conversation
The latest updates on your projects. Learn more about Vercel for Git ↗︎
|
|
Warning Rate limit exceeded@roninjin10 has exceeded the limit for the number of commits or files that can be reviewed per hour. Please wait 4 minutes and 42 seconds before requesting another review. ⌛ How to resolve this issue?After the wait time has elapsed, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout. Please see our FAQ for further information. 📒 Files selected for processing (2)
WalkthroughThe codebase has been refactored to modularize the EVM frame logic by splitting previously monolithic implementations into dedicated files under a Changes
Sequence Diagram(s)sequenceDiagram
participant User
participant Evm
participant Frame
participant StateManager
User->>Evm: createFrame(input, code, depth)
Evm->>Frame: Frame.init(allocator, input, code, depth, checkpoint)
Frame-->>Evm: Frame instance
User->>Frame: execute(stateManager)
Frame->>Frame: (runs code, updates state)
Frame-->>User: FrameOrCall (Result or Call)
Poem
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed help? Create a ticket on our support page for assistance with any issues or questions. Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
CodeRabbit Configuration File (
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
🧹 Nitpick comments (5)
src/Evm/Frame/CallScheme.zig (1)
2-7
: Enhancement: Document individual variants
Consider adding inline doc comments above each variant to detail subtle differences, for improved readability and generated documentation. For example:pub const CallScheme = enum { /// Standard external call with new context Call, /// Execute only the callee's code in caller context CallCode, /// Delegate call inheriting caller and value DelegateCall, /// Read-only call disallowing state modifications StaticCall, };src/Evm/Frame/Stack.zig (1)
1-30
: Implementation looks good with a minor optimization opportunityThe Stack implementation is clean and appropriate for EVM operations, with proper error handling for overflow/underflow conditions. A few suggestions:
The error handling in the
pop
method contains redundancy - line 28 has bothpop()
followed byorelse return error.StackUnderflow
, but you've already checked for empty stack at line 25.Consider adding helper methods that would be useful for EVM operations:
peek
to view the top element without popping- Methods to access elements at specific positions (for DUP and SWAP operations)
- A getter for current stack size
// Simplified pop method pub fn pop(self: *Stack) !u256 { if (self.data.items.len == 0) { return error.StackUnderflow; } - return self.data.pop() orelse return error.StackUnderflow; + return self.data.pop(); } +// Add these useful methods for EVM operations +pub fn peek(self: *Stack) !u256 { + if (self.data.items.len == 0) { + return error.StackUnderflow; + } + return self.data.items[self.data.items.len - 1]; +} + +pub fn at(self: *Stack, pos: usize) !u256 { + if (pos >= self.data.items.len) { + return error.StackUnderflow; + } + return self.data.items[self.data.items.len - 1 - pos]; +} + +pub fn size(self: *Stack) usize { + return self.data.items.len; +}src/Evm/Frame/StateManager.zig (1)
1-33
: Mock implementation needs better initialization and documentationThe StateManager implementation provides a simple mock for testing, which is appropriate at this stage. A few improvements would make it more usable:
- Add an
init
method to configure the mock with test data- Clearly document that the journaling methods are non-functional placeholders
- Add better documentation on how this mock would be used in tests
/// State manager handles the EVM state (balances, code, storage) pub const StateManager = struct { // Simple implementation for testing mockCode: ?Bytes = null, + /// Initialize a mock state manager with optional test code + pub fn init(code: ?Bytes) StateManager { + return StateManager{ + .mockCode = code, + }; + } + pub fn checkpoint(_: *StateManager) JournalCheckpoint { - // Create a checkpoint in the state journal + // MOCK: This is a no-op mock implementation + // In a real implementation, this would create a checkpoint in the state journal return 0; // Placeholder }Also, consider adding a TODO comment indicating that this will be replaced with a real implementation in the future. This helps clarify the temporary nature of this code.
src/Evm/Frame/ExecutionState.zig (1)
6-34
: ExecutionState struct needs additional utility methodsThe ExecutionState struct provides a solid foundation for tracking EVM execution state, but it lacks methods for manipulating the state during execution. This will likely make the code that uses this struct more verbose.
Consider adding methods for:
- Gas management (consume, refund)
- Return data manipulation
- Program counter manipulation
/// EVM execution state pub const ExecutionState = struct { memory: Memory, stack: Stack, pc: usize, gas: struct { remaining: u64, // Gas units remaining refunded: u64, // Gas units refunded }, returnData: Bytes, pub fn init(allocator: std.mem.Allocator, gasLimit: u64) ExecutionState { return ExecutionState{ .memory = Memory.init(allocator), .stack = Stack.init(allocator), .pc = 0, .gas = .{ .remaining = gasLimit, .refunded = 0, }, .returnData = &[_]u8{}, }; } pub fn deinit(self: *ExecutionState) void { self.memory.deinit(); self.stack.deinit(); } + + // Gas management methods + pub fn consumeGas(self: *ExecutionState, amount: u64) !void { + if (amount > self.gas.remaining) { + return error.OutOfGas; + } + self.gas.remaining -= amount; + } + + pub fn refundGas(self: *ExecutionState, amount: u64) void { + self.gas.refunded += amount; + } + + // Program counter methods + pub fn advancePC(self: *ExecutionState, amount: usize) void { + self.pc += amount; + } + + pub fn jumpTo(self: *ExecutionState, target: usize) void { + self.pc = target; + } + + // Return data methods + pub fn setReturnData(self: *ExecutionState, data: Bytes) void { + self.returnData = data; + } };src/Evm/Frame/FrameInput.zig (1)
5-34
: FrameInput design is solid with minor documentation needsThe FrameInput union enum is well-structured for representing both calls and contract creations. A few suggestions:
- Add documentation for what "isStatic" means in EVM context
- Consider using a more explicit representation for CREATE vs CREATE2 than a nullable salt
/// Standard call to address Call: struct { callData: Bytes, gasLimit: u64, target: address.Address, codeAddress: address.Address, // Address where code is loaded from caller: address.Address, value: u256, callType: CallScheme, - isStatic: bool, + isStatic: bool, // When true, state-changing operations are prohibited (used in STATICCALL) }, /// Contract creation Create: struct { initCode: Bytes, gasLimit: u64, caller: address.Address, value: u256, - salt: ?[32]u8, // NULL for regular CREATE, non-null for CREATE2 + salt: ?[32]u8, // NULL for regular CREATE (opcode 0xF0), non-null for CREATE2 (opcode 0xF5) },Consider adding a utility method to get the caller address since it's common to both variants, similar to how you implemented
getGasLimit
.+ pub fn getCaller(self: FrameInput) address.Address { + return switch (self) { + .Call => |call| call.caller, + .Create => |create| create.caller, + }; + }
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
Cache: Disabled due to data retention organization setting
Knowledge Base: Disabled due to data retention organization setting
📒 Files selected for processing (15)
src/Evm/Frame/Bytes.zig
(1 hunks)src/Evm/Frame/CallScheme.zig
(1 hunks)src/Evm/Frame/ExecutionState.zig
(1 hunks)src/Evm/Frame/Frame.zig
(1 hunks)src/Evm/Frame/FrameInput.zig
(1 hunks)src/Evm/Frame/FrameOrCall.zig
(1 hunks)src/Evm/Frame/FrameResult.zig
(1 hunks)src/Evm/Frame/InstructionResult.zig
(1 hunks)src/Evm/Frame/JournalCheckpoint.zig
(1 hunks)src/Evm/Frame/Memory.zig
(1 hunks)src/Evm/Frame/Stack.zig
(1 hunks)src/Evm/Frame/StateManager.zig
(1 hunks)src/Evm/evm.zig
(2 hunks)src/Evm/frame.zig
(1 hunks)src/Evm/frame_test.zig
(3 hunks)
⏰ Context from checks skipped due to timeout of 90000ms (8)
- GitHub Check: Nx Cloud Agents (1)
- GitHub Check: Nx Cloud Agents (3)
- GitHub Check: Nx Cloud Agents (6)
- GitHub Check: Nx Cloud Agents (2)
- GitHub Check: Nx Cloud Agents (5)
- GitHub Check: Nx Cloud Agents (4)
- GitHub Check: Nx Cloud - Main Job
- GitHub Check: Analyze (javascript-typescript)
🔇 Additional comments (23)
src/Evm/Frame/Bytes.zig (1)
1-1
: Clear and concise type alias
The aliasBytes = []const u8
correctly represents an immutable byte slice for code, calldata, and return data throughout the frame modules.src/Evm/Frame/JournalCheckpoint.zig (1)
1-2
: Appropriate checkpoint alias
DefiningJournalCheckpoint = usize
clearly denotes a checkpoint index for journaling state changes. This will improve readability when managing commit/revert operations.src/Evm/frame_test.zig (4)
3-4
: Update imports for modular structure
The relative paths foraddress
("../Address/address.zig"
) andframe
("Frame.zig"
) now accurately reflect the new directory layout.
8-8
: Disambiguate Frame reference with alias
IntroducingActualFrame = @import("Frame/Frame.zig").Frame
avoids ambiguity between the re-export module and the concreteFrame
struct.
29-35
: Use ActualFrame.init for initialization
Switching fromframe.Frame.init
toActualFrame.init
ensures tests target the newly modularizedFrame
type.
65-72
: Consistent use of ActualFrame in STOP execution test
Similarly updating the STOP opcode test toActualFrame.init
maintains consistency across all frame initialization tests.src/Evm/Frame/FrameOrCall.zig (1)
1-10
: Define FrameOrCall union for execution flow control
TheFrameOrCall
union enum cleanly models either aFrameResult
or a follow-upFrameInput
, aligning with the refactored execution pipeline. Imports forFrameResult
andFrameInput
are correctly referenced.src/Evm/Frame/CallScheme.zig (1)
1-7
: Introduce CallScheme enum to classify call types
TheCallScheme
enum covers all essential EVM call variants (Call
,CallCode
,DelegateCall
,StaticCall
). The type-level doc comment improves discoverability.src/Evm/Frame/InstructionResult.zig (1)
1-12
: Well-defined enum for instruction execution results.This enum cleanly captures all the possible outcomes of EVM instruction execution, with clear, descriptive names following standard EVM terminology. The struct is properly documented and follows good Zig conventions.
src/Evm/evm.zig (3)
4-4
: Import path updated to match new directory structure.The capitalization change from "frame.zig" to "Frame.zig" aligns with the new modular file organization.
118-118
: Return type now references explicit module path.The return type is now explicitly importing from "Frame/Frame.zig" instead of using the imported frame module. This is consistent with the refactoring approach of modularizing the frame components.
123-123
: Function call updated to use explicit module path.The initialization now correctly references the Frame struct from its new location.
src/Evm/Frame/FrameResult.zig (2)
1-4
: Appropriate imports for frame result dependencies.The imports correctly reference the necessary dependencies for the frame result type, including the address module, instruction result enum, and bytes type.
5-21
: Well-structured union enum for frame execution results.The
FrameResult
type cleanly separates call and create operation results while sharing common fields (status, returnData, gas metrics). The addition of the optionalcreatedAddress
field for the Create variant is appropriate.src/Evm/Frame/Memory.zig (3)
1-16
: Well-implemented memory management with proper initialization/cleanup.The Memory struct is properly initialized with an ArrayList and includes appropriate deinitialization to avoid memory leaks. Good Zig practices for memory management are followed.
17-25
: Effective memory store implementation with auto-resizing.The store method correctly handles resizing the underlying memory buffer when needed and uses efficient memory copying for the actual data storage.
27-34
: Safe memory load implementation with bounds checking.The load method safely handles out-of-bounds requests by returning an empty slice and properly clamps the end position to avoid overruns. This approach is appropriate for EVM memory access patterns.
src/Evm/frame.zig (1)
1-19
: Well-structured modular design with clear organizationThe refactoring of this file into a central re-export module demonstrates excellent software engineering practices. Breaking down the monolithic file into focused components while maintaining backward compatibility with
usingnamespace
is a solid approach. The clear comments also help document the purpose of this file as the main entry point for the Frame module.src/Evm/Frame/Frame.zig (5)
1-22
: Clean import structure with appropriate scopingThe import structure is well-organized, clearly separated into standard library imports, address imports, frame component imports, and logging configuration. Using a scoped logger for Frame-related logs will help with debugging and log filtering.
23-36
: Well-documented Frame struct with clear field descriptionsThe Frame struct design effectively encapsulates all the components needed for an EVM execution context. Each field has a descriptive comment explaining its purpose, which enhances readability and maintainability.
37-54
: Clean initialization patternThe init function follows a clear pattern for initialization, extracting the gas limit from the input and properly initializing all fields. This approach ensures the Frame is always in a valid state when created.
56-58
: Proper resource cleanupThe deinit method appropriately calls deinit on the state to ensure all resources are properly cleaned up, which is essential for memory management.
60-111
: Comprehensive debug logging implementationThe debug method provides extensive logging of frame state, making it valuable for troubleshooting. The use of pattern matching on the input type to display relevant information is particularly well-implemented.
src/Evm/Frame/Frame.zig
Outdated
/// Execute the frame until completion or a new call is needed | ||
pub fn execute(self: *Frame, stateManager: *StateManager) !FrameOrCall { | ||
// Simple implementation for initial tests | ||
// Just check for basic opcodes and handle them | ||
log.debug("Starting execution", .{}); | ||
_ = stateManager; // Silence unused parameter warning | ||
|
||
if (self.code.len == 0) { | ||
log.debug("Empty code, returning success", .{}); | ||
// Empty code returns success | ||
return FrameOrCall{ | ||
.Result = FrameResult{ | ||
.Call = .{ | ||
.status = .Success, | ||
.returnData = &[_]u8{}, | ||
.gasUsed = self.input.getGasLimit() - self.state.gas.remaining, | ||
.gasRefunded = self.state.gas.refunded, | ||
} | ||
} | ||
}; | ||
} | ||
|
||
log.debug("Code length is {d}, first byte: {x:0>2}", .{self.code.len, self.code[0]}); | ||
|
||
// In a real implementation, we would loop through the bytecode and interpret opcodes | ||
// but for this simplified version, we'll just check for STOP (0x00) | ||
if (self.code[0] == 0x00) { | ||
log.debug("Found STOP opcode, returning success", .{}); | ||
// STOP opcode | ||
return FrameOrCall{ | ||
.Result = FrameResult{ | ||
.Call = .{ | ||
.status = .Success, | ||
.returnData = &[_]u8{}, | ||
.gasUsed = self.input.getGasLimit() - self.state.gas.remaining, | ||
.gasRefunded = self.state.gas.refunded, | ||
} | ||
} | ||
}; | ||
} | ||
|
||
log.debug("Unknown opcode, returning InvalidOpcode", .{}); | ||
// Default response for other opcodes (not yet implemented) | ||
return FrameOrCall{ | ||
.Result = FrameResult{ | ||
.Call = .{ | ||
.status = .InvalidOpcode, | ||
.returnData = &[_]u8{}, | ||
.gasUsed = self.input.getGasLimit() - self.state.gas.remaining, | ||
.gasRefunded = self.state.gas.refunded, | ||
} | ||
} | ||
}; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💡 Verification agent
🧩 Analysis chain
Simplified execution logic needs expansion
The execute method provides a simplified implementation that handles only basic cases (empty code and STOP opcode). While this is a good starting point for the refactoring, it will need to be expanded to handle the full range of EVM opcodes.
Consider documenting the roadmap for implementing the full EVM opcode set, either as TODOs in the code or in a separate document. This would help track progress and ensure no opcodes are missed during implementation.
🏁 Script executed:
#!/bin/bash
# Check if there's any documentation or TODOs about implementing the remaining opcodes
echo "Searching for documentation about opcode implementation..."
rg -i "todo|implement|opcode|evm instruction" --glob "*.{zig,md}" ./src/Evm
Length of output: 8334
Reference the existing opcode roadmap in code and docs
The high-level roadmap for implementing the full EVM instruction set already lives in src/Evm/README.md
(see “Instruction Set: Implementation of all EVM opcodes”) and is fleshed out in src/Evm/README-COMPLETE.md
. To tie the simplified execute
stub to that roadmap and make progress visible:
- In
src/Evm/Frame/Frame.zig
(lines 113–166), add a// TODO:
comment above the placeholder logic, e.g.:// TODO: replace this stub with a full opcode interpreter as per // src/Evm/README.md#instruction-set
- Optionally expand
README.md
(or a new checklist) with a per-opcode implementation status, so teams can tick off groups (arithmetic, bitwise, memory, control flow, etc.) as they’re done. - Keep
README-COMPLETE.md
in sync with each completed opcode or group.
🤖 Prompt for AI Agents
In src/Evm/Frame/Frame.zig around lines 113 to 166, the execute function
currently only handles empty code and the STOP opcode, lacking implementation
for the full EVM opcode set. Add a TODO comment above the existing placeholder
logic indicating that this stub should be replaced with a full opcode
interpreter referencing src/Evm/README.md#instruction-set. Optionally, update
README.md with a per-opcode implementation status checklist to track progress
and keep README-COMPLETE.md synchronized with completed opcodes.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
🧹 Nitpick comments (2)
src/Evm/evm.zig (1)
117-124
: Consider using type aliases instead of direct imports in function signatures.The direct imports to "Frame/Frame.zig" in both the return type and function call create a tight coupling to the file structure, which could be problematic if the directory structure changes.
- pub fn createFrame(self: Evm, input: frame.FrameInput, code: []const u8, depth: u16) !@import("Frame/Frame.zig").Frame { + pub fn createFrame(self: Evm, input: frame.FrameInput, code: []const u8, depth: u16) !frame.Frame {And then update line 123 similarly:
- return try @import("Frame/Frame.zig").Frame.init(self.allocator, input, code, depth, checkpoint); + return try frame.Frame.init(self.allocator, input, code, depth, checkpoint);This assumes that frame.zig re-exports the Frame type from Frame/Frame.zig.
src/Evm/Frame_test.zig (1)
7-14
: Consider using re-exported types instead of direct imports.Similar to the suggestion for evm.zig, consider using the types re-exported through frame.zig instead of direct imports from specific files to reduce coupling to the file structure.
- // Use this to avoid ambiguous reference - const ActualFrame = @import("Frame/Frame.zig").Frame; + // Use the re-exported Frame type + const ActualFrame = frame.Frame;This would make the code more resilient to future changes in the file organization.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
Cache: Disabled due to data retention organization setting
Knowledge Base: Disabled due to data retention organization setting
📒 Files selected for processing (3)
src/Evm/Frame/FrameInput.zig
(1 hunks)src/Evm/Frame_test.zig
(1 hunks)src/Evm/evm.zig
(5 hunks)
⏰ Context from checks skipped due to timeout of 90000ms (8)
- GitHub Check: Nx Cloud Agents (5)
- GitHub Check: Nx Cloud Agents (3)
- GitHub Check: Nx Cloud Agents (2)
- GitHub Check: Nx Cloud Agents (6)
- GitHub Check: Nx Cloud Agents (4)
- GitHub Check: Nx Cloud Agents (1)
- GitHub Check: Nx Cloud - Main Job
- GitHub Check: Analyze (javascript-typescript)
🔇 Additional comments (11)
src/Evm/Frame/FrameInput.zig (3)
1-42
: Well-structured union enum design for frame inputs.The FrameInput union enum is designed with clear separation of concerns for different call types. The inclusion of detailed comments explaining each variant is helpful, and the
getGasLimit
utility method provides consistent access to the gas limit across all variants.
26-33
: Good addition of CREATE2 support.The CREATE2 variant with its salt parameter is properly implemented, enhancing the EVM functionality to support this important opcode. The documentation comment clearly indicates its purpose.
35-41
: Clean implementation of the getGasLimit method.The getGasLimit method provides a clean abstraction that encapsulates implementation details of each variant, making it easier for calling code to access gas limits without needing to handle each variant separately.
src/Evm/evm.zig (4)
4-4
: Import path updated for the new modular structure.The import of the frame module has been updated to use the new structure, maintaining backward compatibility through re-exports.
145-151
: Proper handling of CREATE2 variant in execute function.The CREATE2 variant is handled consistently with the CREATE variant, with good logging of relevant details including gas limit, code length, and salt.
177-178
: Consistent handling of both CREATE and CREATE2 results.The condition has been updated to handle both CREATE and CREATE2 inputs consistently when converting between result types, which is correct.
303-334
: Good test coverage for CREATE2 functionality.The new test for the CREATE2 variant provides appropriate coverage for this new feature, ensuring that it works correctly with the rest of the system.
src/Evm/Frame_test.zig (4)
15-49
: Thorough test for frame initialization with Call input.The test provides good coverage for frame initialization with Call input, checking all the essential values like depth, gas, and code.
51-84
: Comprehensive test for frame initialization with Create input.The test thoroughly verifies frame initialization with Create input, including checking the getGasLimit method.
275-296
: Good test for frame debugging with CREATE2 input.The test verifies that debugging doesn't crash with both standard Call input and the new CREATE2 input, which is important for code stability.
1-388
: Comprehensive test suite for frame functionality.The test file provides excellent coverage for the frame functionality, including initialization, execution, debugging, stack and memory operations, and simple EVM execution. This ensures that the refactored code works as expected.
test "EVM simple execution - create" { | ||
var gpa = std.heap.GeneralPurposeAllocator(.{}){}; | ||
defer _ = gpa.deinit(); | ||
const allocator = gpa.allocator(); | ||
|
||
var stateManager = frame.StateManager{}; | ||
var testEvm = evm.Evm.init(allocator, &stateManager); | ||
|
||
const createInput = FrameInput{ | ||
.Create = .{ | ||
.initCode = &[_]u8{0x00}, // Simple STOP opcode | ||
.gasLimit = 100000, | ||
.caller = address.ZERO_ADDRESS, | ||
.value = 0, | ||
.salt = null, // Regular CREATE (not CREATE2) | ||
}, | ||
}; | ||
|
||
// Execute the frame to create a contract | ||
const result = try testEvm.execute(createInput); | ||
|
||
try testing.expect(result == .Create); | ||
switch (result) { | ||
.Create => |createResult| { | ||
try testing.expectEqual(InstructionResult.Success, createResult.status); | ||
}, | ||
else => unreachable, | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Issue with salt field in Create variant.
The Create variant in the test includes a salt: null
field, but according to the FrameInput definition in FrameInput.zig, the Create variant doesn't have a salt field.
const createInput = FrameInput{
.Create = .{
.initCode = &[_]u8{0x00}, // Simple STOP opcode
.gasLimit = 100000,
.caller = address.ZERO_ADDRESS,
.value = 0,
- .salt = null, // Regular CREATE (not CREATE2)
},
};
This field should be removed as it doesn't exist in the Create variant and could lead to compilation errors.
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
test "EVM simple execution - create" { | |
var gpa = std.heap.GeneralPurposeAllocator(.{}){}; | |
defer _ = gpa.deinit(); | |
const allocator = gpa.allocator(); | |
var stateManager = frame.StateManager{}; | |
var testEvm = evm.Evm.init(allocator, &stateManager); | |
const createInput = FrameInput{ | |
.Create = .{ | |
.initCode = &[_]u8{0x00}, // Simple STOP opcode | |
.gasLimit = 100000, | |
.caller = address.ZERO_ADDRESS, | |
.value = 0, | |
.salt = null, // Regular CREATE (not CREATE2) | |
}, | |
}; | |
// Execute the frame to create a contract | |
const result = try testEvm.execute(createInput); | |
try testing.expect(result == .Create); | |
switch (result) { | |
.Create => |createResult| { | |
try testing.expectEqual(InstructionResult.Success, createResult.status); | |
}, | |
else => unreachable, | |
} | |
} | |
test "EVM simple execution - create" { | |
var gpa = std.heap.GeneralPurposeAllocator(.{}){}; | |
defer _ = gpa.deinit(); | |
const allocator = gpa.allocator(); | |
var stateManager = frame.StateManager{}; | |
var testEvm = evm.Evm.init(allocator, &stateManager); | |
const createInput = FrameInput{ | |
.Create = .{ | |
.initCode = &[_]u8{0x00}, // Simple STOP opcode | |
.gasLimit = 100000, | |
.caller = address.ZERO_ADDRESS, | |
.value = 0, | |
}, | |
}; | |
// Execute the frame to create a contract | |
const result = try testEvm.execute(createInput); | |
try testing.expect(result == .Create); | |
switch (result) { | |
.Create => |createResult| { | |
try testing.expectEqual(InstructionResult.Success, createResult.status); | |
}, | |
else => unreachable, | |
} | |
} |
🤖 Prompt for AI Agents
In src/Evm/Frame_test.zig between lines 389 and 417, the test code for the
Create variant incorrectly includes a salt field, which is not defined in the
FrameInput Create variant. Remove the salt: null field from the createInput
initialization to match the FrameInput definition and avoid compilation errors.
Description
Refactored the EVM frame implementation into a modular directory structure to improve code organization and maintainability. The previously monolithic
frame.zig
file has been split into multiple specialized components in a newFrame
directory, with each component handling a specific aspect of EVM execution.Key changes:
frame.zig
fileTesting
The existing test cases have been updated to work with the new structure, ensuring that the refactoring doesn't break existing functionality. The tests verify frame initialization and simple execution with the STOP opcode.
Additional Information
Your ENS/address:
Summary by CodeRabbit