Solidity Reference
Free reference guide: Solidity Reference
About Solidity Reference
The Solidity Reference is a searchable quick-reference for Ethereum smart contract development. It covers fundamental types such as uint, int, address, and address payable, along with complex data structures like mapping, struct, and enum. Each entry includes production-ready code examples that demonstrate real-world usage patterns commonly found in ERC-20 tokens, DeFi protocols, and NFT contracts.
This reference organizes Solidity syntax into five core categories: Types, Functions, Events, Inheritance, and Storage. The Functions section covers visibility modifiers (public, private, internal, external), custom modifiers with the underscore placeholder pattern, payable functions for receiving ETH, and error handling with require, revert, and assert. The Events section explains how to define and emit events with indexed parameters for efficient off-chain log filtering.
The Inheritance and Storage sections address Solidity-specific concepts that differ from traditional programming languages. You can look up interface definitions for standards like IERC20, library usage with the "using for" syntax, and the critical distinction between storage, memory, and calldata data locations that directly impacts gas costs. All content runs entirely in your browser with no server calls.
Key Features
- Complete type reference covering uint/int sizes, address vs address payable, bool, bytes, and string
- Mapping and nested mapping syntax with real ERC-20 allowance examples
- Function visibility modifiers (public, private, internal, external) with usage guidelines
- Custom modifier patterns including onlyOwner and the underscore (_) placeholder
- Event definition with indexed parameters for efficient log filtering
- Error handling with require, revert, and assert including custom error messages
- Inheritance patterns for multi-contract systems with interface and library usage
- Storage vs memory vs calldata data location specifiers with gas cost implications
Frequently Asked Questions
What is the difference between address and address payable in Solidity?
An address holds a 20-byte Ethereum address and can check balances. An address payable additionally supports transfer() and send() methods for sending ETH. You cannot implicitly convert address to address payable; an explicit cast is required. Use address payable when the contract needs to send ETH to that address.
How do require, revert, and assert differ?
require() is used for input validation and preconditions; it refunds remaining gas on failure. revert() works like require but is useful inside if-else blocks and supports custom errors. assert() is reserved for internal invariant checks and consumes all remaining gas on failure, signaling a bug in the contract. In production code, require() is most commonly used.
When should I use storage vs memory vs calldata?
Storage is persistent on-chain data and is the most expensive. Memory is temporary and exists only during function execution. Calldata is read-only and used for external function parameters; it is cheaper than memory because no copy is made. Use calldata for external function inputs, memory for local variables, and storage only for state variables.
What does the indexed keyword do in Solidity events?
The indexed keyword on event parameters enables off-chain filtering of logs by that parameter value. Each event can have up to three indexed parameters. Indexed parameters are stored as topics in the transaction log rather than as data, making them searchable but limiting them to 32 bytes each.
How does Solidity handle multiple inheritance?
Solidity uses C3 linearization to resolve multiple inheritance. Contracts are listed after the "is" keyword from most base to most derived. When functions with the same name exist in multiple parents, the most derived version is used. The super keyword calls the next contract in the linearized hierarchy, not necessarily the direct parent.
What is the purpose of the modifier pattern with the underscore?
The underscore (_) in a modifier represents where the modified function's body is inserted. Code before the underscore runs as a precondition (e.g., require(msg.sender == owner)), and code after it runs as a postcondition. This pattern enables reusable access control checks, reentrancy guards, and state validation across multiple functions.
How do receive() and fallback() functions work?
receive() is triggered when a contract receives plain ETH with no calldata (e.g., via transfer or send). fallback() is called when no function matches the call signature or when ETH is sent with calldata. Both must be external. A contract needs at least receive() to accept plain ETH transfers; without it, direct transfers will revert.
What is the "using A for B" syntax in Solidity libraries?
"using SafeMath for uint256" attaches all library functions to the uint256 type, so you can call value.add(5) instead of SafeMath.add(value, 5). The library functions must have the type as their first parameter. This pattern is widely used for safe arithmetic, array utilities, and custom type extensions.