Compute the create address in the VM#1589
Open
chfast wants to merge 2 commits into
Open
Conversation
There was a problem hiding this comment.
Pull request overview
This PR moves CREATE/CREATE2 address derivation into the VM (so msg.recipient is set before the evmc_call boundary), aligns EIP-2681/EIP-2929 handling with that new flow, and updates the EVMC interface by removing evmc_result.create_address and bumping the ABI version.
Changes:
- Compute CREATE/CREATE2 addresses inside
create_impl(), warm the created address in the creating frame, and pass it down viaevmc_message::recipient. - Remove
evmc_result.create_address/ the corresponding C++ wrapper APIs and bumpEVMC_ABI_VERSIONto 16. - Update state tests, unit tests, and fuzz harness logic to use VM-computed created addresses.
Reviewed changes
Copilot reviewed 13 out of 13 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| test/unittests/tracing_test.cpp | Updates expected trace output to reflect VM-computed CREATE address. |
| test/unittests/evm_other_test.cpp | Adjusts recorded-call expectations based on nonzero CREATE return value affecting later stack/memory behavior. |
| test/unittests/evm_eip3860_initcode_test.cpp | Stops depending on host-supplied create_address; validates VM-produced nonzero return on success. |
| test/unittests/evm_calls_test.cpp | Switches assertions from mocked call_result.create_address to compute_create*_address() helpers. |
| test/state/state.cpp | Computes/warmups create-tx deployment address up front and adjusts code_address initialization. |
| test/state/host.hpp | Re-exports compute_create*_address() from the new library header; removes local declarations. |
| test/state/host.cpp | Removes prepare_message(), shifts nonce bumping into Host::call(), and relies on VM-populated msg.recipient for creates. |
| test/fuzzer/fuzzer.cpp | Stops synthesizing result.create_address from output bytes. |
| lib/evmone/instructions_calls.cpp | Computes create address in create_impl(), does EIP-2681 check in VM, warms created address (Berlin+), and pushes computed address on success. |
| lib/evmone/create_address.hpp | Introduces header-only compute_create_address() / compute_create2_address() helpers. |
| lib/evmone/CMakeLists.txt | Adds create_address.hpp to the library sources. |
| evmc/include/evmc/evmc.hpp | Removes Result::create_address exposure and the “create-result” constructor overload. |
| evmc/include/evmc/evmc.h | Bumps ABI version, clarifies CREATE recipient semantics, and removes evmc_result.create_address. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Comment on lines
+184
to
+186
| // The VM computes the created account's address (and warms it, EIP-2929) and | ||
| // performs the EIP-2681 nonce-overflow check before entering the create frame. | ||
| assert(msg.recipient != address{}); |
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## master #1589 +/- ##
=======================================
Coverage 97.39% 97.40%
=======================================
Files 164 164
Lines 14666 14655 -11
Branches 3390 3388 -2
=======================================
- Hits 14284 14274 -10
+ Misses 282 280 -2
- Partials 100 101 +1
Flags with carried forward coverage won't be shown. Click here to find out more.
🚀 New features to boost your workflow:
|
chfast
added a commit
that referenced
this pull request
Jul 14, 2026
compute_create_address() and compute_create2_address() are defined in
the testing host (test/state/host.{hpp,cpp}) although they are not
Host-specific, and the VM itself will need them once it computes the
create address instead of the Host (#1589).
Move them to the new TU lib/evmone/create_address.{hpp,cpp} in the
evmone namespace. The implementations are unchanged except the
keccak256() host-utils wrapper being replaced by the direct
ethash::keccak256() call. The functions are marked EVMC_EXPORT so the
testing code can still reach them across the libevmone shared-library
boundary (same as get_delegate_address()).
Also rename state_new_account_address_test.cpp (and its test suite) to
create_address_test.cpp to match.
Claude-Session: https://claude.ai/code/session_01R8uyb9z8VwgRrEKRanDPP8
chfast
added a commit
that referenced
this pull request
Jul 14, 2026
compute_create_address() and compute_create2_address() are defined in
the testing host (test/state/host.{hpp,cpp}) although they are not
Host-specific, and the VM itself will need them once it computes the
create address instead of the Host (#1589).
Move them to the new TU lib/evmone/create_address.{hpp,cpp} in the
evmone namespace. The implementations are unchanged except the
keccak256() host-utils wrapper being replaced by the direct
ethash::keccak256() call. The functions are marked EVMC_EXPORT so the
testing code can still reach them across the libevmone shared-library
boundary.
6b36008 to
81b3ba9
Compare
The create address was computed host-side (Host::prepare_message), one EVMC crossing too late: msg.recipient traveled down empty and was filled midway, the EIP-2681 nonce-overflow light-fail lived in the host while the depth and balance light-fails lived in the VM, the EIP-2929 warming happened host-side where EELS does it in the creating frame, and the parent could learn what it created only from evmc_result.create_address. Compute the address in create_impl instead: read the sender's nonce via get_nonce (unifying the EIP-2681 light-fail with depth/balance), derive the CREATE/CREATE2 address, warm it in the creating frame (EELS: generic_create), and pass it down in msg.recipient - the same VM-resolved-message pattern as code_address for EIP-7702 delegations. This leaves evmc_result.create_address and evmc_message.create2_salt without readers: drop both and bump EVMC_ABI_VERSION to 16. Host::prepare_message dissolves. The creator-nonce bump stays in Host::call before the state checkpoint: per the Yellow Paper it survives a failed creation. At depth 0, build_message computes the deployment address from tx.nonce. Behavior-identical: the EEST glamsterdam-devnet@v7.2.0 state-test failure set is bit-identical to master's. Claude-Session: https://claude.ai/code/session_01R8uyb9z8VwgRrEKRanDPP8
767d513 to
1258466
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The create address was computed host-side (Host::prepare_message), one
EVMC crossing too late: msg.recipient traveled down empty and was
filled midway, the EIP-2681 nonce-overflow light-fail lived in the host
while the depth and balance light-fails lived in the VM, the EIP-2929
warming happened host-side where EELS does it in the creating frame,
and the parent could learn what it created only from
evmc_result.create_address.
Compute the address in create_impl instead: read the sender's nonce via
get_nonce (unifying the EIP-2681 light-fail with depth/balance), derive
the CREATE/CREATE2 address, warm it in the creating frame,
and pass it down in msg.recipient - the same
VM-resolved-message pattern as code_address for EIP-7702 delegations.
This leaves evmc_result.create_address and evmc_message.create2_salt
without readers: drop both and bump EVMC_ABI_VERSION to 16.
Host::prepare_message dissolves. The creator-nonce bump stays in
Host::call before the state checkpoint: per the Yellow Paper it
survives a failed creation. At depth 0, build_message computes the
deployment address from tx.nonce.