Visibility modifiers
Every function and state variable in Solidity has a visibility level. Getting this wrong is one of the most common sources of security vulnerabilities.
public
Callable from anywhere: externally (from other contracts or wallets), internally (within the contract), and via the ABI. State variables marked public automatically get a getter function.
uint256 public totalSupply; // auto-generates a totalSupply() getter
function mint(address to, uint256 amount) public {
// Anyone can call this — be careful!
}external
Can only be called from outside the contract — not from within. Slightly cheaper than public for functions that only need external access, because arguments are read from calldata instead of being copied to memory.
function deposit() external payable {
// Can only be called from outside this contract
}internal
Callable from within the contract and from derived contracts (via inheritance). Not accessible from outside.
function _beforeTransfer(address from, address to, uint256 amount) internal {
// Shared logic used by multiple transfer functions
}private
Only callable from within the contract itself. Not accessible from derived contracts.
function _updateBalance(address account, uint256 newBalance) private {
balances[account] = newBalance;
}State mutability
State mutability describes what a function is allowed to do with contract state.
view
Promises not to modify state. Reading state variables is fine. Free to call (no gas) when called externally.
function balanceOf(address account) public view returns (uint256) {
return balances[account];
}pure
Cannot read or write state. Used for pure computation.
function toWei(uint256 ether_amount) public pure returns (uint256) {
return ether_amount * 1e18;
}payable
Allows the function to receive Ether. Functions without payable will revert if you send ETH to them.
function deposit() external payable {
require(msg.value > 0, 'Send some ETH');
balances[msg.sender] += msg.value;
}Return values
Functions can return multiple values using tuple syntax.
function getPoolInfo() external view returns (uint256 reserve0, uint256 reserve1, uint256 totalLiquidity) {
return (_reserve0, _reserve1, _totalLiquidity);
}Named return variables can be used to improve readability and skip the explicit return statement.
function divide(uint256 a, uint256 b) public pure returns (uint256 result, bool success) {
if (b == 0) return (0, false);
result = a / b;
success = true;
// no return statement needed — named variables are returned automatically
}