# Farcaster Collectible Casts Source: https://github.com/farcasterxyz/collectible-casts Kiwi News: https://news.kiwistand.com/stories/Farcaster-Collectible-Casts?index=0x687fa08fe60524e34ca0c7fb58757de7f5c5817e87611e19b089e531ff9d3eae016a9cdb Submitted by pedrovilela.eth on 2025-07-22 UTC, 5 upvotes, 0 comments ## Summary Farcaster has introduced Collectible Casts, which let users collect any cast as an ERC721 NFT through an ascending USDC auction on Base. The winning bidder receives the token in their wallet, with 90% of the winning bid going to the creator and the remaining 10% going to the protocol treasury for growth incentives. Bidding is restricted to Farcaster users through an offchain authorizer signature, and the auction can be extended when bids arrive near the end. The backend signer can cancel auctions if a cast is deleted or a user opts out, and an owner-only recover function serves as an escape hatch for stuck auctions. ## Article A new way for Farcaster users to support creators through collectible NFTs. Overview Collectible Casts introduce a mechanism where every cast can be collected. If more than one user attempts to collect the same cast within the bidding window, an ascending auction determines the final owner and price. The winning bidder receives an ERC721 token representing the collectible, minted directly to their wallet. 90% of the winning bid goes to the creator; the remaining 10% accrues to the protocol treasury for growth incentives. For more details see the product doc here. Goals Creator monetization - Let users earn immediately without waiting for weekly reward cycles Showcase support - Give users a collectible that is more meaningful than a tip and shareable across wallets/profiles Simplicity first - Ship minimal contracts that we fully understand with few core dependencies Start permissioned - Restrict initial auctions to Farcaster users Changeable periphery - Make experimentation with auction parameters very easy. Make deploying new auction contracts pretty easy. Ossify NFT metadata - Start with offchain metadata but make it possible to progressively ossify. Non-Goals Our own secondary marketplace at launch Multiple clients at launch Gasless bidding at launch Support for arbitrary ERC20 payment tokens Extremely onchain token metadata at launch Extreme gas efficiency Architecture Two main contracts, Auction and CollectibleCasts, with support for modular metadata: ┌─────────────────┐ mints ┌─────────────────┐ delegates ┌─────────────────┐ │ Auction │ ──────────▶ │ CollectibleCasts│ ──────────────▶│ Metadata Module │ │ │ │ (ERC-721) │ metadata │ (optional) │ │ • USDC escrow │ │ • NFT management│ ◀──────────── │ • Dynamic URIs │ │ • Bid tracking │ │ • Metadata │ callbacks │ • Custom logic │ │ • Settlement │ │ • Event emission│ │ │ └─────┬───────────┘ └─────────────────┘ └─────────────────┘ │ escrow ▼ ┌─────────────────┐ │ USDC Token │ │ (Base) │ └─────────────────┘ Auction Flow Start: A backend signer authorizes auction creation with an EIP712 signature, signing over the initial auction parameters and bid. This enables us to change some auction parameters (min bid amount, min increment, fee split, duration, extension time, extension threshold) from the Farcaster app backend and set different policies for new vs historical casts. Auctions start on first bid and the initial bid must provide this authorization signature from the backend. Bidding: Users place ascending USDC bids with automatic refunds. New bids must be the greater of an absolute min bid amount and min bid increment in basis points. Each bid must be submitted with an offchain authorizer signature. This allows us to restrict bids to Farcaster users. Users who are outbid are automatically refunded. Extension: The auction's end time is extended when new bids are placed near the end. These parameters are configurable by the offchain authorizer at auction start time. Settlement: Once ended, anyone can settle an auction. This distributes payment and mints the collectible NFT to the winner. We intend to run batch settlement jobs to settle auctions on behalf of app users. Cancellation: Offchain authorizers can cancel Active and Ended auctions before they are Settled. They will do this in the event that a cast is deleted or a user opts out of collectible casts. Emergency Recovery: In the event of a stuck auction (e.g., USDC blacklisted recipient), the owner can "recover" an auction, cancelling it and sending funds to a specified address instead of the high bidder. This works on both Active and Ended auctions. Assumptions and Acknowledgments Auctions will always use Base USDC. No weird ERC20s. No native ETH bidding. "Push" refunds have some edge case risk in the event that a bidder is blacklisted by the USDC contract. The owner-only recover() function provides an escape hatch for these situations. Authorizers and owner have significant control over the contract and parameters. We will do our best not to be stupid. Auction State Transitions stateDiagram-v2 None --> Active: start() Active --> Ended: time expires Active --> Cancelled: cancel() Active --> Recovered: recover() Ended --> Settled: settle() Ended --> Cancelled: cancel() Ended --> Recovered: recover() Loading Quick Start # Install Foundry curl -L https://foundry.paradigm.xyz | bash foundryup # Clone and setup git clone https://github.com/farcasterxyz/collectible-casts cd collectible-casts forge install # Build and test forge build forge test Development Testing # Run all tests forge test # Run with gas reporting forge test --gas-report # Run with coverage forge coverage # Fuzz testing profiles forge test FOUNDRY_PROFILE=ci forge test FOUNDRY_PROFILE=deep forge test Code Quality # Format code forge fmt # Check formatting forge fmt --check # Lint Solidity files npx solhint 'src/**/*.sol' # Generate documentation forge doc # Contract size analysis forge build --sizes Deployment Environment Setup Required environment variables: export DEPLOYER_ADDRESS= export OWNER_ADDRESS= export TREASURY_ADDRESS= export BACKEND_SIGNER_ADDRESS= export BASE_URI= Deploy to Base # Base Mainnet forge script script/DeployCollectibleCasts.s.sol \ --rpc-url $BASE_RPC_URL \ --broadcast \ --verify # Base Sepolia (testnet) forge script script/DeployCollectibleCasts.s.sol \ --rpc-url $BASE_SEPOLIA_RPC_URL \ --broadcast The deployment script uses CREATE2 for deterministic addresses and automatically configures permissions and parameters. Deployments Base Mainnet Contract Address CollectibleCasts 0xc011ec7ca575d4f0a2eda595107ab104c7af7a09 Auction 0xfc52e33f48dd3fcd5ee428c160722efda645d74a Documentation SPEC.md - Notes from original spec CLAUDE.md - Notes for our buddy Claude