Skip to main content

natspec-standards

NatSpec documentation standards for Solidity contracts. Use when writing or reviewing contract documentation. Every public and external function must have NatSpec. Covers all tags, formatting conventions, and complete examples.

Source facts

Repository
ccashwell/evm-cortex
Last source activity
April 10, 2026 at 16:31
Detected SKILL.md language
English
Stars
131
Forks
18

Install options

The review-first prompt is selected by default. You can switch to a direct command or download a local copy.

Review the source files

Read SKILL.md and any companion files shown by SkillsMP before deciding whether to install.

Showing SKILL.md

SKILL.md
Source instructions · Read-only preview
name
natspec-standards
description
NatSpec documentation standards for Solidity contracts. Use when writing or reviewing contract documentation. Every public and external function must have NatSpec. Covers all tags, formatting conventions, and complete examples.
# NatSpec Standards ## Required Documentation Every public and external function **must** have NatSpec. Internal functions that are non-trivial should also be documented. ## Tags Reference | Tag | Context | Description | |-----|---------|-------------| | `@title` | Contract/interface | Title of the contract | | `@author` | Contract/interface | Author name or team | | `@notice` | Contract/function/event/error | User-facing explanation (shown in etherscan) | | `@dev` | Contract/function/event/error | Developer-facing technical details | | `@param` | Function/event/error | Describes a parameter | | `@return` | Function | Describes a return value | | `@inheritdoc` | Function | Inherits docs from parent contract | | `@custom:tag` | Any | Custom metadata (e.g., `@custom:security-contact` is mandatory) | ## Contract-Level Documentation ```solidity /// @title Staking Vault /// @author Uniswap Labs /// @notice Handles staking deposits and reward distribution for protocol governance tokens. /// @dev Uses ERC-4626 vault standard with custom reward distribution. /// Storage layout is proxy-compatible (see storage-layout skill). /// @custom:security-contact security@uniswap.org contract StakingVault is ERC4626, Ownable2Step, ReentrancyGuard { // ... } ``` ## Function Documentation ```solidity /// @notice Deposits tokens into the vault and mints shares to the caller. /// @dev Follows CEI pattern. Emits {Deposited} event. The share calculation /// uses the current exchange rate, which may be manipulated in the same /// block — see economic-attack-vectors for first-depositor defense. /// @param token The address of the ERC-20 token to deposit. /// @param amount The amount of tokens to deposit (in token's native decimals). /// @return shares The number of vault shares minted to the caller. function deposit(address token, uint256 amount) external nonReentrant whenNotPaused returns (uint256 shares) { if (token == address(0)) revert ZeroAddress(); if (amount == 0) revert ZeroAmount(); shares = convertToShares(amount); _mint(msg.sender, shares); IERC20(token).safeTransferFrom(msg.sender, address(this), amount); emit Deposited(msg.sender, token, amount, shares); } ``` ## Multiple Return Values Each return value gets its own `@return` tag, in order. ```solidity /// @notice Returns the position details for a given position ID. /// @param positionId The unique identifier of the position. /// @return owner The address that owns the position. /// @return collateral The amount of collateral deposited (in token decimals). /// @return debt The amount of debt owed (in token decimals). /// @return healthFactor The position's health factor (18 decimals, < 1e18 = liquidatable). function getPosition(uint256 positionId) external view returns ( address owner, uint256 collateral, uint256 debt, uint256 healthFactor ) { // ... } ``` ## @inheritdoc Use `@inheritdoc` to inherit documentation from a parent interface or abstract contract. Add `@dev` for implementation-specific details. ```solidity interface IVault { /// @notice Withdraws tokens by burning vault shares. /// @param shares The number of shares to burn. /// @return amount The number of tokens returned to the caller. function withdraw(uint256 shares) external returns (uint256 amount); } contract Vault is IVault { /// @inheritdoc IVault /// @dev Applies a withdrawal fee of 0.1% (10 bps). The fee is retained /// in the vault, increasing the share price for remaining holders. function withdraw(uint256 shares) external override returns (uint256 amount) { // ... } } ``` ## Event Documentation ```solidity /// @notice Emitted when a user deposits tokens into the vault. /// @param user The address of the depositor. /// @param token The address of the deposited token. /// @param amount The amount deposited (in token's native decimals). /// @param shares The number of vault shares minted. event Deposited(address indexed user, address indexed token, uint256 amount, uint256 shares); ``` ## Error Documentation ```solidity /// @dev Thrown when the oracle price feed returns data older than the staleness threshold. /// @param feed The address of the Chainlink price feed. /// @param updatedAt The timestamp of the last price update. /// @param threshold The maximum allowed age in seconds. error Oracle_StalePrice(address feed, uint256 updatedAt, uint256 threshold); ``` ## Custom Tags ```solidity /// @custom:security-contact security@protocol.xyz /// @custom:oz-upgrades-from StakingVaultV1 /// @custom:storage-location erc7201:protocol.storage.StakingVault contract StakingVaultV2 is StakingVaultV1 { // ... } ``` ## Modifier Documentation ```solidity /// @dev Restricts function access to the designated oracle updater. /// Reverts with {Unauthorized} if caller is not the updater. modifier onlyUpdater() { if (msg.sender != updater) revert Unauthorized(); _; } ``` ## Struct Documentation ```solidity /// @notice Represents a user's staking position. /// @dev Packed into 2 storage slots (64 bytes). See storage-layout skill. /// @param amount The staked token amount (18 decimals). /// @param rewardDebt Used for reward accounting (scaled by ACC_PRECISION). /// @param lockEnd The timestamp when the lock period expires. /// @param boostMultiplier The user's boost factor (100 = 1x, 200 = 2x). struct StakeInfo { uint256 amount; uint256 rewardDebt; uint48 lockEnd; uint16 boostMultiplier; } ``` ## NatSpec Checklist - [ ] Every contract has `@title`, `@author`, `@notice` - [ ] Every public/external function has `@notice`, `@param`, `@return` - [ ] Complex functions have `@dev` with implementation details - [ ] Events have `@notice` and `@param` for each parameter - [ ] Custom errors have `@dev` explaining trigger conditions - [ ] `@inheritdoc` used for interface implementations - [ ] `@custom:security-contact` on all deployable contracts - [ ] No redundant docs (don't restate what the code obviously does) - [ ] Units specified in `@param`/`@return` (decimals, bps, seconds) - [ ] Cross-references to related skills/patterns where helpful
View on GitHub