Solidity Style Guide: Correct naming convention and function order

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.

Structs should follow the CapWords convention. For instance, MyCoin, Position, or PositionXY are appropriately named structs.

Events should be named using the CapWords style. For instance, Deposit, Transfer, Approval, BeforeTransfer, and AfterTransfer are good examples of event 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 should also use mixedCase. Examples include totalSupply, remainingSupply, balancesOf, creatorAddress, isPreSale, and tokenExchangeRate.

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.

Modifiers should also use mixedCase. Examples include onlyBy, onlyAfter, and onlyDuringThePreSale.

Enums should adhere to the CapWords style. Examples include TokenGroup, Frame, HashStyle, and CharacterLocation.

Function arguments should follow mixedCase as well. Examples include initialSupply, account, recipientAddress, senderAddress, and newOwner.

Non-external functions and state variables, whether private or internal, should be prefixed with _singleLeadingUnderscore.

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
    // ...
}

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));
    }

The components of a contract should be arranged in the specified order:

  1. Pragma statements

  2. Import statements

  3. Interfaces

  4. Libraries

  5. Contracts

Within each contract, library, or interface, adhere to this arrangement:

  1. Type declarations

  2. State variables

  3. Events

  4. Errors

  5. Modifiers

  6. 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 {}
}