fix(evm): set tx_origin from sender address in CLI and state loader - #455
Conversation
ORIGIN opcode returned zero address because tx_origin was never set. loadState() now parses tx_origin from state.json, and the CLI falls back to --sender when tx_origin is still unset. This aligns DTVM behavior with Geth for contracts that read tx.origin.
⚡ Performance Regression Check Results✅ Performance Check Passed (interpreter)Performance Benchmark Results (threshold: 25%)
Summary: 194 benchmarks, 0 regressions ✅ Performance Check Passed (multipass)Performance Benchmark Results (threshold: 25%)
Summary: 194 benchmarks, 0 regressions |
There was a problem hiding this comment.
Pull request overview
Fixes EVM ORIGIN behavior in the CLI/state-loading path by ensuring tx_origin is populated from either loaded state or the sender address, aligning execution results with expected EVM semantics and updating affected tests.
Changes:
- Load
tx_originfromtx_contextinstate.jsonwhen present. - In the CLI, default
tx_originto the sender address when it’s otherwise unset. - Update EVM interpreter tests and the
originexpected output to reflect non-zeroORIGIN.
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
src/utils/evm.cpp |
Extends state loading to parse tx_origin from JSON tx_context. |
src/cli/dtvm.cpp |
Adds CLI fallback to set tx_origin from --sender. |
src/tests/evm_interp_tests.cpp |
Sets a non-zero default tx_origin for interpreter tests. |
tests/evm_asm/origin.expected |
Updates expected memory/return for ORIGIN-based test. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| // Set tx_origin from sender address (fallback if not loaded from state) | ||
| evmc::address SenderAddr = zen::utils::parseAddress(SenderAddress); | ||
| if (MockedHost.tx_context.tx_origin == evmc::address{}) { | ||
| MockedHost.tx_context.tx_origin = SenderAddr; | ||
| } |
There was a problem hiding this comment.
The fallback logic treats tx_origin == evmc::address{} as “not set”, but that can’t distinguish between “missing in loaded state” vs “explicitly set to zero address in state”. A safer approach is to set tx_origin from --sender before calling loadState(), and let loadState() override it only when the JSON contains tx_origin (including an explicit zero). This also avoids re-parsing the sender address multiple times.
- Move tx_origin initialization from a post-loadState fallback to pre-loadState default. This sets tx_origin from --sender before calling loadState(), allowing loadState() to override it when tx_origin is present in state.json. Avoids the ambiguity of treating zero address as 'not set' vs 'explicitly set to zero'. - Add tx_origin serialization in saveState() to keep save/load symmetric, preventing tx_origin from being lost during state round-tripping via --save-state/--load-state.
1. Does this PR affect any open issues?(Y/N) and add issue references (e.g. "fix #123", "re #123".):
2. What is the scope of this PR (e.g. component or file name):
3. Provide a description of the PR(e.g. more details, effects, motivations or doc link):
4. Are there any breaking changes?(Y/N) and describe the breaking changes(e.g. more details, motivations or doc link):
5. Are there test cases for these changes?(Y/N) select and add more details, references or doc links:
6. Release note