Solidity Style Guide: Correct naming convention and function order
Naming Convention
Contract and Library Names
Contracts and libraries should adhere to the CapWords style. For example, consider names like SimpleToken
, SmartBank
, or StakingContract
. It's essential that the name of the contract or library matches its filename. For instance, if a contract file encompasses multiple contracts or libraries, the filename should align with the core contract, although it's preferable to avoid this scenario whenever possible.
Struct Names
Structs should follow the CapWords convention. For instance, MyCoin
, Position
, or PositionXY
are appropriately named structs.
Event Names
Events should be named using the CapWords style. For instance, Deposit
, Transfer
, Approval
, BeforeTransfer
, and AfterTransfer
are good examples of event names.
Function Names
Functions should utilize mixedCase. Consider functions like getBalance
, transfer
, verifyOwner
, addMember
, or changeOwner
as examples of correctly named functions.
Local and State Variable Names
Local and state variable names should also use mixedCase. Examples include totalSupply
, remainingSupply
, balancesOf
, creatorAddress
, isPreSale
, and tokenExchangeRate
.
Constants
Constants should be represented in all capital letters, with underscores separating words. For instance, consider constants like MAX_BLOCKS
, TOKEN_NAME
, TOKEN_TICKER
, or CONTRACT_VERSION
.
Modifier Names
Modifiers should also use mixedCase. Examples include onlyBy
, onlyAfter
, and onlyDuringThePreSale
.
Enums
Enums should adhere to the CapWords style. Examples include TokenGroup
, Frame
, HashStyle
, and CharacterLocation
.
Function Argument Names
Function arguments should follow mixedCase as well. Examples include initialSupply
, account
, recipientAddress
, senderAddress
, and newOwner
.
Underscore Prefix for Non-external Functions and Variables
Non-external functions and state variables, whether private or internal, should be prefixed with _singleLeadingUnderscore
.
Order of Functions
Functions should be organized based on their visibility, with constructors placed first, followed by receive and fallback functions (if they exist), then external, public, internal, and private functions. View and pure functions should be placed last within each visibility group.
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.25;
contract TestContract {
constructor() {
// ...
}
receive() external payable {
// ...
}
fallback() external {
// ...
}
// External functions
// ...
// External functions that are view
// ...
// External functions that are pure
// ...
// Public functions
// ...
// Internal functions
// ...
// Private functions
// ...
}
Function Declaration
The modifier order for a function declaration should follow this sequence: Visibility, Mutability, Virtual, Override, and Custom modifiers.
// Modifiers
modifier onlyOwner() {
require(msg.sender == owner, "Only owner can call this function");
_;
}
// Functions
function balance(uint256 from) public view returns (uint256) {
return balanceOf[from];
}
function shutdown() public onlyOwner {
selfdestruct(payable(owner));
}
Organization of Contract Components
The components of a contract should be arranged in the specified order:
- Pragma statements
- Import statements
- Interfaces
- Libraries
- Contracts
Within each contract, library, or interface, adhere to this arrangement:
- Type declarations
- State variables
- Events
- Errors
- Modifiers
- Functions
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.25;
// Pragma statements
import "example.sol";
// Interfaces
interface ExampleInterface {}
// Libraries
library ExampleLibrary {}
// Contracts
contract ExampleContract {
// Type declarations
struct ExampleStruct {}
// State variables
uint256 public exampleVariable;
// Events
event ExampleEvent();
// Modifiers
modifier exampleModifier {}
// Functions
function exampleFunction() public {}
}