Skip to main content

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

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.

Functions

initialize

Replaces the constructor. Called once at deployment via the proxy.
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.
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
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.

updateResolver

Updates the resolver address.

updateTreasury

Updates the treasury address.

updateFeePercentage

Updates the protocol fee.
Constraint: Fee cannot exceed 500 basis points (5%).

_authorizeUpgrade

UUPS hook — restricts upgrades to the contract owner.

View Functions

Events

Upgrade Path

The UUPS proxy allows upgrading the Factory implementation without changing its address or losing state:
To migrate to clones, add a mouthBetImplementation state variable and update createBet() to use Clones.clone(). No changes needed to MouthBet itself.