Access control vulnerabilities are among the most common causes of smart contract exploits. When functions that should be restricted — like minting tokens, withdrawing funds, or upgrading logic — are callable by anyone, attackers can take full control of the contract.
Missing onlyOwner modifiers, incorrect role checks, or flawed initialization (where anyone can become the owner) are the typical culprits.
// VULNERABLE — no access check on a critical function
function mint(address to, uint256 amount) public {
_mint(to, amount); // anyone can mint unlimited tokens!
}
// Also vulnerable: initialization that can be called twice
function initialize(address owner) public {
_owner = owner; // no check if already initialized
}
import "@openzeppelin/contracts/access/Ownable.sol";
contract SafeToken is Ownable {
function mint(address to, uint256 amount) public onlyOwner {
_mint(to, amount);
}
// For upgradeable contracts, use initializer modifier
function initialize(address owner) public initializer {
__Ownable_init();
transferOwnership(owner);
}
}
initWallet() function let anyone become the owner, leading to $31 million stolen.Ownable or AccessControl for role-based permissions.modifier onlyOwner or role checks to every admin function.initializer modifier from OpenZeppelin's Initializable.public and external function to confirm that unrestricted access is intentional.