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
This example begins with count zero and a request to call increment(). No real contract is deployed.
This example begins with count zero and a request to call increment(). No real contract is deployed.Execution follows the code’s input and permission rules. A website button is not the access-control mechanism.The function reads zero, calculates zero plus one, and writes one to persistent storage.The accepted state contains count one. Later reads can inspect it. Events are emitted only if the code implements them.
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?