Access Control
Authorization
Missing or incorrect access control is one of the most common smart contract vulnerabilities. Functions meant to be restricted can be called by anyone.
Common Access Control Issues
solidity
// VULNERABLE: Missing access control
contract Vulnerable {
address public owner;
constructor() {
owner = msg.sender;
}
// Anyone can call this!
function setOwner(address newOwner) public {
owner = newOwner;
}
// Missing modifier
function withdrawAll() public {
payable(owner).transfer(address(this).balance);
}
}
// SECURE: Proper access control
contract Secure {
address public owner;
modifier onlyOwner() {
require(msg.sender == owner, "Not owner");
_;
}
function setOwner(address newOwner) public onlyOwner {
owner = newOwner;
}
function withdrawAll() public onlyOwner {
payable(owner).transfer(address(this).balance);
}
}tx.origin Phishing
solidity
// VULNERABLE: Using tx.origin for auth
contract TxOriginVictim {
address public owner;
function withdrawAll() public {
require(tx.origin == owner); // BAD!
payable(msg.sender).transfer(address(this).balance);
}
}
// ATTACK: Trick owner into calling attacker contract
contract TxOriginAttacker {
TxOriginVictim victim;
address attacker;
constructor(address _victim) {
victim = TxOriginVictim(_victim);
attacker = msg.sender;
}
// Owner calls this function (e.g., via phishing)
// tx.origin is still the owner!
function attack() public {
victim.withdrawAll(); // Passes tx.origin check
}
}Always Use msg.sender
Never use tx.origin for authentication. It can be manipulated through
intermediate contract calls.