Solidity

msg.sender

msg.sender is the address that directly called the current Solidity function in the current EVM call context.

msg.sender is the immediate caller, which may be a wallet, router, proxy, relayer, or another contract.

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.sender is always an externally owned account.

  • Privileged functions callable through routers, callbacks, or relayers without explicit trust checks.

  • msg.sender checks inside proxy implementations that were not reviewed with the proxy call path.

  • Meta-transaction code that uses msg.sender instead of the recovered or forwarded user.

  • Comments that treat msg.sender and 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 delegatecall paths before trusting msg.sender checks in implementation code.

  • When msg.sender is only a transport address, require a trusted forwarder, recovered signer, or explicit role holder instead of treating the caller as the user.

Sources