---
# System prepended metadata

title: Untitled

---

# ValidatorNFT and ValidatorSale Flow Diagrams

## Deployment Flow

```mermaid
graph TD
    A[Deploy ValidatorNFT Contract] --> B[ValidatorNFT Deployed]
    B --> C[Deploy ValidatorSale Contract]
    C --> |Pass NFT Address and Treasury Address| D[ValidatorSale Deployed]
    D --> E[Grant MINTER_ROLE to ValidatorSale]
    E --> |validatorNFT.grantRole| F[System Ready for Sales]
    
    style A fill:#f9f,stroke:#333,stroke-width:4px
    style F fill:#9f9,stroke:#333,stroke-width:4px
```

## Sale Process Flow

```mermaid
sequenceDiagram
    participant Buyer
    participant USDC
    participant ValidatorSale
    participant ValidatorNFT
    participant Treasury
    
    Note over Buyer: Buyer wants to purchase NFT 0 - Ace of Clubs
    
    Buyer->>USDC: approve(ValidatorSale, 52000 USDC)
    USDC-->>Buyer: Approval granted
    
    Buyer->>ValidatorSale: buy(tokenId: 0)
    
    ValidatorSale->>USDC: transferFrom(Buyer, ValidatorSale, 52000 USDC)
    USDC-->>ValidatorSale: Transfer complete
    
    Note over ValidatorSale: Calculate 52 percent for treasury
    ValidatorSale->>USDC: transfer(Treasury, 27040 USDC)
    USDC-->>Treasury: 52 percent transferred
    
    Note over ValidatorSale: 48 percent - 24960 USDC - remains for bonding
    
    ValidatorSale->>ValidatorNFT: mintAndTransfer(Buyer, tokenId: 0)
    ValidatorNFT-->>ValidatorNFT: _safeMint(Buyer, 0)
    ValidatorNFT-->>ValidatorNFT: cardMinted 0 equals true
    ValidatorNFT-->>ValidatorNFT: cardDisabled 0 equals true
    ValidatorNFT-->>Buyer: NFT 0 transferred
    
    ValidatorSale-->>Buyer: emit Bought(Buyer, 0)
    ValidatorNFT-->>Buyer: emit ValidatorAdded(Buyer, 0, totalSupply)
    
    Note over Buyer: NFT is disabled by default
    Buyer->>ValidatorNFT: toggleEnable(0)
    ValidatorNFT-->>ValidatorNFT: cardDisabled 0 equals false
    ValidatorNFT-->>Buyer: emit CardEnabled(0)
    Note over Buyer: Now an active validator!
```

## Contract Interactions Overview

```mermaid
graph LR
    subgraph ValidatorNFT["ValidatorNFT Contract"]
        A[MINTER_ROLE]
        B[mintAndTransfer]
        C[toggleEnable]
        D[Card State Management]
    end
    
    subgraph ValidatorSale["ValidatorSale Contract"]
        E[buy]
        F[Treasury Distribution]
        G[Bonding Reserve]
        H[withdrawToTreasury]
    end
    
    subgraph External["External"]
        I[USDC Contract]
        J[Treasury Address]
        K[Buyers]
    end
    
    K -.->|Approve USDC| I
    K -.->|Call buy| E
    E -.->|Transfer USDC| I
    E -.->|Send 52 percent| J
    E -.->|Keep 48 percent| G
    E -.->|Mint NFT| B
    A -.->|Authorizes| B
    K -.->|Enable NFT| C
    H -.->|Emergency| J
```

### Flow Description:
1. **Buyers → USDC Contract**: Approve USDC spending
2. **Buyers → buy()**: Call purchase function
3. **buy() → USDC Contract**: Transfer payment
4. **buy() → Treasury Address**: Send 52%
5. **buy() → Bonding Reserve**: Keep 48%
6. **buy() → mintAndTransfer()**: Mint NFT
7. **MINTER_ROLE → mintAndTransfer()**: Authorizes minting
8. **Buyers → toggleEnable()**: Enable validator NFT
9. **withdrawToTreasury() → Treasury Address**: Emergency withdrawal

## Key Features

### ValidatorNFT
- **52 unique NFTs** representing a deck of cards
- **Access Control**: Only addresses with MINTER_ROLE can mint using mintAndTransfer function
- **Default Disabled**: NFTs are disabled when minted
- **Owner Control**: Only token owners can enable/disable their NFTs

### ValidatorSale  
- **Fixed Price**: 52,000 USDC per NFT
- **Treasury Split**: 52% immediately to treasury
- **Bonding Reserve**: 48% held for validator bonding/slashing
- **Mint on Purchase**: No pre-minting required
- **Failsafe**: Owner can withdraw bonding funds if needed

## Deployment Steps

1. Deploy ValidatorNFT with name and symbol
2. Deploy ValidatorSale with ValidatorNFT address and treasury address
3. Grant MINTER_ROLE on ValidatorNFT to ValidatorSale contract
4. System is ready for purchases

## Purchase Steps

### Direct USDC Purchase
1. Buyer approves USDC spending to ValidatorSale
2. Buyer calls `buy(tokenId)` with desired card ID (0-51)
3. Contract transfers 52,000 USDC from buyer
4. Contract sends 27,040 USDC (52%) to treasury
5. Contract keeps 24,960 USDC (48%) for bonding
6. Contract mints and transfers NFT to buyer
7. Buyer calls `toggleEnable(tokenId)` to activate validator status

### Quote System for Other Tokens

The `quote` function allows buyers to check prices in other tokens (ETH, WBTC, etc.) before purchasing:

```mermaid
sequenceDiagram
    participant Buyer
    participant ValidatorSale
    participant UniswapQuoter
    participant UniswapRouter
    
    Note over Buyer: Buyer has ETH but needs to know how much ETH equals 52000 USDC
    
    Buyer->>ValidatorSale: quote(WETH, 3000)
    Note over ValidatorSale: Fee 3000 = 0.3% pool
    ValidatorSale->>UniswapQuoter: quoteExactOutputSingle
    Note over UniswapQuoter: Calculate: How much WETH needed to get 52000 USDC?
    UniswapQuoter-->>ValidatorSale: Returns amount of WETH needed
    ValidatorSale-->>Buyer: Returns WETH amount
    
    Note over Buyer: Now buyer knows they need X amount of WETH
    
    Buyer->>UniswapRouter: Swap WETH for USDC
    UniswapRouter-->>Buyer: Receive 52000 USDC
    
    Buyer->>ValidatorSale: buy(tokenId)
    Note over ValidatorSale: Standard purchase flow continues
```

#### Why the Quote Function?

1. **Price Discovery**: Buyers can check how much of any token (ETH, WBTC, DAI) they need to purchase an NFT
2. **Multi-token Support**: While the sale only accepts USDC, buyers can plan their token swaps
3. **Fee Tiers**: Supports different Uniswap pool fee tiers (0.05%, 0.3%, 1%)
4. **Exact Output**: Calculates the exact input needed to get 52,000 USDC

#### Example Usage:
```solidity
// Check how much WETH is needed
uint256 wethNeeded = validatorSale.quote(WETH_ADDRESS, 3000);

// Check how much WBTC is needed  
uint256 wbtcNeeded = validatorSale.quote(WBTC_ADDRESS, 500);

// Buyer then swaps their token for USDC on Uniswap before purchasing
```

### Quote System Flow Overview

```mermaid
graph TD
    A[Buyer has ETH/WBTC/other tokens] --> B{Wants to buy NFT}
    B --> C[Call quote function]
    C --> D[Get amount needed in their token]
    D --> E[Decision: Proceed?]
    E -->|Yes| F[Swap tokens for USDC on DEX]
    E -->|No| G[Cancel purchase]
    F --> H[Now has 52000 USDC]
    H --> I[Call buy function]
    I --> J[NFT purchased]
    
    style A fill:#f9f,stroke:#333,stroke-width:2px
    style J fill:#9f9,stroke:#333,stroke-width:2px
```

## Testing Setup

### Mainnet Forking for Quote Function Testing

The quote function requires interaction with Uniswap contracts on mainnet. To test this functionality locally, you need to set up mainnet forking:

#### 1. Get an RPC Provider
Sign up for a free account at:
- [Alchemy](https://www.alchemy.com/)
- [Infura](https://infura.io/)

#### 2. Configure Environment
Create a `.env` file in the contracts directory:
```bash
FORK_URL=https://eth-mainnet.alchemyapi.io/v2/YOUR_API_KEY
```

#### 3. Update Hardhat Config
Add forking configuration to `hardhat.config.ts`:
```typescript
networks: {
  hardhat: {
    forking: {
      url: process.env.FORK_URL || "",
      blockNumber: 18500000 // Optional: Pin to specific block
    }
  }
}
```

#### 4. Run Tests

Copy and paste these commands to run specific test suites:

```bash
# Run all tests
npm run hh:test

# ValidatorNFT Tests
npm run hh:test -- contracts/test/ValidatorNFT.test.ts

# ValidatorSale Integration Tests  
npm run hh:test -- contracts/test/ValidatorSale.test.ts

# ValidatorNFT and Sale Integration Tests
npm run hh:test -- contracts/test/ValidatorNFTSale.integration.test.ts

# Quote Function Tests (Simple - No Forking Required)
npm run hh:test -- contracts/test/ValidatorSale.quote.simple.test.ts

# Quote Function Tests (Full - Requires Mainnet Forking)
npm run hh:test -- contracts/test/ValidatorSale.quote.test.ts

# Run Multiple Specific Tests
npm run hh:test -- contracts/test/ValidatorNFT.test.ts contracts/test/ValidatorSale.test.ts

# Run Tests with Gas Reporting
REPORT_GAS=true npm run hh:test

# Run Tests with Coverage
npm run hh:coverage
```

#### Test File Descriptions

| Test File | Description | Forking Required |
|-----------|-------------|------------------|
| `ValidatorNFT.test.ts` | Core NFT functionality, mintAndTransfer, toggling | No |
| `ValidatorSale.test.ts` | Purchase flow with mocked USDC | No |
| `ValidatorNFTSale.integration.test.ts` | Integration between NFT and Sale contracts | No |
| `ValidatorSale.quote.simple.test.ts` | Basic quote validation tests | No |
| `ValidatorSale.quote.test.ts` | Full quote tests with real Uniswap | **Yes** |

### Why Mainnet Forking?
- The quote function calls Uniswap V3 Quoter at `0x61fFE014bA17989E743c5F6cB21bF9697530B21e`
- This contract only exists on mainnet
- Forking creates a local copy with all mainnet contracts and state
- Enables realistic testing without spending real money