Section 01 · Definition
What is the address type in Solidity?
An address is a 20 byte identity on Ethereum. It is how the chain refers to a wallet or a contract — and Solidity gives you a first-class type for it.
Quick answer
What is address? address is a Solidity value type that holds a 160-bit Ethereum identifier. It is most often the address of a user's wallet (an externally owned account, or EOA) or the address of another smart contract. Solidity treats it as its own type so the compiler can enforce the difference between an address that is allowed to receive ether (address payable) and one that is not.
Every transaction on Ethereum has a sender address and (for non-deployment transactions) a recipient address. Inside Solidity those values appear as msg.sender and address(this). You will store addresses inside mappings to track who owns what, inside arrays to keep lists of participants, and inside structs alongside other identity fields.
Section 02 · Where it comes from
How an address is derived
An Ethereum address is not random. It is the last 20 bytes of the keccak256 hash of a public key. That fact has practical consequences for security and verification.
Because addresses are derived from public keys (for EOAs) or from a known formula involving the deployer's address and nonce (for contracts), they are not guessable in any practical sense. Two different keys produce two different addresses. Two different deployers, or the same deployer at two different nonces, produce two different contract addresses. Before pasting any address into a contract, run it through the Ethereum Address Validator to confirm shape and EIP-55 checksum.
Section 03 · address payable
The payable modifier on the type itself
address payable is a stricter sub-type. The compiler will not let you call .transfer or .send on a plain address — you have to acknowledge the cast.
address public router; // can read state, can call functions
address payable public treasury; // can also receive ether
function pay(uint256 amount) external {
treasury.transfer(amount); // ok
// router.transfer(amount); // compile error
payable(router).transfer(amount); // explicit cast — only do this if you know router is safe
}The intent behind the split is safety. Sending ether to an address that does not have a payable fallback or receive function will revert, locking funds inside your contract until you fix the call. Forcing the developer to write payable(...) makes the assumption explicit and easier to audit.
Section 04 · Built-in members
What you can do with an address value
The address type comes with a small set of built-in members that you will use constantly. Memorise these — every contract reads or sets at least one of them.
address user = msg.sender;
uint256 wei_ = user.balance; // ether (in wei) held by the address
bytes memory bc = user.code; // bytecode at the address (empty for EOAs)
bytes32 hash_ = user.codehash; // keccak256 of code
// Low level call — the modern way to send ether or call any function
(bool ok, bytes memory data) = payable(user).call{value: 1 ether}("");
require(ok, "transfer failed");The legacy .transfer(amount) and .send(amount) forward only 2 300 gas, which can fail unexpectedly with contracts that have non-trivial fallback logic. The recommended pattern in modern Solidity is the low-level call shown above, combined with a reentrancy guard modifier when the call could give control back to the caller.
EOA vs contract address
There is no compile-time way to tell whether an address holds a wallet or a contract. The runtime check is `addr.code.length > 0` — non-zero means a contract is deployed there. Be careful: during a contract's own constructor, the address has no code yet, so the check returns false and gives a misleading answer.
Section 05 · Real-world uses
Where address shows up in production code
A short tour of the patterns you will see in the first contracts you read.
// 1. Owner / admin
address public owner;
// 2. ERC20 balances and allowances
mapping(address => uint256) public balanceOf;
mapping(address => mapping(address => uint256)) public allowance;
// 3. NFT ownership
mapping(uint256 => address) public ownerOf;
// 4. Whitelist
mapping(address => bool) public isWhitelisted;
// 5. Multisig signers
address[] public signers;
// 6. Hardcoded protocol contracts
address public constant USDC = 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48;