/nft-protocol-security
Protocol Type Trigger nft (detected when ERC721/ERC1155 with marketplace, minting, staking, or collateral logic found) - Inject Into Breadth agents, depth-token-flow, depth-edge...
$ npx -y skills add PlamenTSV/plamen --skill nft-protocol-security --agent claude-codeHow it fires
How this skill gets triggered: by you, by Claude, or both.
- Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
- You can call itInvoke it directly when you want it.
- Slash command
/nft-protocol-security
Context preview
The summary Claude sees to decide when to auto-load this skill.
Protocol Type Trigger nft (detected when ERC721/ERC1155 with marketplace, minting, staking, or collateral logic found) - Inject Into Breadth agents, depth-token-flow, depth-edge...
SKILL.md
nft-protocol-security.SKILL.mdname: "nft-protocol-security"
description: "Protocol Type Trigger nft (detected when ERC721/ERC1155 with marketplace, minting, staking, or collateral logic found) - Inject Into Breadth agents, depth-token-flow, depth-edge..."
Injectable Skill: NFT Protocol Security
> **Protocol Type Trigger**: `nft` (detected when ERC721/ERC1155 with marketplace, minting, staking, or collateral logic found) > **Inject Into**: Breadth agents, depth-token-flow, depth-edge-case > **Language**: EVM only (Solana/Move NFT models use different mechanisms without callbacks or enumeration) > **Finding prefix**: `[NFT-N]`
Orchestrator Decomposition Guide
When decomposing this skill into depth agent investigation questions, map sections to domains:
- Sections 1, 2: depth-token-flow (callback flows, approval/transfer paths)
- Section 3: depth-edge-case (enumeration invariants, boundary states)
- Section 4: depth-state-trace (ownership state consistency, metadata integrity)
When This Skill Activates
Recon detects NFT protocol patterns: ERC721/ERC1155 with state-modifying logic beyond simple transfer (marketplace listing, staking, collateral, minting with conditions, royalty enforcement, batch operations).
Pure ERC721/ERC1155 token implementations without protocol logic do NOT trigger this skill.
---
1. Callback Reentrancy Surface
For each function that triggers NFT callbacks:
1a. Safe Transfer Callback Inventory
Enumerate all code paths that invoke `_safeMint`, `_safeTransfer`, `safeTransferFrom`, or `onERC1155Received`/`onERC1155BatchReceived`:
| # | Function | Callback Triggered | State Modified BEFORE Callback | State Modified AFTER Callback | Reentrancy Guard? | |---|----------|-------------------|-------------------------------|------------------------------|-------------------|
For each entry:
- Is all critical state updated BEFORE the callback? (checks-effects-interactions)
- Can the callback recipient re-enter the calling contract?
- Can the callback recipient REVERT selectively to reject unwanted outcomes and retry until a desired outcome occurs?
- Pattern: `_safeMint(to, tokenId)` → `onERC721Received` callback → recipient reverts if assigned token has undesirable properties → retry until desired properties assigned.
1b. Batch Callback Completeness
For contracts implementing ERC1155:
- Is `onERC1155Received` implemented for single transfers?
- Is `onERC1155BatchReceived` implemented for batch transfers?
- If batch callback is MISSING: `safeBatchTransferFrom` will revert, blocking batch settlement/distribution.
- Do both callbacks return the correct selector?
Tag: `[TRACE:_safeMint → onERC721Received callback → state_before={list} → reentrant_path={YES/NO}]`
---
2. Approval and Transfer Path Analysis
2a. Approval Scope
For each approval mechanism:
- `approve(address, tokenId)`: per-token approval. Is approval cleared on transfer?
- `setApprovalForAll(address, bool)`: blanket approval. Can an approved operator transfer ANY token?
- Is there a mechanism to revoke approvals? Can approval persist across ownership changes?
2b. Transfer Authorization
For each transfer function:
- Who can transfer? (owner, approved, operator)
- Is authorization checked for ALL transfer code paths? (direct, marketplace, staking, collateral seizure)
- Pattern: protocol custody contract has `setApprovalForAll` from users → contract can transfer any user's NFTs → compromise of contract = compromise of all approved NFTs.
2c. Royalty Bypass
If royalties are enforced:
- Can transfers occur through paths that bypass royalty checks? (direct `transferFrom` vs marketplace `executeSale`)
- Are royalties enforced at the token level (ERC2981) or marketplace level?
- If marketplace-level only: direct transfer bypasses royalties.
Tag: `[TRACE:transfer_path={function} → auth_check={method} → royalty_enforced={YES/NO}]`
---
3. Enumeration and Index Integrity
For contracts using ERC721Enumerable or custom enumeration:
3a. Index Structure Consistency
- What data structures track token ownership enumeration? (`_ownedTokens`, `_allTokens`, index mappings)
- For every state-changing operation (mint, burn, transfer): are ALL index structures updated atomically?
- Pattern: override `_beforeTokenTransfer` (OZ v4) or `_update` (OZ v5) without calling `super` → index structures become stale.
3b. Burn and Transfer Edge Cases
- After burn: does `tokenOfOwnerByIndex` still return correct values? Is `totalSupply` decremented?
- After transfer: does old owner's index shrink and new owner's index grow?
- At boundary: single-token owner burns their only token → empty enumeration handles correctly?
3c. Batch Operation Atomicity
For batch mint/burn/transfer:
- Are indices updated for EACH token in the batch, or only once at the end?
- Can a partial failure in a batch leave indices in an inconsistent state?
- Gas cost at maximum batch size: does it exceed block gas limit?
Tag: `[BOUNDARY:burn_last_token → _ownedTokens[owner].length={0} → tokenOfOwnerByIndex={result}]`
---
4. Metadata and State Consistency
4a. Token URI Integrity
If `tokenURI` or `uri` returns dynamic content:
- For ERC1155: does `uri(uint256 id)` return a template with literal `{id}` placeholder per spec? Or a fully resolved URL? (clients expect to substitute the zero-padded hex ID client-side)
- Can metadata be changed after mint? By whom? Does change emit event?
- Is metadata stored on-chain or off-chain? If off-chain: what happens if the URI host is unreachable?
4b. Token Property Assignment
If tokens have properties assigned at mint time (rarity, type, attributes):
- Is the assignment deterministic or random?
- If random: is the randomness source manipulable? (block.timestamp, block.prevrandao, weak PRNG)
- Can the minter influence which properties are assigned? (selective minting via callback revert)
- Cross-reference FLASH_LOAN_INTERACTION if properties affect economic value.
4c. Ownership State
Read more
name: "nft-protocol-security" description: "Protocol Type Trigger nft (detected when ERC721/ERC1155 with marketplace, minting, staking, or collateral logic found) - Inject Into Breadth agents, depth-token-flow, depth-edge..."
Injectable Skill: NFT Protocol Security
> **Protocol Type Trigger**: `nft` (detected when ERC721/ERC1155 with marketplace, minting, staking, or collateral logic found) > **Inject Into**: Breadth agents, depth-token-flow, depth-edge-case > **Language**: EVM only (Solana/Move NFT models use different mechanisms without callbacks or enumeration) > **Finding prefix**: `[NFT-N]`
Orchestrator Decomposition Guide
When decomposing this skill into depth agent investigation questions, map sections to domains:
- Sections 1, 2: depth-token-flow (callback flows, approval/transfer paths)
- Section 3: depth-edge-case (enumeration invariants, boundary states)
- Section 4: depth-state-trace (ownership state consistency, metadata integrity)
When This Skill Activates
Recon detects NFT protocol patterns: ERC721/ERC1155 with state-modifying logic beyond simple transfer (marketplace listing, staking, collateral, minting with conditions, royalty enforcement, batch operations).
Pure ERC721/ERC1155 token implementations without protocol logic do NOT trigger this skill.
---
1. Callback Reentrancy Surface
For each function that triggers NFT callbacks:
1a. Safe Transfer Callback Inventory
Enumerate all code paths that invoke `_safeMint`, `_safeTransfer`, `safeTransferFrom`, or `onERC1155Received`/`onERC1155BatchReceived`:
| # | Function | Callback Triggered | State Modified BEFORE Callback | State Modified AFTER Callback | Reentrancy Guard? | |---|----------|-------------------|-------------------------------|------------------------------|-------------------|
For each entry:
- Is all critical state updated BEFORE the callback? (checks-effects-interactions)
- Can the callback recipient re-enter the calling contract?
- Can the callback recipient REVERT selectively to reject unwanted outcomes and retry until a desired outcome occurs?
- Pattern: `_safeMint(to, tokenId)` → `onERC721Received` callback → recipient reverts if assigned token has undesirable properties → retry until desired properties assigned.
1b. Batch Callback Completeness
For contracts implementing ERC1155:
- Is `onERC1155Received` implemented for single transfers?
- Is `onERC1155BatchReceived` implemented for batch transfers?
- If batch callback is MISSING: `safeBatchTransferFrom` will revert, blocking batch settlement/distribution.
- Do both callbacks return the correct selector?
Tag: `[TRACE:_safeMint → onERC721Received callback → state_before={list} → reentrant_path={YES/NO}]`
---
2. Approval and Transfer Path Analysis
2a. Approval Scope
For each approval mechanism:
- `approve(address, tokenId)`: per-token approval. Is approval cleared on transfer?
- `setApprovalForAll(address, bool)`: blanket approval. Can an approved operator transfer ANY token?
- Is there a mechanism to revoke approvals? Can approval persist across ownership changes?
2b. Transfer Authorization
For each transfer function:
- Who can transfer? (owner, approved, operator)
- Is authorization checked for ALL transfer code paths? (direct, marketplace, staking, collateral seizure)
- Pattern: protocol custody contract has `setApprovalForAll` from users → contract can transfer any user's NFTs → compromise of contract = compromise of all approved NFTs.
2c. Royalty Bypass
If royalties are enforced:
- Can transfers occur through paths that bypass royalty checks? (direct `transferFrom` vs marketplace `executeSale`)
- Are royalties enforced at the token level (ERC2981) or marketplace level?
- If marketplace-level only: direct transfer bypasses royalties.
Tag: `[TRACE:transfer_path={function} → auth_check={method} → royalty_enforced={YES/NO}]`
---
3. Enumeration and Index Integrity
For contracts using ERC721Enumerable or custom enumeration:
3a. Index Structure Consistency
- What data structures track token ownership enumeration? (`_ownedTokens`, `_allTokens`, index mappings)
- For every state-changing operation (mint, burn, transfer): are ALL index structures updated atomically?
- Pattern: override `_beforeTokenTransfer` (OZ v4) or `_update` (OZ v5) without calling `super` → index structures become stale.
3b. Burn and Transfer Edge Cases
- After burn: does `tokenOfOwnerByIndex` still return correct values? Is `totalSupply` decremented?
- After transfer: does old owner's index shrink and new owner's index grow?
- At boundary: single-token owner burns their only token → empty enumeration handles correctly?
3c. Batch Operation Atomicity
For batch mint/burn/transfer:
- Are indices updated for EACH token in the batch, or only once at the end?
- Can a partial failure in a batch leave indices in an inconsistent state?
- Gas cost at maximum batch size: does it exceed block gas limit?
Tag: `[BOUNDARY:burn_last_token → _ownedTokens[owner].length={0} → tokenOfOwnerByIndex={result}]`
---
4. Metadata and State Consistency
4a. Token URI Integrity
If `tokenURI` or `uri` returns dynamic content:
- For ERC1155: does `uri(uint256 id)` return a template with literal `{id}` placeholder per spec? Or a fully resolved URL? (clients expect to substitute the zero-padded hex ID client-side)
- Can metadata be changed after mint? By whom? Does change emit event?
- Is metadata stored on-chain or off-chain? If off-chain: what happens if the URI host is unreachable?
4b. Token Property Assignment
If tokens have properties assigned at mint time (rarity, type, attributes):
- Is the assignment deterministic or random?
- If random: is the randomness source manipulable? (block.timestamp, block.prevrandao, weak PRNG)
- Can the minter influence which properties are assigned? (selective minting via callback revert)
- Cross-reference FLASH_LOAN_INTERACTION if properties affect economic value.
4c. Ownership State
Autonomous Web3 security auditor for Claude Code and OpenAI Codex CLI. Orchestrates 18-100 AI agents across 40+ phases to produce audit reports with verified PoC exploits — for smart contracts and L1 node-client infrastructure.
Repo: PlamenTSV/plamen
Other skills on plamen.
- /ability-analysis
Trigger Pattern Always (Aptos Move) - foundational security check - Inject Into Breadth agents, depth agents
Open skill - /bit-shift-safety
Trigger Pattern Always (Aptos Move) - Move VM aborts on shift = bit width - Inject Into Breadth agents, depth-edge-case
Open skill - /centralization-risk
Trigger Protocol has privileged roles (admin, operator, governance, resource account owner) - Covers Single points of failure, privilege escalation, external governance dependen...
Open skill - /cross-chain-timing
Trigger Pattern wormhole|layerzero|ccip|bridge|cross_chain|vaa|guardian|emitter|relay|remote_chain|payload|nonce.sequence - Inject Into Breadth agents, depth-external
Open skill - /dependency-audit
Trigger EXTERNAL_LIB flag detected (protocol uses third-party Move dependencies) - Used by Breadth agents, depth-external
Open skill - /economic-design-audit
Trigger Pattern MONETARY_PARAMETER flag (required) - Inject Into Breadth agents (merged via M4 hierarchy)
Open skill

