Style Guide
Adhering to a consistent coding style is crucial for maintaining readability and quality across all Decentra projects. This style guide outlines the conventions that developers must follow when contributing code.
General Guidelines
File Names: Use
CamelCase
for contract names andsnake_case
for filenames.Line Length: Keep lines to a maximum of 80 characters.
Indentation: Use 4 spaces per indentation level. Do not use tabs.
Comments: Use
//
for single-line comments and/* ... */
for multi-line comments. Always use Natspec comments for public and external functions.
Contract and File Structure
Order of Elements: Arrange the elements in the following order:
Pragmas
Imports
Interfaces
Libraries
Contracts
Enums
Structs
State Variables
Events
Modifiers
Functions
State Variables
Grouping: Group state variables by their type and purpose. For example, keep all
uint
variables together, alladdress
variables together, and so on.Ordering: Order state variables from the most to the least important. Within groups, order them alphabetically.
Visibility: Explicitly define the visibility of state variables (
private
,internal
,public
).Naming: Use descriptive names in
camelCase
and avoid abbreviations.
Example:
contract Example {
// Grouped by type
uint256 public totalSupply;
uint256 private _decimals;
// Grouped by type
address public owner;
address private _admin;
// Grouped by purpose
mapping(address => uint256) private _balances;
mapping(address => mapping(address => uint256)) private _allowances;
}
To optimize storage slots, aim to group to uints of type 128 (for example) one after the other.
Functions
Order of Functions: Order functions by their visibility and purpose:
Constructor
Fallback function (if applicable)
External functions
Public functions
Internal functions
Private functions
Modifiers: List modifiers directly above the function they modify.
Ordering within Functions: Order arguments from inputs to outputs. For example,
function transfer(address recipient, uint256 amount)
.Function Naming: Use descriptive names in
camelCase
. Function names should start with a verb.
Example:
contract Example {
// Constructor
constructor() public {
// Initialization code
}
// External function
function transfer(address recipient, uint256 amount) external returns (bool) {
// Function code
}
// Public function
function approve(address spender, uint256 amount) public returns (bool) {
// Function code
}
// Internal function
function _transfer(address sender, address recipient, uint256 amount) internal {
// Function code
}
// Private function
function _calculateReward(address user) private view returns (uint256) {
// Function code
}
}
Function Parameters
Ordering: Order function parameters from inputs to outputs.
Naming: Use descriptive parameter names in
camelCase
. Avoid using single-letter names except for loop indices, function parameters are expected to have a "_" before them as an industry standard.
Example:
function setApprovalForAll(address _operator, bool _approved) external {
// Function code
}
Events
Naming: Use
PascalCase
for event names andcamelCase
for parameter names.Ordering Parameters: Order parameters with indexed fields first, followed by non-indexed fields.
Example:
event Transfer(address indexed from, address indexed to, uint256 value);
event Approval(address indexed owner, address indexed spender, uint256 value);
Error Handling
Revert Messages: Provide descriptive error messages in
require
,assert
, andrevert
statements.Custom Errors: Prefer using custom errors for gas optimization.
Example:
if (x <= y) {
revert InsufficientBalance()
}
custom errors are defined above the smart contract name declaration.
Import Statements
Order: Place import statements at the top of the file, grouped and ordered alphabetically.
Aliasing: Use aliasing to avoid naming conflicts.
Example:
import "./Ownable.sol";
import "./ERC20.sol";
Documentation
Natspec Comments: Use Natspec comments for all public and external functions, as well as for any complex internal logic.
Comment Placement: Place comments directly above the code they refer to.
Example:
/**
* @dev Transfers tokens to a specified address.
* @param _recipient The address to transfer to.
* @param _amount The amount to be transferred.
* @return A boolean value indicating whether the operation succeeded.
*/
function transfer(address _recipient, uint256 _amount) external returns (bool) {
// Function code
}
By following these style guidelines, you ensure that your code is consistent, readable, and maintainable. This contributes to the overall quality and reliability of Decentra projects.
Contributions that do no adhere to the style guide will be considered invalidated by default.