> ## Documentation Index
> Fetch the complete documentation index at: https://docs.mouth.app/llms.txt
> Use this file to discover all available pages before exploring further.

# MouthBetFactory

> The upgradeable factory contract that deploys and manages individual bet contracts.

## Overview

`MouthBetFactory` is the core protocol contract. It deploys individual `MouthBet` escrow contracts and stores protocol-wide configuration.

Deployed behind a **UUPS proxy** so the address remains fixed across upgrades. Inherits from `Initializable`, `UUPSUpgradeable`, and `OwnableUpgradeable` (OpenZeppelin v5).

## State Variables

| Variable        | Type                          | Description                                                                                        |
| --------------- | ----------------------------- | -------------------------------------------------------------------------------------------------- |
| `resolver`      | `address`                     | Address authorized to resolve bets                                                                 |
| `treasury`      | `address`                     | Address receiving protocol fees                                                                    |
| `feePercentage` | `uint256`                     | Protocol fee in basis points (200 = 2%), snapshotted per-bet at creation and collected per-deposit |
| `usdc`          | `address`                     | USDC token address on Base                                                                         |
| `betCount`      | `uint256`                     | Total number of bets created                                                                       |
| `bets`          | `mapping(uint256 => address)` | Bet ID → Bet contract address                                                                      |
| `isMouthBet`    | `mapping(address => bool)`    | Verify if an address is a legitimate Mouth bet                                                     |

<Note>
  `owner` is inherited from `OwnableUpgradeable` and is not listed separately. Storage layout must be preserved across upgrades — new variables are only appended at the end. The `MAX_FEE` (500 = 5%) and `MIN_POT` (10e6 = 10 USDC) constants are also defined.
</Note>

## Functions

### `initialize`

Replaces the constructor. Called once at deployment via the proxy.

```solidity theme={null}
function initialize(
    address _resolver,
    address _treasury,
    address _usdc
) external initializer
```

**Logic:**

1. Initialize `OwnableUpgradeable` with `msg.sender` as owner
2. Initialize `UUPSUpgradeable`
3. Set `resolver`, `treasury`, `usdc`
4. Set `feePercentage` to 200 (2%)

### `createBet`

Deploys a new `MouthBet` contract, calls its `initialize()`, and transfers the Challenger's USDC deposit to the bet contract.

```solidity theme={null}
function createBet(
    address _challenger,
    address _opponent,          // address(0) if Open PvP
    uint256 _challengerAmount,  // USDC amount the Challenger deposits
    uint256 _odds,              // Challenger's perceived probability (10-90, default 50)
    uint256 _expirationDate,    // unix timestamp
    uint256 _acceptanceDeadline, // unix timestamp (mandatory for all bet types)
    string calldata _title,
    bool _disputeable           // If true, 48h dispute window. If false, immediately finalized.
) external returns (uint256 betId, address betAddress)
```

**Access**: Only callable by the Mouth backend (via server-side wallet) or directly by users. The Challenger must have approved the **Factory** contract to spend their USDC before calling.

**Logic:**

1. Validate parameters:
   * `_challengerAmount` must be greater than 0
   * `_odds` must be between 10 and 90 (inclusive)
   * `_expirationDate` must be in the future
   * `_acceptanceDeadline` must be in the future (`> block.timestamp`) and before `_expirationDate`
2. Calculate `totalOpponentAmount`: `_challengerAmount * (100 - _odds) / _odds`
3. Validate minimum pot: `_challengerAmount + totalOpponentAmount >= 10 USDC` (10e6 with 6 decimals)
4. Deploy new `MouthBet` contract: `MouthBet bet = new MouthBet()`
5. Call `bet.initialize(...)` with all parameters including `_disputeable` (sets `challengerDeposited = true`)
6. Transfer Challenger's USDC to the bet contract: `IERC20(usdc).safeTransferFrom(_challenger, address(bet), _challengerAmount)`
7. Store bet address in `bets` mapping
8. Mark address in `isMouthBet`
9. Emit `BetCreated` event
10. Return bet ID and contract address

<Note>
  The Challenger's USDC is transferred in the same transaction as bet creation. The Challenger must approve the **Factory** contract (not the bet contract) to spend their USDC. The opponent address can be a pre-generated Privy wallet for users who haven't signed up yet — see [Identity & Wallets](/architecture/identity-and-wallets).
</Note>

### `updateResolver`

Updates the resolver address.

```solidity theme={null}
function updateResolver(address _newResolver) external onlyOwner
```

### `updateTreasury`

Updates the treasury address.

```solidity theme={null}
function updateTreasury(address _newTreasury) external onlyOwner
```

### `updateFeePercentage`

Updates the protocol fee.

```solidity theme={null}
function updateFeePercentage(uint256 _newFee) external onlyOwner
```

**Constraint**: Fee cannot exceed 500 basis points (5%).

### `_authorizeUpgrade`

UUPS hook — restricts upgrades to the contract owner.

```solidity theme={null}
function _authorizeUpgrade(address newImplementation) internal override onlyOwner
```

### View Functions

```solidity theme={null}
function getBetAddress(uint256 _betId) external view returns (address)
function getBetCount() external view returns (uint256)
function verifyBet(address _bet) external view returns (bool)
```

## Events

```solidity theme={null}
event BetCreated(
    uint256 indexed betId,
    address indexed betAddress,
    address indexed challenger,
    address opponent,
    uint256 challengerAmount,
    uint256 totalOpponentAmount,
    uint256 odds,
    uint256 expirationDate
);

event ResolverUpdated(address indexed oldResolver, address indexed newResolver);
event TreasuryUpdated(address indexed oldTreasury, address indexed newTreasury);
event FeeUpdated(uint256 oldFee, uint256 newFee);
```

## Upgrade Path

The UUPS proxy allows upgrading the Factory implementation without changing its address or losing state:

```
v1 (now):    new MouthBet() + initialize()       ← full deploy
v2 (future): Clones.clone(impl) + initialize()   ← minimal proxy, ~10x cheaper
```

To migrate to clones, add a `mouthBetImplementation` state variable and update `createBet()` to use `Clones.clone()`. No changes needed to `MouthBet` itself.
