Skip to content

Hats-Protocol/cracked-nft

Repository files navigation

Cracked NFT

A non-transferrable NFT contract with voting capabilities for recognizing elite Farcaster builders.

Overview

CrackedCredential is an ERC721Votes token contract that serves as "The self-curated hall of fame for elite Farcaster builders." These credentials are designed to be permanent, non-transferrable recognition tokens that also function as governance voting units.

Key Features

  • Non-transferrable: Once minted, tokens cannot be transferred between addresses (except burning)
  • Burnable: Token owners can burn their own tokens to remove them from circulation
  • One token per address: Each address can only own one credential token
  • Voting Power: Each NFT represents 1 vote in governance decisions
  • Auto-delegation: Newly minted tokens are automatically delegated to the recipient
  • Delegation: Token holders can delegate their voting power to others without transferring the NFT
  • Owner-only minting: Only the contract owner can mint new credentials
  • Batch minting: Support for minting multiple tokens in a single transaction
  • Approval disabled: Approvals are disabled for security (no approve or setApprovalForAll)
  • On-chain metadata: Token metadata is generated and encoded on-chain using Base64
  • EIP-712 Support: Secure signature-based delegation using typed structured data
  • Zero address protection: Cannot mint to address(0)
  • Comprehensive validation: Safer minting with recipient validation

Contract Details

  • Token Name: Cracked Farcaster Dev
  • Symbol: CFD
  • Standard: ERC721Votes (extends ERC721 with OpenZeppelin Votes functionality)
  • EIP-712 Domain: "Cracked Farcaster Dev" version "1"
  • Clock Mode: Timestamp-based (ERC-6372 compliant)

Usage

Deployment

Deploy the contract with an initial owner address who will have minting privileges:

CrackedCredential credential = new CrackedCredential("Cracked Farcaster Dev", "CFD", <initialOwner>);

Minting

Mint single or multiple credentials (auto-delegates to recipients):

// Single mint
credential.safeMint(recipient);

// Batch mint
address[] memory recipients = [addr1, addr2, addr3];
credential.safeMintBatch(recipients);

Minting Requirements:

  • Only the contract owner can mint
  • Recipient must not be address(0)
  • Recipient must not already own a token (one token per address)
  • All recipients in batch must be unique

Burning

Token owners can burn their own tokens:

// Burn your own token
credential.burn(tokenId);

Burning Requirements:

  • Only the token owner can burn their token
  • Burning removes the token from circulation and burns the voting power

Voting & Delegation

// Check voting power
uint256 votes = credential.getVotes(account);

// Check who someone delegated to
address delegatee = credential.delegates(account);

// Delegate voting power to someone else (without transferring NFT)
credential.delegate(delegatee);

// Delegate via signature (gasless)
credential.delegateBySig(delegatee, nonce, expiry, v, r, s);

// Check historical voting power
uint256 pastVotes = credential.getPastVotes(account, blockNumber);

Key Voting Mechanics

  1. Auto-delegation: When minted, tokens are automatically delegated to the recipient
  2. NFT Ownership vs Voting Power:
    • NFT ownership and voting power are separate
    • You keep your NFT even when delegating votes to others
    • Transfers are blocked, but delegation is always allowed
  3. Vote Weight: Each NFT = 1 vote regardless of token ID
  4. Vote Tracking: Voting power is tracked over time for governance snapshots
  5. Timestamp-based: Uses block.timestamp instead of block numbers for time tracking (ERC-6372)

Security Features

  • Non-transferrable: Tokens cannot be transferred (except burning)
  • Approval disabled: approve() and setApprovalForAll() are disabled
  • One token per address: Prevents accumulation of multiple tokens
  • Zero address protection: Cannot mint to address(0)
  • Owner-only minting: Only contract owner can create new credentials
  • Burn authorization: Only token owners can burn their own tokens

Examples

Basic Voting Flow

// Deploy
CrackedCredential cred = new CrackedCredential("Cracked Farcaster Dev", "CFD", <owner>);

// Mint to Alice (auto-delegated)
cred.safeMint(alice);
assert(cred.getVotes(alice) == 1);        // Alice has 1 vote
assert(cred.delegates(alice) == alice);   // Alice delegated to herself

// Alice delegates to Bob
cred.delegate(bob);
assert(cred.getVotes(alice) == 0);        // Alice now has 0 votes
assert(cred.getVotes(bob) == 1);          // Bob now has 1 vote
assert(cred.ownerOf(0) == alice);         // Alice still owns the NFT

// Alice burns her token
cred.burn(0);
assert(cred.getVotes(bob) == 0);          // Bob loses the delegated vote

Governance Integration

// In a Governor contract
function propose(...) external returns (uint256) {
    // Voting power is automatically checked via ERC721Votes
    require(getVotes(msg.sender, block.number - 1) >= proposalThreshold());
    // ... rest of proposal logic
}

Error Handling

// These will revert:
credential.safeMint(address(0));                    // InvalidRecipient
credential.safeMint(alice); credential.safeMint(alice); // RecipientAlreadyOwnsToken
credential.approve(bob, 0);                         // ApprovalDisabled
credential.transferFrom(alice, bob, 0);            // NotTransferrable

Development

Built with Foundry. Install dependencies:

forge install

Run tests:

forge test

Run with coverage:

forge coverage

Contract Architecture

The contract follows OpenZeppelin best practices with:

  • Comprehensive NatSpec documentation: All functions are fully documented
  • Proper function ordering: Functions organized by visibility and purpose
  • Error handling: Custom errors for better gas efficiency and clarity
  • Security-first design: Disabled approvals, non-transferrable tokens
  • Voting integration: Full ERC721Votes implementation for governance
  • On-chain metadata: Base64-encoded JSON metadata generated on-chain

About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published