Lesson 16 of 25
msg.sender & msg.value
Global variables — caller context, ETH value, and block information.
IntermediateTransaction Context Globals
Solidity provides built-in global variables that give you context about the current transaction and block. These are the most commonly used.
Solidity
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
contract ContextDemo {
function getContext() public payable returns (
address sender,
uint256 value,
uint256 gasLeft,
uint256 blockNum,
uint256 timestamp
) {
sender = msg.sender; // who called this function
value = msg.value; // how much ETH was sent
gasLeft = gasleft(); // remaining gas
blockNum = block.number; // current block number
timestamp = block.timestamp; // current block timestamp (Unix)
}
}
msg.sender in Access Control
msg.sender changes depending on who calls the function. When contracts call other contracts, msg.sender is the calling contract's address — not the original EOA.
Solidity
contract AccessControl {
address public owner;
mapping(address => bool) public admins;
constructor() { owner = msg.sender; }
modifier onlyOwner() {
require(msg.sender == owner, "Not owner");
_;
}
modifier onlyAdmin() {
require(admins[msg.sender] || msg.sender == owner, "Not admin");
_;
}
function addAdmin(address admin) public onlyOwner {
admins[admin] = true;
}
function adminAction() public onlyAdmin {
// accessible to owner AND admins
}
}
tx.origin vs msg.sender
tx.origin is the original EOA that started the transaction chain. NEVER use tx.origin for authorization — it is vulnerable to phishing attacks where a malicious contract tricks a user into calling it.
Solidity
// ❌ DANGEROUS — vulnerable to phishing
contract Unsafe {
address owner;
function withdraw() public {
require(tx.origin == owner); // WRONG!
// A malicious contract can trick the owner into calling it,
// which then calls this withdraw() — tx.origin is still owner!
}
}
// ✅ SAFE — use msg.sender
contract Safe {
address owner;
function withdraw() public {
require(msg.sender == owner); // msg.sender = direct caller only
}
}