Claude-skill-registry crane-natspec
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.
install
source · Clone the upstream repo
git clone https://github.com/majiayu000/claude-skill-registry
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/majiayu000/claude-skill-registry "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/data/crane-natspec" ~/.claude/skills/majiayu000-claude-skill-registry-crane-natspec && rm -rf "$T"
manifest:
skills/data/crane-natspec/SKILL.mdsource content
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
| Tag | Purpose | Example |
|---|---|---|
| Canonical signature string | |
| bytes4 selector | |
/// @notice Transfers tokens /// @custom:signature transfer(address,uint256) /// @custom:selector 0xa9059cbb function transfer(address to_, uint256 amount_) external returns (bool);
Errors
| Tag | Purpose | Example |
|---|---|---|
| Canonical error signature | |
| bytes4 selector | |
/// @notice Thrown when caller is not the owner /// @custom:signature NotOwner(address) /// @custom:selector 0x30cd7471 error NotOwner(address caller);
Events
| Tag | Purpose | Example |
|---|---|---|
| Canonical event signature | |
| bytes32 topic0 hash | |
/// @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
| Tag | Purpose | Example |
|---|---|---|
| bytes4 interface ID | |
/// @title IERC165 /// @custom:interfaceid 0x01ffc9a7 interface IERC165 { function supportsInterface(bytes4 interfaceId) external view returns (bool); }
Computing Values with cast
castUse 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
-
matches actual signature exactly@custom:signature -
computed correctly (functions/errors)@custom:selector -
computed correctly (events)@custom:topiczero -
computed correctly (interfaces)@custom:interfaceid - NatSpec params match function parameters
Additional Resources
Reference Files
- More complete examplesreferences/natspec-examples.md
Quick Reference
| Symbol Type | Selector Tag | Hash Type |
|---|---|---|
| Function | | bytes4 |
| Error | | bytes4 |
| Event | | bytes32 |
| Interface | | bytes4 (XOR of selectors) |