0
0
Blockchain / Solidityprogramming~7 mins

Transaction context (tx.origin vs msg.sender) in Blockchain / Solidity

Choose your learning style9 modes available
Introduction

Understanding tx.origin and msg.sender helps you know who started a transaction and who called a function in smart contracts.

When you want to check who originally started a transaction across multiple contract calls.
When you want to know the immediate caller of a function in a smart contract.
When building security checks to prevent unauthorized access in smart contracts.
When debugging or logging the flow of transactions in decentralized applications.
Syntax
Blockchain / Solidity
address txOrigin = tx.origin;
address msgSender = msg.sender;

tx.origin is the original external account that started the transaction.

msg.sender is the immediate caller of the current function.

Examples
This function returns the original address that started the transaction.
Blockchain / Solidity
function checkOrigin() public view returns (address) {
    return tx.origin;
}
This function returns the address that called this function directly.
Blockchain / Solidity
function checkSender() public view returns (address) {
    return msg.sender;
}
This example shows how tx.origin stays the same across calls, but msg.sender changes to the immediate caller.
Blockchain / Solidity
contract Caller {
    function callOther(address callee) public {
        OtherContract(callee).calledFunction();
    }
}

contract OtherContract {
    function calledFunction() public view returns (address origin, address sender) {
        return (tx.origin, msg.sender);
    }
}
Sample Program

This program has two contracts. Caller calls OtherContract. When callOther runs, tx.origin is the original user who started the transaction, and msg.sender inside calledFunction is the Caller contract.

Blockchain / Solidity
pragma solidity ^0.8.0;

contract OtherContract {
    function calledFunction() public view returns (address origin, address sender) {
        return (tx.origin, msg.sender);
    }
}

contract Caller {
    OtherContract other;

    constructor(address otherAddress) {
        other = OtherContract(otherAddress);
    }

    function callOther() public view returns (address origin, address sender) {
        return other.calledFunction();
    }
}
OutputSuccess
Important Notes

Never use tx.origin for authorization checks because it can be tricked by phishing attacks.

Use msg.sender to check who called your function directly for better security.

Remember, tx.origin is always an external account, never a contract.

Summary

tx.origin is the original external account that started the transaction.

msg.sender is the immediate caller of the current function.

Use msg.sender for secure access control in smart contracts.