In this track: Execution traces and low-level calls
advanced · 4 MIN READ

msg.sender versus tx.origin

The immediate caller and transaction originator can differ.

LET’S PICTURE IT

The person handing you a form may differ from the person who first opened the request.

SEE IT FOR YOURSELF
A valid counter call, step by stepStep 1 / 4
A valid counter call, step by stepFunction requestincrement()No argumentsBefore executionstored count0A local teaching example with a defined starting stateIncoming callCheck function dispatchCheck coded conditionsRules passConditions passContinue executionA failed check can revert insteadCalculation0 + 1Result: 1Storage writecount = 1Persists if call succeedsCalculating a local value and storing it are separate stepsPersistent statecount1Later readGetter reports 1No new incrementState, logs and browser display have different roles

This example begins with count zero and a request to call increment(). No real contract is deployed.

Animated local teaching model. No wallet, RPC or live blockchain data. Some labels and hashes are abbreviated for readability.

Read the immediate caller

Under an ordinary call from A to B, msg.sender in B is A. It is not automatically the user who originally submitted the transaction.

Read transaction origin separately

tx.origin identifies the transaction originator under the EVM context. It remains transaction-wide through ordinary nested calls rather than tracking each immediate caller.

Avoid origin-based authorization

A malicious intermediary can be called by a user and then call another contract. Checking tx.origin alone can incorrectly treat the intermediary’s action as directly authorized.

Design explicit permissions

Use the appropriate caller and account authorization model for the application. Smart accounts, delegated execution and relaying make simplistic assumptions about a human caller unreliable.

Follow the execution

User → A → B
in B: msg.sender = A
in B: tx.origin = User

These fields answer different questions.

A local conceptual trace with explicit assumptions; this is not a trace of a live transaction.

QUICK CHECK · NO PRESSURE

For User → A → B under ordinary calls, who is msg.sender in B?

Your progress stays in this browser.
Keep exploring the original referenceethereum.org ↗

Original explanations by EtherTools. Examples are educational and source-linked; this site is independent of the Ethereum Foundation. Our approach.