Claude-skill-registry crane-tokens
This skill should be used when the user asks to "deploy an ERC20 token", "create a token", "implement ERC20", "add permit to token", "mint/burn functionality", "ERC4626 vault", "tokenized vault", "ERC721 NFT", or needs guidance on token standards implementation with Crane's Diamond Factory Packages.
git clone https://github.com/majiayu000/claude-skill-registry
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-tokens" ~/.claude/skills/majiayu000-claude-skill-registry-crane-tokens && rm -rf "$T"
skills/data/crane-tokens/SKILL.mdCrane Token Components
Crane provides pre-built Diamond Factory Packages (DFPkg) for deploying ERC20, ERC20Permit, and ERC4626 tokens as Diamond proxies.
Token Package Selection
| Need | Package | Features |
|---|---|---|
| Basic ERC20 | | Transfer, approve, metadata |
| ERC20 + Permit | | + EIP-2612 gasless approvals |
| Full-featured token | | + Mint/burn with owner control |
Quick Start: Deploy ERC20 with Permit
import {ERC20PermitDFPkg, IERC20PermitDFPkg} from "@crane/contracts/tokens/ERC20/ERC20PermitDFPkg.sol"; import {IERC20} from "@crane/contracts/interfaces/IERC20.sol"; // 1. Deploy facets (typically done once via FactoryService) IFacet erc20Facet = factory.deployFacet(type(ERC20Facet).creationCode, salt); IFacet erc5267Facet = factory.deployFacet(type(ERC5267Facet).creationCode, salt); IFacet erc2612Facet = factory.deployFacet(type(ERC2612Facet).creationCode, salt); // 2. Deploy package with facet references ERC20PermitDFPkg pkg = new ERC20PermitDFPkg(IERC20PermitDFPkg.PkgInit({ erc20Facet: erc20Facet, erc5267Facet: erc5267Facet, erc2612Facet: erc2612Facet })); // 3. Deploy token instance via Diamond factory IERC20 token = IERC20(diamondFactory.deploy( pkg, abi.encode(IERC20PermitDFPkg.PkgArgs({ name: "My Token", symbol: "MTK", decimals: 18, totalSupply: 1_000_000e18, recipient: msg.sender, optionalSalt: bytes32(0) })) ));
Available Packages
ERC20DFPkg
Basic ERC20 token with metadata.
PkgInit (constructor):
struct PkgInit { IFacet erc20Facet; }
PkgArgs (deployment):
struct PkgArgs { string name; string symbol; uint8 decimals; // Defaults to 18 if 0 uint256 totalSupply; // Initial mint amount address recipient; // Required if totalSupply > 0 bytes32 optionalSalt; }
Interfaces:
IERC20, IERC20Metadata
ERC20PermitDFPkg
ERC20 with EIP-2612 permit (gasless approvals).
PkgInit:
struct PkgInit { IFacet erc20Facet; IFacet erc5267Facet; // EIP-5267 domain separator IFacet erc2612Facet; // EIP-2612 permit }
PkgArgs: Same as ERC20DFPkg
Interfaces:
IERC20, IERC20Metadata, IERC20Permit, IERC5267
ERC20PermitMintBurnLockedOwnableDFPkg
Full-featured token with owner-controlled mint/burn and time-locked ownership transfer.
PkgInit:
struct PkgInit { IFacet erc20Facet; IFacet erc5267Facet; IFacet erc2612Facet; IFacet erc20MintBurnOwnableFacet; IDiamondPackageCallBackFactory diamondFactory; }
PkgArgs:
struct PkgArgs { string name; string symbol; uint8 decimals; address owner; // Initial owner (mint/burn access) bytes32 optionalSalt; }
Interfaces:
IERC20, IERC20Metadata, IERC20Permit, IERC5267, IERC20MintBurn
Convenience deploy function:
function deployToken( string memory name, string memory symbol, uint8 decimals, address owner, bytes32 optionalSalt ) external returns (address tokenAddress);
Token Component Files
| File | Purpose |
|---|---|
| Diamond storage for balances, allowances, metadata |
| Business logic (transfer, approve, etc.) |
| Diamond facet exposing IERC20 + IFacet |
| Permit extension logic |
| Diamond facet for permit |
| Mint/burn with onlyOwner modifier |
Storage Pattern
Tokens use standard Crane Repo pattern:
library ERC20Repo { bytes32 internal constant STORAGE_SLOT = keccak256("eip.erc.20"); struct Storage { string name; string symbol; uint8 decimals; uint256 totalSupply; mapping(address => uint256) balanceOf; mapping(address => mapping(address => uint256)) allowance; } function _initialize(string memory name_, string memory symbol_, uint8 decimals_) internal; function _mint(address to_, uint256 amount_) internal; function _burn(address from_, uint256 amount_) internal; function _transfer(address from_, address to_, uint256 amount_) internal; }
Testing Tokens
Use the provided TestBase contracts:
import {TestBase_ERC20} from "@crane/contracts/tokens/ERC20/TestBase_ERC20.sol"; import {TestBase_ERC20Permit} from "@crane/contracts/tokens/ERC20/TestBase_ERC20Permit.sol"; contract MyToken_Test is TestBase_ERC20Permit { function _deployToken() internal override returns (IERC20Permit) { // Deploy your token instance } }
Additional Resources
Reference Files
For detailed implementation patterns and examples:
- Complete package comparison and deployment patternsreferences/token-packages.md