Layout of a Source File
6.1 Structure
// SPDX-License-Identifier: MIT // 1. license identifier (machine-readable)
pragma solidity ^0.8.24; // 2. version pragma
pragma abicoder v2; // (default since 0.8.0 — optional)
import "./Token.sol"; // 3. imports
import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol";
import * as Utils from "./Utils.sol";
uint256 constant MAX_SUPPLY = 1_000_000e18; // 4. file-level constants
error Unauthorized(address caller); // file-level errors
event Log(string message); // file-level events (0.8.22+)
struct Point { uint128 x; uint128 y; } // file-level structs and enums
enum Status { Pending, Active, Closed }
type Price is uint256; // user-defined value types
function square(uint256 x) pure returns (uint256) { return x * x; } // free functions
interface IExample { function ping() external returns (bool); }
library MathLib { function max(uint256 a, uint256 b) internal pure returns (uint256) { return a > b ? a : b; } }
abstract contract Base { function hook() internal virtual; }
contract Example is Base
…6.2 SPDX license identifier
The compiler warns if it is missing. Common values: MIT, GPL-3.0-or-later, Apache-2.0, BUSL-1.1, UNLICENSED (proprietary).
6.3 Version pragmas
pragma solidity 0.8.28; pragma solidity ^0.8.20; ≥ 0.8.20 and < 0.9.0 pragma solidity >=0.8.4 <0.9.0; pragma experimental SMTChecker; old way to enable SMTChecker (now a compiler setting)
6.4 Imports
import "./A.sol"; // imports all global symbols (discouraged — pollutes namespace)
import {A, B as Bee} from "./AB.sol"; // named imports (preferred)
import * as Lib from "./Lib.sol"; // namespace import: Lib.Something
import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; // resolved through remappings / node_modules6.5 Comments and NatSpec
NatSpec tags: @title, @author, @notice, @dev, @param, @return, @inheritdoc, @custom:<name> (e.g., @custom:security-contact, @custom:oz-upgrades-unsafe-allow).
// single-line comment
/* multi-line
comment */
/// @title Vault
/// @author Your Name
/// @notice Explains to end users what this does
/// @dev Explains to developers extra details
contract Vault {
/// @notice Deposit Ether
/// @param minShares Minimum shares expected (slippage protection)
/// @return shares The number of shares minted
function deposit(uint256 minShares) external payable returns (uint256 shares) {
shares = msg.value;
require(shares >= minShares, "slippage");
}
}6.6 Naming conventions (Solidity style guide)
Contracts, libraries, structs, events, errors, enums TokenVault, Transfer Functions, variables, modifiers balanceOf, onlyOwner UPPER_CASE or mixedCase (projects vary) OWNER, i_owner Private/internal members often _leadingUnderscore constructor, receive, fallback, external, public, internal, private; view/pure last within each group