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.
Deploys ERC20, ERC20Permit, and ERC4626 tokens using Crane's Diamond Factory Packages.
npx claudepluginhub cyotee/cyotee-claude-plugin-craneThis skill inherits all available tools. When active, it can use any tool Claude has access to.
references/token-packages.mdCrane provides pre-built Diamond Factory Packages (DFPkg) for deploying ERC20, ERC20Permit, and ERC4626 tokens as Diamond proxies.
| Need | Package | Features |
|---|---|---|
| Basic ERC20 | ERC20DFPkg | Transfer, approve, metadata |
| ERC20 + Permit | ERC20PermitDFPkg | + EIP-2612 gasless approvals |
| Full-featured token | ERC20PermitMintBurnLockedOwnableDFPkg | + Mint/burn with owner control |
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)
}))
));
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
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
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);
| File | Purpose |
|---|---|
ERC20Repo.sol | Diamond storage for balances, allowances, metadata |
ERC20Target.sol | Business logic (transfer, approve, etc.) |
ERC20Facet.sol | Diamond facet exposing IERC20 + IFacet |
ERC20PermitTarget.sol | Permit extension logic |
ERC20PermitFacet.sol | Diamond facet for permit |
ERC20MintBurnOwnableFacet.sol | Mint/burn with onlyOwner modifier |
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;
}
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
}
}
For detailed implementation patterns and examples:
references/token-packages.md - Complete package comparison and deployment patternsActivates when the user asks about AI prompts, needs prompt templates, wants to search for prompts, or mentions prompts.chat. Use for discovering, retrieving, and improving prompts.
Search, retrieve, and install Agent Skills from the prompts.chat registry using MCP tools. Use when the user asks to find skills, browse skill catalogs, install a skill for Claude, or extend Claude's capabilities with reusable AI agent components.
Creating algorithmic art using p5.js with seeded randomness and interactive parameter exploration. Use this when users request creating art using code, generative art, algorithmic art, flow fields, or particle systems. Create original algorithmic art rather than copying existing artists' work to avoid copyright violations.