msg.sender Explained in Detail
msg.sender is the direct caller of the current function. If a wallet calls a contract directly, msg.sender is the wallet. If a router calls the contract, msg.sender is the router.
This makes msg.sender the normal starting point for access control, but it is not always the human user behind the transaction. Contracts can call contracts, proxies can delegate execution, and relayers can submit actions on behalf of users.
Smart contract example
The check below only allows the immediate caller to withdraw:
function withdraw() external {
require(msg.sender == owner, "not owner");
payable(owner).transfer(address(this).balance);
}
That is safer than tx.origin authorization, but it still needs context. If owner is expected to be a multisig, proxy admin, or trusted forwarder, the caller path must match that design.
msg.sender in Auditing
Auditors trace every route that can set msg.sender for privileged code: direct calls, routers, callbacks, proxies, relayers, and smart wallets.
msg.sender also behaves differently around delegatecall. A delegated implementation executes in the proxy's storage context while preserving the caller seen by the proxy, so authorization must be reviewed against the full proxy call path.
Red flags in code
-
Authorization that assumes
msg.senderis always an externally owned account. -
Privileged functions callable through routers, callbacks, or relayers without explicit trust checks.
-
msg.senderchecks inside proxy implementations that were not reviewed with the proxy call path. -
Meta-transaction code that uses
msg.senderinstead of the recovered or forwarded user. -
Comments that treat
msg.senderand tx.origin as interchangeable.
How to test or review it
-
Trace every caller that can reach privileged functions.
-
Test direct wallet calls, contract-mediated calls, and proxy calls separately.
-
Confirm whether smart wallets, routers, and relayers should be supported.
-
Review
delegatecallpaths before trustingmsg.senderchecks in implementation code. -
When
msg.senderis only a transport address, require a trusted forwarder, recovered signer, or explicit role holder instead of treating the caller as the user.
Keep learning this topic
tx.origin
tx.origin is a Solidity global variable that returns the original externally owned account that started the transaction.
Access Control Vulnerability
An access control vulnerability lets an unauthorized caller perform privileged actions such as moving funds, changing roles, upgrading contracts, or changing protocol settings.
Delegatecall
Delegatecall executes code from another contract while reading and writing the caller's storage, preserving the original caller context.
Access Control Attacks
Access control attacks in Solidity: broken authorization patterns, privilege escalation paths, and secure role and ownership design.
Phishing Attacks
Phishing attacks targeting smart contract users and teams: common social-engineering vectors, wallet risks, and practical prevention controls.
Delegatecall & Call Injection Attacks
Delegatecall and call injection attacks in Solidity: storage collision exploits, proxy vulnerabilities like Parity, and secure upgrade patterns.
Smart Contract Audit Checklist
Use this SCH tool to turn the concept into practical audit work.
Practice this in real audit scenarios
Definitions help, but auditors need reps. SCH turns concepts like msg.sender into exploit labs, code review habits, and report-writing practice.
Start the free trial or see the full smart contract auditing course.