askill
crane-natspec

crane-natspecSafety 100Repository

This skill should be used when the user asks about "natspec", "documentation", "include-tag", "selector", "cast", "@custom:signature", "@custom:selector", "@custom:topiczero", "@custom:interfaceid", "AsciiDoc", or needs guidance on documenting Crane contracts with NatSpec and AsciiDoc include-tags.

0 stars
1.2k downloads
Updated 2/5/2026

Package Files

Loading files...
SKILL.md

Crane NatSpec & Documentation Standards

Crane uses NatSpec combined with AsciiDoc include-tags for accurate, extractable documentation.

AsciiDoc Include-Tags

Wrap documented symbols with include-tags for documentation extraction:

// tag::MySymbol[]
/// @notice Description of the symbol
function myFunction() external { ... }
// end::MySymbol[]

Tag Format Rules

  • Tag markers must match exactly (no extra spaces inside [])
  • Tag name should match the symbol being documented
  • Use PascalCase for tag names matching type names
  • Use camelCase for function tag names

Example Usage

// tag::transfer[]
/// @notice Transfers tokens to a recipient
/// @param to_ The recipient address
/// @param amount_ The amount to transfer
/// @return success True if transfer succeeded
/// @custom:signature transfer(address,uint256)
/// @custom:selector 0xa9059cbb
function transfer(address to_, uint256 amount_) external returns (bool success);
// end::transfer[]

Custom NatSpec Tags

Functions

TagPurposeExample
@custom:signatureCanonical signature stringtransfer(address,uint256)
@custom:selectorbytes4 selector0xa9059cbb
/// @notice Transfers tokens
/// @custom:signature transfer(address,uint256)
/// @custom:selector 0xa9059cbb
function transfer(address to_, uint256 amount_) external returns (bool);

Errors

TagPurposeExample
@custom:signatureCanonical error signatureNotOwner(address)
@custom:selectorbytes4 selector0x30cd7471
/// @notice Thrown when caller is not the owner
/// @custom:signature NotOwner(address)
/// @custom:selector 0x30cd7471
error NotOwner(address caller);

Events

TagPurposeExample
@custom:signatureCanonical event signatureTransfer(address,address,uint256)
@custom:topiczerobytes32 topic0 hash0xddf252ad...
/// @notice Emitted on token transfer
/// @custom:signature Transfer(address,address,uint256)
/// @custom:topiczero 0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef
event Transfer(address indexed from, address indexed to, uint256 amount);

Note: Events use @custom:topiczero (bytes32), not @custom:selector (bytes4).

ERC-165 Interfaces

TagPurposeExample
@custom:interfaceidbytes4 interface ID0x01ffc9a7
/// @title IERC165
/// @custom:interfaceid 0x01ffc9a7
interface IERC165 {
    function supportsInterface(bytes4 interfaceId) external view returns (bool);
}

Computing Values with cast

Use Foundry's cast to compute selectors and hashes:

Function Selector (bytes4)

cast sig "transfer(address,uint256)"
# Output: 0xa9059cbb

Error Selector (bytes4)

cast sig "NotOwner(address)"
# Output: 0x30cd7471

Event Topic0 (bytes32)

cast keccak "Transfer(address,address,uint256)"
# Output: 0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef

Interface ID (bytes4)

For interface IDs, prefer computing in Solidity:

bytes4 interfaceId = type(IMyInterface).interfaceId;

Or compute manually by XOR-ing all function selectors:

# Get each selector
cast sig "func1(uint256)"  # 0x12345678
cast sig "func2(address)"  # 0x87654321

# XOR them in Solidity or manually
bytes4 interfaceId = 0x12345678 ^ 0x87654321;

Complete Documentation Example

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.30;

// tag::IMyToken[]
/// @title IMyToken
/// @notice Interface for MyToken
/// @custom:interfaceid 0x36372b07
interface IMyToken {

    // tag::Transfer[]
    /// @notice Emitted when tokens are transferred
    /// @param from The sender address
    /// @param to The recipient address
    /// @param amount The amount transferred
    /// @custom:signature Transfer(address,address,uint256)
    /// @custom:topiczero 0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef
    event Transfer(address indexed from, address indexed to, uint256 amount);
    // end::Transfer[]

    // tag::InsufficientBalance[]
    /// @notice Thrown when transfer amount exceeds balance
    /// @param account The account with insufficient balance
    /// @param balance The current balance
    /// @param required The required amount
    /// @custom:signature InsufficientBalance(address,uint256,uint256)
    /// @custom:selector 0xcf479181
    error InsufficientBalance(address account, uint256 balance, uint256 required);
    // end::InsufficientBalance[]

    // tag::transfer[]
    /// @notice Transfers tokens to a recipient
    /// @param to_ The recipient address
    /// @param amount_ The amount to transfer
    /// @return success True if the transfer succeeded
    /// @custom:signature transfer(address,uint256)
    /// @custom:selector 0xa9059cbb
    function transfer(address to_, uint256 amount_) external returns (bool success);
    // end::transfer[]

    // tag::balanceOf[]
    /// @notice Returns the token balance of an account
    /// @param account_ The account to query
    /// @return balance The token balance
    /// @custom:signature balanceOf(address)
    /// @custom:selector 0x70a08231
    function balanceOf(address account_) external view returns (uint256 balance);
    // end::balanceOf[]
}
// end::IMyToken[]

Validation Checklist

For each documented symbol, verify:

  • Include-tags wrap the symbol correctly
  • Tag names match symbol names
  • @custom:signature matches actual signature exactly
  • @custom:selector computed correctly (functions/errors)
  • @custom:topiczero computed correctly (events)
  • @custom:interfaceid computed correctly (interfaces)
  • NatSpec params match function parameters

Additional Resources

Reference Files

  • references/natspec-examples.md - More complete examples

Quick Reference

Symbol TypeSelector TagHash Type
Function@custom:selectorbytes4
Error@custom:selectorbytes4
Event@custom:topiczerobytes32
Interface@custom:interfaceidbytes4 (XOR of selectors)

Install

Download ZIP
Requires askill CLI v1.0+

AI Quality Score

95/100Analyzed 2/11/2026

An excellent, high-density technical reference for documenting Solidity contracts. It combines NatSpec with AsciiDoc tags and provides actionable CLI commands for computing selectors and hashes.

100
95
85
95
98

Metadata

Licenseunknown
Version-
Updated2/5/2026
Publishermajiayu000

Tags

No tags yet.