Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/0xchriswilder/journey/llms.txt

Use this file to discover all available pages before exploring further.

Week 4: Production & Capstone

Subtitle: Advanced patterns, production deployment, and capstone project Estimated Time: 15 hours of lessons + 15 hours capstone project

Objectives

Advanced Patterns

Implement sealed auctions, private tokens, confidential governance

Production Contracts

Break down production contracts step-by-step with gas optimization

Security & Deployment

Understand production deployment, security, and monitoring

Capstone Project

Complete a production-quality confidential dApp

Milestone

Completed capstone project with smart contract, frontend, tests, and documentation
Production-quality code ready for deployment
Deep understanding of FHEVM security and best practices

Lessons

Lesson 4.1: Advanced FHEVM Applications

Duration: 60 minutes
  • Design a sealed-bid auction contract with encrypted bids
  • Implement private ERC-20 token transfers with encrypted balances
  • Architect a confidential DAO voting system with weighted votes
Three-Phase State Machine: Bidding → Reveal → Settlement
contract BlindAuction is ZamaEthereumConfig {
    struct Auction {
        address creator;
        uint256 biddingEndTime;
        uint256 revealEndTime;
        euint64 highestBid;        // ENCRYPTED
        address highestBidder;
        uint64 revealedHighestBid;
        bool ended;
    }

    // Phase 1: Place encrypted bid
    function placeBid(
        uint256 auctionId,
        externalEuint64 encryptedBid,
        bytes calldata inputProof
    ) external {
        euint64 bid = FHE.fromExternal(encryptedBid, inputProof);

        if (FHE.isInitialized(auction.highestBid)) {
            ebool isHigher = FHE.gt(bid, auction.highestBid);
            auction.highestBid = FHE.select(isHigher, bid, auction.highestBid);
        } else {
            auction.highestBid = bid;  // First bid
        }

        FHE.allowThis(auction.highestBid);
    }

    // Phase 2: Request reveal
    function requestReveal(uint256 auctionId) external {
        auction.highestBid = FHE.makePubliclyDecryptable(auction.highestBid);
        emit RevealRequested(auctionId, FHE.toBytes32(auction.highestBid));
    }

    // Phase 3: Settlement with proof verification
    function endAuction(
        uint256 auctionId,
        bytes memory cleartexts,
        bytes memory decryptionProof
    ) external {
        bytes32[] memory handlesList = new bytes32[](1);
        handlesList[0] = FHE.toBytes32(auction.highestBid);
        FHE.checkSignatures(handlesList, cleartexts, decryptionProof);

        auction.revealedHighestBid = abi.decode(cleartexts, (uint64));
        auction.ended = true;
    }
}
Key Design Decisions:
highestBid starts uninitialized — use FHE.isInitialized() to check
FHE.select() updates highest bid without revealing either value
ACL permissions re-granted after every FHE.select() (new ciphertext)
v0.9+ self-relaying: makePubliclyDecryptablecheckSignatures
The official OpenZeppelin standard for confidential tokensAll balances are euint64, transfers use encrypted amounts with proof verification, and only account holders can decrypt their own balance.
contract ERC7984Mock is ERC7984, ZamaEthereumConfig, Ownable {
    // Hook: Called on every mint / burn / transfer
    function _update(
        address from, address to, euint64 amount
    ) internal virtual override returns (euint64 transferred) {
        transferred = super._update(from, to, amount);
        // Grant owner access to total supply (for monitoring)
        FHE.allow(confidentialTotalSupply(), _OWNER);
    }

    // Mint with external encrypted input (production)
    function $_mint(
        address to, externalEuint64 encryptedAmount, bytes calldata inputProof
    ) public onlyOwner returns (euint64) {
        euint64 internalAmount = FHE.fromExternal(encryptedAmount, inputProof);
        return _mint(to, internalAmount);
    }

    // Transfer with external encrypted input
    function $_transfer(
        address from, address to,
        externalEuint64 encryptedAmount, bytes calldata inputProof
    ) public returns (euint64) {
        return _transfer(from, to, FHE.fromExternal(encryptedAmount, inputProof));
    }
}
Key Concepts:
All balances are euint64 — chain never stores plaintext
FHE.fromExternal() converts client-side encryption to on-chain format
_update() hook runs on every mint/burn/transfer for ACL management
Two mint flavors: production (with proof) and testing (plaintext)

Lesson 4.2: Contract Deep Dive & Gas Optimization

Duration: 60 minutes
  • Understand why sealed-bid auctions solve front-running and shill bidding
  • Trace the three-phase state machine and key FHE operations
  • See why incremental winner tracking is used instead of batch comparison
  • Apply gas optimization strategies: type selection, batching, minimal decryption
In traditional on-chain auctions, all bids are visible. This creates:
Front-running — Bots outbid you after seeing your transaction
Strategic underbidding — Everyone knows the current highest bid
Shill bidding — Fake bids to drive up prices
Bid sniping — Last-second bids based on visible competition
Sealed-bid auctions solve these:
Bids are encrypted until reveal — nobody can see them during bidding
Winner determined by FHE.gt() comparison without revealing values
Only the winning bid is ever decrypted and revealed
This pattern is used in production by Zama Auction, the first app on Zama Protocol mainnet.
Phase 1: BiddingUsers place encrypted bids. The contract tracks the highest bid using FHE.gt() + FHE.select() without revealing any value.Phase 2: ClosedBidding ends. The auctioneer receives permission to decrypt the winner (FHE.allow or makePubliclyDecryptable).Phase 3: RevealedThe auctioneer publishes winner and winning bid on-chain after proof verification.
The state machine is a security boundary: during Bidding, not even the auctioneer can see the highest bid.
FHE.gt(bid, highestBid)Returns an ebool — “is this bid higher?” — without revealing either number.FHE.select(isHigher, bid, highestBid)Picks the new highest bid based on the encrypted condition. No information leaked.FHE.isInitialized(highestBid)Used to handle the first bid: no comparison needed until there is a previous highest.The New-Handle RuleAfter any FHE operation that creates a new handle (e.g., FHE.select), you must call FHE.allowThis() again on the new handle.
auction.highestBid = FHE.select(isHigher, bid, auction.highestBid);
FHE.allowThis(auction.highestBid);  // REQUIRED!
Question: Why update highest bid on every placeBid instead of comparing all bids when the auction closes?Answer 1: Gas DistributionFHE comparisons are expensive. Incremental approach spreads cost across all placeBid transactions instead of one huge closeAuction.Answer 2: ScalabilityWith many bidders, a batch comparison could exceed block gas limit. Each placeBid does O(1) FHE work.
1. Use the Smallest Typeeuint8 operations are cheaper than euint64. Only use larger types when needed.2. Minimize Decryption RequestsEach decryption has overhead. Batch multiple values into a single request.3. Batch OperationsCombine multiple operations to reduce the number of FHE calls.4. Avoid Unnecessary PermissionsOnly call FHE.allowThis() and FHE.allow() when you need decryption access.5. Cache ConstantsIf you use FHE.asEuint8(0) or FHE.asEuint8(1) frequently, cache them in state.

Lesson 4.3: Production Deployment & Security

Duration: 45 minutes
  • Complete a security checklist for FHEVM contracts
  • Deploy to production (mainnet) with proper configuration
  • Set up monitoring and alerting for deployed contracts
  • Identify next steps and advanced resources for continued learning
1

Access Control

Every decryption request must be gated behind proper access control (onlyOwner, role-based, etc.)
2

Permission Management

Audit every FHE.allowThis() and FHE.allow() call. Ensure no unauthorized addresses can decrypt.
3

Input Validation

Always use FHE.fromExternal() with proof verification. Never accept raw encrypted data without proof.
4

State Consistency

Ensure encrypted state is updated atomically. Use the check-effects-interactions pattern.
5

Proof Verification

In v0.9+ resolve callbacks, always call FHE.checkSignatures() before using decrypted values.
6

Gas Limits

Test gas consumption for all functions. FHE operations are more expensive than standard operations.
7

Upgrade Path

Consider using proxy patterns if you need contract upgradeability.
8

Testing

Achieve >90% test coverage including edge cases and failure scenarios.
Security is non-negotiable for production FHEVM contracts. Test on Sepolia before deploying to mainnet, and consider a professional audit for high-value contracts.
Congratulations on completing the FHEVM Bootcamp!Deploy to ProductionUse the Zama mainnet when available, or continue building on Sepolia testnet.Join the CommunityExplore TemplatesBuild & ShareCreate your own FHEVM projects and share them with the community. Bounties and grants are available.Stay UpdatedFollow Zama on Twitter and subscribe to their newsletter for the latest updates.

Capstone Project

Estimated Time: 15 hours Objective: Build a production-quality confidential dApp demonstrating end-to-end FHEVM proficiency.

Choose Your Track

Track A: DeFi

Sealed-Bid AuctionExtend the BlindAuction with:
  • Multiple simultaneous auctions
  • Bid deposit/refund system
  • Minimum bid threshold
  • Creator fee on winning bid
Reference: Lessons 4.1 and 4.2

Track B: Governance

Weighted VotingBuild a governance system where:
  • Token holders vote with encrypted weight
  • Multiple proposals active simultaneously
  • Quorum threshold (minimum total weight)
  • Delegation: allow(votingPower, delegateAddress)

Track C: Identity

Private Credential VerificationCreate an identity system where:
  • Users store encrypted attributes
  • Prove attribute ranges without revealing values
  • Selective disclosure to verifiers
  • Credential revocation

Requirements

Write a complete, well-tested FHEVM smart contract for your chosen track.Must compile and deploy successfully to Sepolia.
Build a React frontend that integrates with your contract.Must handle wallet connection, encryption, and all contract interactions.
Write comprehensive Hardhat tests with >80% coverage.Include unit tests, integration tests, and edge case tests.
Write a README with:
  • Project overview
  • Architecture diagram
  • Setup instructions
  • Usage guide
  • Security considerations
Demonstrate:
  • Clear concept with privacy rationale
  • Sound architecture
  • Appropriate use of FHEVM patterns

Grading Criteria

CriterionWeightExcellence (90-100%)
Concept & Design20%Novel concept, excellent architecture, clear privacy rationale
Smart Contract25%Production-quality, proper permissions, gas-optimized
Frontend25%Polished, responsive UI with excellent UX and error handling
Testing15%>90% coverage, tests for edge cases and failure modes
Documentation15%Comprehensive README with diagrams, GIFs, clear instructions

Submission

1

Use Lessons 4.1 & 4.2

Reference the Production Contract Library and BlindAuction walkthrough
2

Create repository

Create a GitHub repository for your capstone project
3

Include all code

Contracts, tests, frontend, and comprehensive README
4

Deploy to Sepolia

Include the contract address in your README
5

Optional: Deploy frontend

Deploy to Vercel/Netlify for bonus points
6

Submit

Submit GitHub repository link — [Submission portal coming soon]

Bootcamp Complete!

You’ve mastered FHEVM fundamentals
You can write, test, and deploy confidential smart contracts
You can build full-stack confidential dApps
You understand production patterns and security best practices
What’s next?

Deploy to Production

Take your capstone project to mainnet when Zama launches

Join the Community

Connect with other FHEVM developers on Discord and GitHub

Build Something New

Create novel confidential applications and apply for grants

Teach Others

Run your own FHEVM workshop using this curriculum