Skip to content

For AI agents: a documentation index is available at /llms.txt. Every page is also available as Markdown at the same URL with a .md suffix, or by requesting Accept: text/markdown.

BLOK Capital

Guía de estilo para contratos inteligentes

Convenciones de nomenclatura 1. Visión arquitectónica Nuestro protocolo utiliza una arquitectura modular de diamante/faceta, donde cada faceta encapsula…

Última actualización:

Convenciones de nomenclatura#

1. Visión arquitectónica#

Nuestro protocolo utiliza una arquitectura modular de diamante/faceta, donde cada faceta encapsula un dominio específico (p. ej., intercambios Uniswap, creación de gardens, control de acceso). Las facetas exponen interfaces externas, delegan la lógica a contratos base internos y usan bibliotecas de almacenamiento para la gestión del estado. Este patrón permite la posibilidad de actualizaciones (upgradability), separación de responsabilidades y límites claros entre las funcionalidades del protocolo.
Ejemplo: Faceta Uniswap

  • Faceta externa: UniswapFacet expone funciones de swap y TWAP.
  • Interfaz: IUniswap define la API externa y los structs de parámetros.
  • Base interna: UniswapBase implementa la lógica central, sólo invocable por la faceta.
  • Biblioteca de almacenamiento: UniswapStorage gestiona el estado persistente.
  • Biblioteca de errores: IUniswapBase define errores y eventos.

2. Convenciones de nomenclatura#

Contratos y Facetas

  • Contratos de faceta: Sufijo Facet (p. ej., UniswapFacet).
  • Contratos base: Sufijo Base (p. ej., UniswapBase).
  • Bibliotecas de almacenamiento: Sufijo Storage (p. ej., UniswapStorage).
  • Interfaces: Prefijo I (p. ej., IUniswap).
  • Interfaces base: Prefijo I y sufijo Base (p. ej., IUniswapBase).

Funciones

  • Funciones externas: Usar nombres descriptivos en camelCase (p. ej., swapExactInputSingleHop).
  • Funciones internas: Prefijar con _ (p. ej., _swapExactInputSingleHop).
  • Inicialización: Sufijo _init (p. ej., UniswapFacet_init).

Structs

  • Structs de parámetros: Sufijo Params (p. ej., GardenSwapParams).
  • Tipos compuestos: Usar nombres descriptivos (p. ej., TokenWithFee).

Errores

  • Prefijo de dominio: Prefijar con el nombre de la faceta (p. ej., UniswapFacet_InsufficientBalance).
  • Descriptivos: Usar PascalCase, describir el fallo (p. ej., UniswapFacet_SwapDeadlineHasPassed).

Eventos

  • Tiempo pasado: Usar pasado para cambios de estado (p. ej., UniswapFacetTokensSwapped).
  • Prefijo de dominio: Prefijar con el nombre de la faceta para mayor claridad.

Variables

  • Variables de estado: Privadas, con prefijo _ en contratos base, almacenadas en bibliotecas de almacenamiento.
  • Variables dentro de structs: Usar camelCase, descriptivas.

Carpetas

  • Facetas: Cada faceta debe tener una carpeta separada.
  • Descriptivas: Usar camelCase (p. ej., liquidityPoolRegistry).

/*###############################################################################
 
    @title Diamond
    @author BLOK Capital DAO
 
    ▗▄▄▖ ▗▖    ▗▄▖ ▗▖ ▗▖     ▗▄▄▖ ▗▄▖ ▗▄▄▖▗▄▄▄▖▗▄▄▄▖▗▄▖ ▗▖       ▗▄▄▄  ▗▄▖  ▗▄▖ 
    ▐▌ ▐▌▐▌   ▐▌ ▐▌▐▌▗▞▘    ▐▌   ▐▌ ▐▌▐▌ ▐▌ █    █ ▐▌ ▐▌▐▌       ▐▌  █▐▌ ▐▌▐▌ ▐▌
    ▐▛▀▚▖▐▌   ▐▌ ▐▌▐▛▚▖     ▐▌   ▐▛▀▜▌▐▛▀▘  █    █ ▐▛▀▜▌▐▌       ▐▌  █▐▛▀▜▌▐▌ ▐▌
    ▐▙▄▞▘▐▙▄▄▖▝▚▄▞▘▐▌ ▐▌    ▝▚▄▄▖▐▌ ▐▌▐▌  ▗▄█▄▖  █ ▐▌ ▐▌▐▙▄▄▖    ▐▙▄▄▀▐▌ ▐▌▝▚▄▞▘
 
 
################################################################################*/

Orden de disposición de los elementos del contrato inteligente#

Los elementos del contrato deben disponerse en el siguiente orden:

  1. Sentencias pragma
  2. Sentencias import
  3. Eventos
  4. Errores
  5. Interfaces
  6. Bibliotecas (libraries)
  7. Contratos

Dentro de cada contrato, biblioteca o interfaz, use el siguiente orden:

  1. Declaraciones de tipos (type declarations)
  2. Variables de estado
  3. Eventos
  4. Errores
  5. Modificadores
  6. Funciones

Siga la guía oficial de Solidity para más detalles: link

Orden de las funciones#

El orden ayuda a los lectores a identificar qué funciones pueden llamar y a encontrar el constructor y las definiciones receive / fallback más fácilmente.

Las funciones deben agruparse según su visibilidad y ordenarse:

  • constructor
  • función receive (si existe)
  • función fallback (si existe)
  • external
  • public
  • internal
  • private

Dentro de un mismo grupo, colocar las funciones view y pure al final.


// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.7.0 <0.9.0;
 
contract A {
    constructor() {
        // ...
    }
 
    receive() external payable {
        // ...
    }
 
    fallback() external {
        // ...
    }
 
    // External functions
    // ...
 
    // External functions that are view
    // ...
 
    // External functions that are pure
    // ...
 
    // Public functions
    // ...
 
    // Internal functions
    // ...
 
    // Private functions
    // ...
}

Contrato de ejemplo#

El siguiente bloque mantiene el código tal cual; los comentarios de documentación en inglés se pueden traducir si lo desea, pero se mantiene la sintaxis original para garantizar compatibilidad.

// SPDX-License-Identifier: GPL-3.0
/*###############################################################################
 
    @title Diamond
    @author BLOK Capital DAO
 
    ▗▄▄▖ ▗▖    ▗▄▖ ▗▖ ▗▖     ▗▄▄▖ ▗▄▖ ▗▄▄▖▗▄▄▄▖▗▄▄▄▖▗▄▖ ▗▖       ▗▄▄▄  ▗▄▖  ▗▄▖ 
    ▐▌ ▐▌▐▌   ▐▌ ▐▌▐▌▗▞▘    ▐▌   ▐▌ ▐▌▐▌ ▐▌ █    █ ▐▌ ▐▌▐▌       ▐▌  █▐▌ ▐▌▐▌ ▐▌
    ▐▛▀▚▖▐▌   ▐▌ ▐▌▐▛▚▖     ▐▌   ▐▛▀▜▌▐▛▀▘  █    █ ▐▛▀▜▌▐▌       ▐▌  █▐▛▀▜▌▐▌ ▐▌
    ▐▙▄▞▘▐▙▄▄▖▝▚▄▞▘▐▌ ▐▌    ▝▚▄▄▖▐▌ ▐▌▐▌  ▗▄█▄▖  █ ▐▌ ▐▌▐▙▄▄▖    ▐▙▄▄▀▐▌ ▐▌▝▚▄▞▘
 
 
################################################################################*/
 
pragma solidity ^0.8.24;
 
/*//////////////////////////////////////////////////////////////
                            IMPORTS
//////////////////////////////////////////////////////////////*/
 
import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
 
/*//////////////////////////////////////////////////////////////
                           CONTRACTS
//////////////////////////////////////////////////////////////*/
 
/// @title ProtocolTemplate
/// @notice A starting point for BLOK Capital protocol modules adhering to the style guide.
/// @dev Replace placeholders with domain-specific logic. Follow visibility and layout ordering strictly.
contract ProtocolTemplate {
    /*//////////////////////////////////////////////
                1) TYPE DECLARATIONS
    //////////////////////////////////////////////*/
 
    /// @notice Example struct for cohesive configuration/state.
    struct Config {
        // slot 0
        address admin;     // privileged controller (e.g., DAO multisig or Diamond facet admin)
        // slot 1
        uint96  feeBps;    // example fee in basis points
        bool    paused;    // simple circuit breaker
    }
 
    /*//////////////////////////////////////////////
                2) STATE VARIABLES
    //////////////////////////////////////////////*/
 
    /// @notice Packed configuration/state.
    Config private _cfg;
 
    /// @notice Generic key-value parameters (optional pattern).
    mapping(bytes32 => uint256) private _params;
 
    /// @notice Example immutable version tag for off-chain tooling.
    string public constant VERSION = "v0.1.0-template";
 
    /*//////////////////////////////////////////////
                    3) EVENTS
    //////////////////////////////////////////////*/
    /// @notice Emitted when the admin address is updated.
    /// @param oldAdmin The previous admin.
    /// @param newAdmin The new admin.
    event AdminUpdated(address indexed oldAdmin, address indexed newAdmin);
 
    /*//////////////////////////////////////////////
                    4) ERRORS
    //////////////////////////////////////////////*/
    /// @notice Thrown when a caller that is not the admin invokes an admin-only function.
    error NotAdmin();
 
    /// @notice Thrown when an operation uses a zero address where it is not allowed.
    error ZeroAddress();
 
    /*//////////////////////////////////////////////
                    5) MODIFIERS
    //////////////////////////////////////////////*/
 
    /// @notice Restricts function to the current admin.
    modifier onlyAdmin() {
        if (msg.sender != _cfg.admin) revert NotAdmin();
        _;
    }
 
    /// @notice Reverts when the contract is paused.
    modifier whenNotPaused() {
        if (_cfg.paused) revert InvalidParameter(LibKeys.K_PAUSED, 1);
        _;
    }
 
    /*//////////////////////////////////////////////
                    6) FUNCTIONS
    //////////////////////////////////////////////*/
 
    //------------- Constructor -------------
 
    /// @notice Initializes the template with an admin and optional initial params.
    /// @param initialAdmin The admin address (DAO, multisig, or Diamond owner).
    /// @param initialFeeBps Initial fee basis points (0–10_000).
    /// @param initiallyPaused Whether the module starts paused.
    constructor(address initialAdmin, uint96 initialFeeBps, bool initiallyPaused) {
        if (initialAdmin == address(0)) revert ZeroAddress();
        if (initialFeeBps > 10_000) revert InvalidParameter(LibKeys.K_FEE_BPS, initialFeeBps);
 
        _cfg.admin = initialAdmin;
        _cfg.feeBps = initialFeeBps;
        _cfg.paused = initiallyPaused;
 
        _params[LibKeys.K_FEE_BPS] = initialFeeBps;
        _params[LibKeys.K_PAUSED] = initiallyPaused ? 1 : 0;
    }
 
    //------------- Receive (if exists) -------------
 
    /// @notice Accepts ETH transfers.
    receive() external payable {
        // Intentionally empty. Consider emitting an event if tracking deposits is required.
    }
 
    //------------- Fallback (if exists) -------------
 
    /// @notice Fallback for non-matching function selectors.
    fallback() external payable {
        // Intentionally empty. Consider delegating or reverting depending on module design.
    }
 
    //------------- External -------------
 
    /// @notice Update the admin address.
    /// @param newAdmin The new admin address.
    /// @dev External to keep the interface surface clear; restricted via onlyAdmin.
    function setAdmin(address newAdmin) external onlyAdmin {
        if (newAdmin == address(0)) revert ZeroAddress();
        address old = _cfg.admin;
        _cfg.admin = newAdmin;
        emit AdminUpdated(old, newAdmin);
    }
 
    /// @notice Update a numeric parameter by key.
    /// @param key The parameter key (see LibKeys).
    /// @param value The new value.
    /// @dev Example: setting FEE_BPS or PAUSED.
    function setParam(bytes32 key, uint256 value) external onlyAdmin {
        uint256 old = _params[key];
 
        // Example validation: enforce bounds for known keys.
        if (key == LibKeys.K_FEE_BPS) {
            if (value > 10_000) revert InvalidParameter(key, value);
            _cfg.feeBps = uint96(value);
        } else if (key == LibKeys.K_PAUSED) {
            _cfg.paused = (value != 0);
        }
 
        _params[key] = value;
        emit ParamUpdated(key, old, value);
    }
 
    //------------- External view -------------
 
    /// @inheritdoc IProtocolTemplate
    function admin() external view returns (address) {
        return _cfg.admin;
    }
 
    /// @inheritdoc IProtocolTemplate
    function getParam(bytes32 key) external view returns (uint256 value) {
        return _params[key];
    }
 
    /// @notice Get the current fee in basis points.
    function feeBps() external view returns (uint96) {
        return _cfg.feeBps;
    }
 
    /// @notice Return whether the contract is paused.
    function paused() external view returns (bool) {
        return _cfg.paused;
    }
 
    //------------- Public -------------
 
    /// @notice Example public function demonstrating the `whenNotPaused` guard.
    /// @dev Replace with real business logic (e.g., deposit/withdraw/swap).
    function exampleAction(uint256 amount) public whenNotPaused {
        // Implement domain-specific logic. This is a stub.
        // e.g., _takeFee(amount); _doSomething(amount);
        amount; // silence compiler warning for template
    }
 
    //------------- Internal -------------
 
    /// @notice Example internal helper to compute a fee.
    /// @param amount The gross amount.
    /// @return fee The computed fee based on current feeBps.
    function _computeFee(uint256 amount) internal view returns (uint256 fee) {
        unchecked {
            fee = (amount * _cfg.feeBps) / 10_000;
        }
    }
 
    //------------- Private -------------
 
    // Add private helpers as needed, placed after internal functions.
}

Plantilla de contrato#

La plantilla siguiente se mantiene en su forma original de código. Si desea, puedo traducir los comentarios /// @notice y otros comentarios en el código al español también.

// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.24;
/*###############################################################################
 
    @title Enter contract title
    @author BLOK Capital DAO
    @notice Enter contract utility
 
    ▗▄▄▖ ▗▖    ▗▄▖ ▗▖ ▗▖     ▗▄▄▖ ▗▄▖ ▗▄▄▖▗▄▄▄▖▗▄▄▄▖▗▄▖ ▗▖       ▗▄▄▄  ▗▄▖  ▗▄▖ 
    ▐▌ ▐▌▐▌   ▐▌ ▐▌▐▌▗▞▘    ▐▌   ▐▌ ▐▌▐▌ ▐▌ █    █ ▐▌ ▐▌▐▌       ▐▌  █▐▌ ▐▌▐▌ ▐▌
    ▐▛▀▚▖▐▌   ▐▌ ▐▌▐▛▚▖     ▐▌   ▐▛▀▜▌▐▛▀▘  █    █ ▐▛▀▜▌▐▌       ▐▌  █▐▛▀▜▌▐▌ ▐▌
    ▐▙▄▞▘▐▙▄▄▖▝▚▄▞▘▐▌ ▐▌    ▝▚▄▄▖▐▌ ▐▌▐▌  ▗▄█▄▖  █ ▐▌ ▐▌▐▙▄▄▖    ▐▙▄▄▀▐▌ ▐▌▝▚▄▞▘
 
 
################################################################################*/
 
 
/*//////////////////////////////////////////////////////////////
                            IMPORTS
//////////////////////////////////////////////////////////////*/
 
/*//////////////////////////////////////////////////////////////
                           CONTRACTS
//////////////////////////////////////////////////////////////*/
 
contract ProtocolTemplate {
    /*//////////////////////////////////////////////
                1) TYPE DECLARATIONS
    //////////////////////////////////////////////*/
 
 
    /*//////////////////////////////////////////////
                2) STATE VARIABLES
    //////////////////////////////////////////////*/
 
    /// constant
    /// public  
    /// private
    /// mapping
    
    /*//////////////////////////////////////////////
                    3) EVENTS
    //////////////////////////////////////////////*/
 
 
    /*//////////////////////////////////////////////
                    4) ERRORS
    //////////////////////////////////////////////*/
 
 
    /*//////////////////////////////////////////////
                    5) MODIFIERS
    //////////////////////////////////////////////*/
 
 
    /*//////////////////////////////////////////////
                    6) FUNCTIONS
    //////////////////////////////////////////////*/
 
    //------------- Constructor -------------
 
    //------------- Receive (if exists) -------------
 
    //------------- Fallback (if exists) -------------
 
    //------------- External -------------
 
    //------------- External view -------------
 
    //------------- Public -------------
 
    //------------- Internal -------------
 
    //------------- Private -------------
 
    // Add private helpers as needed, placed after internal functions.
}