LivoFactoryUniV4Unified

0x8024f24df3fe8b45daa0d9d94f59aa7e98da1b7f

Verification
Verified
v0.8.28+commit.7893614a
Type
Contract
17,339 bytes
ABI entries
88
42 read · 7 write
License
none

Contract information

Address
0x8024f24df3fe8b45daa0d9d94f59aa7e98da1b7f
Chain
Robinhood Chain (4663)
Compiler
v0.8.28+commit.7893614a
Optimization
Enabled
Creation tx
0x89c44f2d02…b13b549307

Token

Not a token

This contract does not expose ERC-20 metadata.

Read contract (42)

BONDING_CURVE()address
CREATOR_VAULT_BPS_STEP()uint256
CREATOR_VAULT_FACTORY()address
GRADUATOR()address
GRADUATOR_THICK()address
GRADUATOR_THIN()address
LAUNCHPAD()address
MASTER_FEE_HANDLER()address
MAX_CREATOR_VAULTS()uint256
MAX_CREATOR_VAULT_TOTAL_BPS()uint256
MAX_TAX_DECAY_DURATION_SECONDS()uint256
MAX_TAX_DECAY_START_COMBINED_BPS()uint256
MAX_TAX_DURATION_SECONDS()uint256
MAX_TOTAL_FEE_BPS()uint256
THICK_CURVE_BASE()address
THICK_VAULT_CURVE_10()address
THICK_VAULT_CURVE_15()address
THICK_VAULT_CURVE_20()address
THICK_VAULT_CURVE_25()address
THICK_VAULT_CURVE_30()address
THICK_VAULT_CURVE_5()address
THIN_CURVE_BASE()address
THIN_VAULT_CURVE_10()address
THIN_VAULT_CURVE_15()address
THIN_VAULT_CURVE_20()address
THIN_VAULT_CURVE_25()address
THIN_VAULT_CURVE_30()address
THIN_VAULT_CURVE_5()address
TOKEN_IMPL_BASE()address
TOKEN_IMPL_TAX()address
UPGRADE_INTERFACE_VERSION()string
VAULT_CURVE_10()address
VAULT_CURVE_15()address
VAULT_CURVE_20()address
VAULT_CURVE_25()address
VAULT_CURVE_30()address
VAULT_CURVE_5()address
maxBuyOnDeploy(uint8, uint256)uint256
owner()address
previewTokenImplementation(tuple[], tuple[], tuple, tuple)address
proxiableUUID()bytes32
quoteBuyOnDeploy(uint8, uint256, uint256, tuple, tuple)uint256

Events (9)

BondingCurveAssignedBuyOnDeployCreatorVaultsCreatedInitializedLpFeeBpsSetOwnershipTransferredTokenCreatedTokenReferralUpgraded

ABI

[
  {
    "inputs": [
      {
        "internalType": "address",
        "name": "launchpad",
        "type": "address"
      },
      {
        "components": [
          {
            "internalType": "address",
            "name": "base",
            "type": "address"
          },
          {
            "internalType": "address",
            "name": "tax",
            "type": "address"
          }
        ],
        "internalType": "struct ILivoFactory.TokenImpls",
        "name": "impls",
        "type": "tuple"
      },
      {
        "internalType": "address",
        "name": "bondingCurve",
        "type": "address"
      },
      {
        "internalType": "address",
        "name": "graduator",
        "type": "address"
      },
      {
        "internalType": "address",
        "name": "masterFeeHandler",
        "type": "address"
      },
      {
        "internalType": "address",
        "name": "creatorVaultFactory",
        "type": "address"
      },
      {
        "internalType": "address[6]",
        "name": "vaultBondingCurves",
        "type": "address[6]"
      },
      {
        "components": [
          {
            "components": [
              {
                "components": [
                  {
                    "internalType": "address",
                    "name": "base",
                    "type": "address"
                  },
                  {
                    "internalType": "address[6]",
                    "name": "vaults",
                    "type": "address[6]"
                  }
                ],
                "internalType": "struct ILivoFactory.TierCurves",
                "name": "thin",
                "type": "tuple"
              },
              {
                "components": [
                  {
                    "internalType": "address",
                    "name": "base",
                    "type": "address"
                  },
                  {
                    "internalType": "address[6]",
                    "name": "vaults",
                    "type": "address[6]"
                  }
                ],
                "internalType": "struct ILivoFactory.TierCurves",
                "name": "thick",
                "type": "tuple"
              }
            ],
            "internalType": "struct ILivoFactory.LiquidityTierConfig",
            "name": "curves",
            "type": "tuple"
          },
          {
            "components": [
              {
                "internalType": "address",
                "name": "thin",
                "type": "address"
              },
              {
                "internalType": "address",
                "name": "thick",
                "type": "address"
              }
            ],
            "internalType": "struct LivoFactoryUniV4Unified.TierGraduators",
            "name": "graduators",
            "type": "tuple"
          }
        ],
        "internalType": "struct LivoFactoryUniV4Unified.V4TierConfig",
        "name": "v4Tier",
        "type": "tuple"
      }
    ],
    "stateMutability": "nonpayable",
    "type": "constructor"
  },
  {
    "inputs": [
      {
        "internalType": "address",
        "name": "target",
        "type": "address"
      }
    ],
    "name": "AddressEmptyCode",
    "type": "error"
  },
  {
    "inputs": [],
    "name": "CreatorVaultAllocationTooHigh",
    "type": "error"
  },
  {
    "inputs": [],
    "name": "CreatorVaultDistributionFailed",
    "type": "error"
  },
  {
    "inputs": [
      {
        "internalType": "address",
        "name": "implementation",
        "type": "address"
      }
    ],
    "name": "ERC1967InvalidImplementation",
    "type": "error"
  },
  {
    "inputs": [],
    "name": "ERC1967NonPayable",
    "type": "error"
  },
  {
    "inputs": [],
    "name": "FailedDeployment",
    "type": "error"
  },
  {
    "inputs": [],
    "name": "FailedInnerCall",
    "type": "error"
  },
  {
    "inputs": [
      {
        "internalType": "uint256",
        "name": "balance",
        "type": "uint256"
      },
      {
        "internalType": "uint256",
        "name": "needed",
        "type": "uint256"
      }
    ],
    "name": "InsufficientBalance",
    "type": "error"
  },
  {
    "inputs": [],
    "name": "InvalidAntiSniperConfig",
    "type": "error"
  },
  {
    "inputs": [],
    "name": "InvalidCreatorVault",
    "type": "error"
  },
  {
    "inputs": [],
    "name": "InvalidFeeReceiver",
    "type": "error"
  },
  {
    "inputs": [],
    "name": "InvalidInitialization",
    "type": "error"
  },
  {
    "inputs": [],
    "name": "InvalidLpFeeBps",
    "type": "error"
  },
  {
    "inputs": [],
    "name": "InvalidNameOrSymbol",
    "type": "error"
  },
  {
    "inputs": [],
    "name": "InvalidShares",
    "type": "error"
  },
  {
    "inputs": [],
    "name": "InvalidSupplyShares",
    "type": "error"
  },
  {
    "inputs": [],
    "name": "InvalidTaxBps",
    "type": "error"
  },
  {
    "inputs": [],
    "name": "InvalidTaxConfig",
    "type": "error"
  },
  {
    "inputs": [],
    "name": "InvalidTaxDuration",
    "type": "error"
  },
  {
    "inputs": [],
    "name": "InvalidTokenAddress",
    "type": "error"
  },
  {
    "inputs": [],
    "name": "InvalidTokenOwner",
    "type": "error"
  },
  {
    "inputs": [],
    "name": "MultipleDirectFeeReceivers",
    "type": "error"
  },
  {
    "inputs": [],
    "name": "NotInitializing",
    "type": "error"
  },
  {
    "inputs": [
      {
        "internalType": "address",
        "name": "owner",
        "type": "address"
      }
    ],
    "name": "OwnableInvalidOwner",
    "type": "error"
  },
  {
    "inputs": [
      {
        "internalType": "address",
        "name": "account",
        "type": "address"
      }
    ],
    "name": "OwnableUnauthorizedAccount",
    "type": "error"
  },
  {
    "inputs": [
      {
        "internalType": "address",
        "name": "token",
        "type": "address"
      }
    ],
    "name": "SafeERC20FailedOperation",
    "type": "error"
  },
  {
    "inputs": [],
    "name": "TooManyCreatorVaults",
    "type": "error"
  },
  {
    "inputs": [],
    "name": "UUPSUnauthorizedCallContext",
    "type": "error"
  },
  {
    "inputs": [
      {
        "internalType": "bytes32",
        "name": "slot",
        "type": "bytes32"
      }
    ],
    "name": "UUPSUnsupportedProxiableUUID",
    "type": "error"
  },
  {
    "anonymous": false,
    "inputs": [
      {
        "indexed": true,
        "internalType": "address",
        "name": "token",
        "type": "address"
      },
      {
        "indexed": true,
        "internalType": "address",
        "name": "bondingCurve",
        "type": "address"
      }
    ],
    "name": "BondingCurveAssigned",
    "type": "event"
  },
  {
    "anonymous": false,
    "inputs": [
      {
        "indexed": true,
        "internalType": "address",
        "name": "token",
        "type": "address"
      },
      {
        "indexed": true,
        "internalType": "address",
        "name": "buyer",
        "type": "address"
      },
      {
        "indexed": false,
        "internalType": "uint256",
        "name": "ethSpent",
        "type": "uint256"
      },
      {
        "indexed": false,
        "internalType": "uint256",
        "name": "tokensBought",
        "type": "uint256"
      },
      {
        "indexed": false,
        "internalType": "address[]",
        "name": "recipients",
        "type": "address[]"
      },
      {
        "indexed": false,
        "internalType": "uint256[]",
        "name": "amounts",
        "type": "uint256[]"
      }
    ],
    "name": "BuyOnDeploy",
    "type": "event"
  },
  {
    "anonymous": false,
    "inputs": [
      {
        "indexed": true,
        "internalType": "address",
        "name": "token",
        "type": "address"
      },
      {
        "indexed": false,
        "internalType": "uint256",
        "name": "totalVaultAllocation",
        "type": "uint256"
      },
      {
        "indexed": false,
        "internalType": "address[]",
        "name": "vaults",
        "type": "address[]"
      },
      {
        "indexed": false,
        "internalType": "uint256[]",
        "name": "amounts",
        "type": "uint256[]"
      }
    ],
    "name": "CreatorVaultsCreated",
    "type": "event"
  },
  {
    "anonymous": false,
    "inputs": [
      {
        "indexed": false,
        "internalType": "uint64",
        "name": "version",
        "type": "uint64"
      }
    ],
    "name": "Initialized",
    "type": "event"
  },
  {
    "anonymous": false,
    "inputs": [
      {
        "indexed": true,
        "internalType": "address",
        "name": "token",
        "type": "address"
      },
      {
        "indexed": false,
        "internalType": "uint16",
        "name": "lpFeeBps",
        "type": "uint16"
      }
    ],
    "name": "LpFeeBpsSet",
    "type": "event"
  },
  {
    "anonymous": false,
    "inputs": [
      {
        "indexed": true,
        "internalType": "address",
        "name": "previousOwner",
        "type": "address"
      },
      {
        "indexed": true,
        "internalType": "address",
        "name": "newOwner",
        "type": "address"
      }
    ],
    "name": "OwnershipTransferred",
    "type": "event"
  },
  {
    "anonymous": false,
    "inputs": [
      {
        "indexed": true,
        "internalType": "address",
        "name": "token",
        "type": "address"
      },
      {
        "indexed": false,
        "internalType": "string",
        "name": "name",
        "type": "string"
      },
      {
        "indexed": false,
        "internalType": "string",
        "name": "symbol",
        "type": "string"
      },
      {
        "indexed": false,
        "internalType": "address",
        "name": "tokenOwner",
        "type": "address"
      },
      {
        "indexed": false,
        "internalType": "address",
        "name": "launchpad",
        "type": "address"
      },
      {
        "indexed": false,
        "internalType": "address",
        "name": "graduator",
        "type": "address"
      },
      {
        "indexed": false,
        "internalType": "address",
        "name": "feeHandler",
        "type": "address"
      }
    ],
    "name": "TokenCreated",
    "type": "event"
  },
  {
    "anonymous": false,
    "inputs": [
      {
        "indexed": true,
        "internalType": "address",
        "name": "token",
        "type": "address"
      },
      {
        "indexed": true,
        "internalType": "address",
        "name": "referral",
        "type": "address"
      }
    ],
    "name": "TokenReferral",
    "type": "event"
  },
  {
    "anonymous": false,
    "inputs": [
      {
        "indexed": true,
        "internalType": "address",
        "name": "implementation",
        "type": "address"
      }
    ],
    "name": "Upgraded",
    "type": "event"
  },
  {
    "inputs": [],
    "name": "BONDING_CURVE",
    "outputs": [
      {
        "internalType": "contract ILivoBondingCurve",
        "name": "",
        "type": "address"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "CREATOR_VAULT_BPS_STEP",
    "outputs": [
      {
        "internalType": "uint256",
        "name": "",
        "type": "uint256"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "CREATOR_VAULT_FACTORY",
    "outputs": [
      {
        "internalType": "contract ILivoCreatorVaultFactory",
        "name": "",
        "type": "address"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "GRADUATOR",
    "outputs": [
      {
        "internalType": "contract ILivoGraduator",
        "name": "",
        "type": "address"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "GRADUATOR_THICK",
    "outputs": [
      {
        "internalType": "address",
        "name": "",
        "type": "address"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "GRADUATOR_THIN",
    "outputs": [
      {
        "internalType": "address",
        "name": "",
        "type": "address"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "LAUNCHPAD",
    "outputs": [
      {
        "internalType": "contract ILivoLaunchpad",
        "name": "",
        "type": "address"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "MASTER_FEE_HANDLER",
    "outputs": [
      {
        "internalType": "contract ILivoMasterFeeHandler",
        "name": "",
        "type": "address"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "MAX_CREATOR_VAULTS",
    "outputs": [
      {
        "internalType": "uint256",
        "name": "",
        "type": "uint256"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "MAX_CREATOR_VAULT_TOTAL_BPS",
    "outputs": [
      {
        "internalType": "uint256",
        "name": "",
        "type": "uint256"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "MAX_TAX_DECAY_DURATION_SECONDS",
    "outputs": [
      {
        "internalType": "uint256",
        "name": "",
        "type": "uint256"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "MAX_TAX_DECAY_START_COMBINED_BPS",
    "outputs": [
      {
        "internalType": "uint256",
        "name": "",
        "type": "uint256"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "MAX_TAX_DURATION_SECONDS",
    "outputs": [
      {
        "internalType": "uint256",
        "name": "",
        "type": "uint256"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "MAX_TOTAL_FEE_BPS",
    "outputs": [
      {
        "internalType": "uint256",
        "name": "",
        "type": "uint256"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "THICK_CURVE_BASE",
    "outputs": [
      {
        "internalType": "contract ILivoBondingCurve",
        "name": "",
        "type": "address"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "THICK_VAULT_CURVE_10",
    "outputs": [
      {
        "internalType": "contract ILivoBondingCurve",
        "name": "",
        "type": "address"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "THICK_VAULT_CURVE_15",
    "outputs": [
      {
        "internalType": "contract ILivoBondingCurve",
        "name": "",
        "type": "address"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "THICK_VAULT_CURVE_20",
    "outputs": [
      {
        "internalType": "contract ILivoBondingCurve",
        "name": "",
        "type": "address"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "THICK_VAULT_CURVE_25",
    "outputs": [
      {
        "internalType": "contract ILivoBondingCurve",
        "name": "",
        "type": "address"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "THICK_VAULT_CURVE_30",
    "outputs": [
      {
        "internalType": "contract ILivoBondingCurve",
        "name": "",
        "type": "address"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "THICK_VAULT_CURVE_5",
    "outputs": [
      {
        "internalType": "contract ILivoBondingCurve",
        "name": "",
        "type": "address"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "THIN_CURVE_BASE",
    "outputs": [
      {
        "internalType": "contract ILivoBondingCurve",
        "name": "",
        "type": "address"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "THIN_VAULT_CURVE_10",
    "outputs": [
      {
        "internalType": "contract ILivoBondingCurve",
        "name": "",
        "type": "address"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "THIN_VAULT_CURVE_15",
    "outputs": [
      {
        "internalType": "contract ILivoBondingCurve",
        "name": "",
        "type": "address"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "THIN_VAULT_CURVE_20",
    "outputs": [
      {
        "internalType": "contract ILivoBondingCurve",
        "name": "",
        "type": "address"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "THIN_VAULT_CURVE_25",
    "outputs": [
      {
        "internalType": "contract ILivoBondingCurve",
        "name": "",
        "type": "address"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "THIN_VAULT_CURVE_30",
    "outputs": [
      {
        "internalType": "contract ILivoBondingCurve",
        "name": "",
        "type": "address"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "THIN_VAULT_CURVE_5",
    "outputs": [
      {
        "internalType": "contract ILivoBondingCurve",
        "name": "",
        "type": "address"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "TOKEN_IMPL_BASE",
    "outputs": [
      {
        "internalType": "address",
        "name": "",
        "type": "address"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "TOKEN_IMPL_TAX",
    "outputs": [
      {
        "internalType": "address",
        "name": "",
        "type": "address"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "UPGRADE_INTERFACE_VERSION",
    "outputs": [
      {
        "internalType": "string",
        "name": "",
        "type": "string"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "VAULT_CURVE_10",
    "outputs": [
      {
        "internalType": "contract ILivoBondingCurve",
        "name": "",
        "type": "address"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "VAULT_CURVE_15",
    "outputs": [
      {
        "internalType": "contract ILivoBondingCurve",
        "name": "",
        "type": "address"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "VAULT_CURVE_20",
    "outputs": [
      {
        "internalType": "contract ILivoBondingCurve",
        "name": "",
        "type": "address"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "VAULT_CURVE_25",
    "outputs": [
      {
        "internalType": "contract ILivoBondingCurve",
        "name": "",
        "type": "address"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "VAULT_CURVE_30",
    "outputs": [
      {
        "internalType": "contract ILivoBondingCurve",
        "name": "",
        "type": "address"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "VAULT_CURVE_5",
    "outputs": [
      {
        "internalType": "contract ILivoBondingCurve",
        "name": "",
        "type": "address"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [
      {
        "components": [
          {
            "internalType": "string",
            "name": "name",
            "type": "string"
          },
          {
            "internalType": "string",
            "name": "symbol",
            "type": "string"
          },
          {
            "internalType": "bytes32",
            "name": "salt",
            "type": "bytes32"
          },
          {
            "components": [
              {
                "internalType": "address",
                "name": "account",
                "type": "address"
              },
              {
                "internalType": "uint256",
                "name": "shares",
                "type": "uint256"
              },
              {
                "internalType": "bool",
                "name": "directFeesEnabled",
                "type": "bool"
              }
            ],
            "internalType": "struct ILivoFactory.FeeShare[]",
            "name": "feeShares",
            "type": "tuple[]"
          },
          {
            "internalType": "enum LiquidityTier",
            "name": "liquidityTier",
            "type": "uint8"
          }
        ],
        "internalType": "struct ILivoFactory.TokenSetupTiered",
        "name": "tokenSetup",
        "type": "tuple"
      },
      {
        "components": [
          {
            "internalType": "uint16",
            "name": "buyTaxBps",
            "type": "uint16"
          },
          {
            "internalType": "uint16",
            "name": "sellTaxBps",
            "type": "uint16"
          },
          {
            "internalType": "uint32",
            "name": "taxDurationSeconds",
            "type": "uint32"
          },
          {
            "internalType": "bool",
            "name": "startTaxFromLaunch",
            "type": "bool"
          },
          {
            "internalType": "uint16",
            "name": "buyTaxDecayStartBps",
            "type": "uint16"
          },
          {
            "internalType": "uint16",
            "name": "sellTaxDecayStartBps",
            "type": "uint16"
          },
          {
            "internalType": "uint32",
            "name": "taxDecayDuration",
            "type": "uint32"
          }
        ],
        "internalType": "struct TaxConfigs",
        "name": "taxConfigs",
        "type": "tuple"
      },
      {
        "components": [
          {
            "internalType": "bool",
            "name": "renounceOwnership",
            "type": "bool"
          },
          {
            "internalType": "uint16",
            "name": "lpFeeBps",
            "type": "uint16"
          }
        ],
        "internalType": "struct LivoFactoryUniV4Unified.UniV4Configs",
        "name": "univ4Configs",
        "type": "tuple"
      },
      {
        "components": [
          {
            "internalType": "address",
            "name": "account",
            "type": "address"
          },
          {
            "internalType": "uint256",
            "name": "shares",
            "type": "uint256"
          }
        ],
        "internalType": "struct ILivoFactory.SupplyShare[]",
        "name": "buyOnDeployShares",
        "type": "tuple[]"
      },
      {
        "components": [
          {
            "internalType": "uint16",
            "name": "maxBuyPerTxBps",
            "type": "uint16"
          },
          {
            "internalType": "uint16",
            "name": "maxWalletBps",
            "type": "uint16"
          },
          {
            "internalType": "uint40",
            "name": "protectionWindowSeconds",
            "type": "uint40"
          },
          {
            "internalType": "address[]",
            "name": "whitelist",
            "type": "address[]"
          }
        ],
        "internalType": "struct AntiSniperConfigs",
        "name": "antiSniperConfigs",
        "type": "tuple"
      },
      {
        "components": [
          {
            "internalType": "address",
            "name": "owner",
            "type": "address"
          },
          {
            "internalType": "uint256",
            "name": "supplyBps",
            "type": "uint256"
          },
          {
            "internalType": "uint256",
            "name": "cliffSeconds",
            "type": "uint256"
          },
          {
            "internalType": "uint256",
            "name": "vestingSeconds",
            "type": "uint256"
          }
        ],
        "internalType": "struct ILivoFactory.CreatorVault[]",
        "name": "creatorVaults",
        "type": "tuple[]"
      },
      {
        "internalType": "address",
        "name": "referral",
        "type": "address"
      }
    ],
    "name": "createToken",
    "outputs": [
      {
        "internalType": "address",
        "name": "token",
        "type": "address"
      }
    ],
    "stateMutability": "payable",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "string",
        "name": "name",
        "type": "string"
      },
      {
        "internalType": "string",
        "name": "symbol",
        "type": "string"
      },
      {
        "internalType": "bytes32",
        "name": "salt",
        "type": "bytes32"
      },
      {
        "components": [
          {
            "internalType": "address",
            "name": "account",
            "type": "address"
          },
          {
            "internalType": "uint256",
            "name": "shares",
            "type": "uint256"
          },
          {
            "internalType": "bool",
            "name": "directFeesEnabled",
            "type": "bool"
          }
        ],
        "internalType": "struct ILivoFactory.FeeShare[]",
        "name": "feeReceivers",
        "type": "tuple[]"
      },
      {
        "components": [
          {
            "internalType": "address",
            "name": "account",
            "type": "address"
          },
          {
            "internalType": "uint256",
            "name": "shares",
            "type": "uint256"
          }
        ],
        "internalType": "struct ILivoFactory.SupplyShare[]",
        "name": "supplyShares",
        "type": "tuple[]"
      },
      {
        "internalType": "bool",
        "name": "renounceOwnership_",
        "type": "bool"
      },
      {
        "components": [
          {
            "internalType": "uint16",
            "name": "buyTaxBps",
            "type": "uint16"
          },
          {
            "internalType": "uint16",
            "name": "sellTaxBps",
            "type": "uint16"
          },
          {
            "internalType": "uint32",
            "name": "taxDurationSeconds",
            "type": "uint32"
          },
          {
            "internalType": "bool",
            "name": "startTaxFromLaunch",
            "type": "bool"
          }
        ],
        "internalType": "struct TaxConfigInit",
        "name": "taxCfg",
        "type": "tuple"
      },
      {
        "components": [
          {
            "internalType": "uint16",
            "name": "maxBuyPerTxBps",
            "type": "uint16"
          },
          {
            "internalType": "uint16",
            "name": "maxWalletBps",
            "type": "uint16"
          },
          {
            "internalType": "uint40",
            "name": "protectionWindowSeconds",
            "type": "uint40"
          },
          {
            "internalType": "address[]",
            "name": "whitelist",
            "type": "address[]"
          }
        ],
        "internalType": "struct AntiSniperConfigs",
        "name": "antiSniperCfg",
        "type": "tuple"
      }
    ],
    "name": "createToken",
    "outputs": [
      {
        "internalType": "address",
        "name": "token",
        "type": "address"
      }
    ],
    "stateMutability": "payable",
    "type": "function"
  },
  {
    "inputs": [
      {
        "components": [
          {
            "internalType": "string",
            "name": "name",
            "type": "string"
          },
          {
            "internalType": "string",
            "name": "symbol",
            "type": "string"
          },
          {
            "internalType": "bytes32",
            "name": "salt",
            "type": "bytes32"
          },
          {
            "components": [
              {
                "internalType": "address",
                "name": "account",
                "type": "address"
              },
              {
                "internalType": "uint256",
                "name": "shares",
                "type": "uint256"
              },
              {
                "internalType": "bool",
                "name": "directFeesEnabled",
                "type": "bool"
              }
            ],
            "internalType": "struct ILivoFactory.FeeShare[]",
            "name": "feeShares",
            "type": "tuple[]"
          },
          {
            "internalType": "enum LiquidityTier",
            "name": "liquidityTier",
            "type": "uint8"
          }
        ],
        "internalType": "struct ILivoFactory.TokenSetupTiered",
        "name": "tokenSetup",
        "type": "tuple"
      },
      {
        "components": [
          {
            "internalType": "uint16",
            "name": "buyTaxBps",
            "type": "uint16"
          },
          {
            "internalType": "uint16",
            "name": "sellTaxBps",
            "type": "uint16"
          },
          {
            "internalType": "uint32",
            "name": "taxDurationSeconds",
            "type": "uint32"
          },
          {
            "internalType": "bool",
            "name": "startTaxFromLaunch",
            "type": "bool"
          },
          {
            "internalType": "uint16",
            "name": "buyTaxDecayStartBps",
            "type": "uint16"
          },
          {
            "internalType": "uint16",
            "name": "sellTaxDecayStartBps",
            "type": "uint16"
          },
          {
            "internalType": "uint32",
            "name": "taxDecayDuration",
            "type": "uint32"
          }
        ],
        "internalType": "struct TaxConfigs",
        "name": "taxConfigs",
        "type": "tuple"
      },
      {
        "components": [
          {
            "internalType": "bool",
            "name": "renounceOwnership",
            "type": "bool"
          },
          {
            "internalType": "uint16",
            "name": "lpFeeBps",
            "type": "uint16"
          }
        ],
        "internalType": "struct LivoFactoryUniV4Unified.UniV4Configs",
        "name": "univ4Configs",
        "type": "tuple"
      },
      {
        "components": [
          {
            "internalType": "address",
            "name": "account",
            "type": "address"
          },
          {
            "internalType": "uint256",
            "name": "shares",
            "type": "uint256"
          }
        ],
        "internalType": "struct ILivoFactory.SupplyShare[]",
        "name": "buyOnDeployShares",
        "type": "tuple[]"
      },
      {
        "components": [
          {
            "internalType": "uint16",
            "name": "maxBuyPerTxBps",
            "type": "uint16"
          },
          {
            "internalType": "uint16",
            "name": "maxWalletBps",
            "type": "uint16"
          },
          {
            "internalType": "uint40",
            "name": "protectionWindowSeconds",
            "type": "uint40"
          },
          {
            "internalType": "address[]",
            "name": "whitelist",
            "type": "address[]"
          }
        ],
        "internalType": "struct AntiSniperConfigs",
        "name": "antiSniperConfigs",
        "type": "tuple"
      },
      {
        "components": [
          {
            "internalType": "address",
            "name": "owner",
            "type": "address"
          },
          {
            "internalType": "uint256",
            "name": "supplyBps",
            "type": "uint256"
          },
          {
            "internalType": "uint256",
            "name": "cliffSeconds",
            "type": "uint256"
          },
          {
            "internalType": "uint256",
            "name": "vestingSeconds",
            "type": "uint256"
          }
        ],
        "internalType": "struct ILivoFactory.CreatorVault[]",
        "name": "creatorVaults",
        "type": "tuple[]"
      }
    ],
    "name": "createToken",
    "outputs": [
      {
        "internalType": "address",
        "name": "token",
        "type": "address"
      }
    ],
    "stateMutability": "payable",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "initialize",
    "outputs": [],
    "stateMutability": "nonpayable",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "enum LiquidityTier",
        "name": "tier",
        "type": "uint8"
      },
      {
        "internalType": "uint256",
        "name": "totalLockedInVaultsBps",
        "type": "uint256"
      }
    ],
    "name": "maxBuyOnDeploy",
    "outputs": [
      {
        "internalType": "uint256",
        "name": "maxTokens",
        "type": "uint256"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "owner",
    "outputs": [
      {
        "internalType": "address",
        "name": "",
        "type": "address"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [
      {
        "components": [
          {
            "internalType": "address",
            "name": "account",
            "type": "address"
          },
          {
            "internalType": "uint256",
            "name": "shares",
            "type": "uint256"
          },
          {
            "internalType": "bool",
            "name": "directFeesEnabled",
            "type": "bool"
          }
        ],
        "internalType": "struct ILivoFactory.FeeShare[]",
        "name": "",
        "type": "tuple[]"
      },
      {
        "components": [
          {
            "internalType": "address",
            "name": "account",
            "type": "address"
          },
          {
            "internalType": "uint256",
            "name": "shares",
            "type": "uint256"
          }
        ],
        "internalType": "struct ILivoFactory.SupplyShare[]",
        "name": "",
        "type": "tuple[]"
      },
      {
        "components": [
          {
            "internalType": "uint16",
            "name": "buyTaxBps",
            "type": "uint16"
          },
          {
            "internalType": "uint16",
            "name": "sellTaxBps",
            "type": "uint16"
          },
          {
            "internalType": "uint32",
            "name": "taxDurationSeconds",
            "type": "uint32"
          },
          {
            "internalType": "bool",
            "name": "startTaxFromLaunch",
            "type": "bool"
          },
          {
            "internalType": "uint16",
            "name": "buyTaxDecayStartBps",
            "type": "uint16"
          },
          {
            "internalType": "uint16",
            "name": "sellTaxDecayStartBps",
            "type": "uint16"
          },
          {
            "internalType": "uint32",
            "name": "taxDecayDuration",
            "type": "uint32"
          }
        ],
        "internalType": "struct TaxConfigs",
        "name": "taxCfg",
        "type": "tuple"
      },
      {
        "components": [
          {
            "internalType": "uint16",
            "name": "maxBuyPerTxBps",
            "type": "uint16"
          },
          {
            "internalType": "uint16",
            "name": "maxWalletBps",
            "type": "uint16"
          },
          {
            "internalType": "uint40",
            "name": "protectionWindowSeconds",
            "type": "uint40"
          },
          {
            "internalType": "address[]",
            "name": "whitelist",
            "type": "address[]"
          }
        ],
        "internalType": "struct AntiSniperConfigs",
        "name": "antiSniperCfg",
        "type": "tuple"
      }
    ],
    "name": "previewTokenImplementation",
    "outputs": [
      {
        "internalType": "address",
        "name": "",
        "type": "address"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "proxiableUUID",
    "outputs": [
      {
        "internalType": "bytes32",
        "name": "",
        "type": "bytes32"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "enum LiquidityTier",
        "name": "liquidityTier",
        "type": "uint8"
      },
      {
        "internalType": "uint256",
        "name": "tokenAmount",
        "type": "uint256"
      },
      {
        "internalType": "uint256",
        "name": "totalLockedInVaultsBps",
        "type": "uint256"
      },
      {
        "components": [
          {
            "internalType": "uint16",
            "name": "buyTaxBps",
            "type": "uint16"
          },
          {
            "internalType": "uint16",
            "name": "sellTaxBps",
            "type": "uint16"
          },
          {
            "internalType": "uint32",
            "name": "taxDurationSeconds",
            "type": "uint32"
          },
          {
            "internalType": "bool",
            "name": "startTaxFromLaunch",
            "type": "bool"
          },
          {
            "internalType": "uint16",
            "name": "buyTaxDecayStartBps",
            "type": "uint16"
          },
          {
            "internalType": "uint16",
            "name": "sellTaxDecayStartBps",
            "type": "uint16"
          },
          {
            "internalType": "uint32",
            "name": "taxDecayDuration",
            "type": "uint32"
          }
        ],
        "internalType": "struct TaxConfigs",
        "name": "taxCfg",
        "type": "tuple"
      },
      {
        "components": [
          {
            "internalType": "bool",
            "name": "renounceOwnership",
            "type": "bool"
          },
          {
            "internalType": "uint16",
            "name": "lpFeeBps",
            "type": "uint16"
          }
        ],
        "internalType": "struct LivoFactoryUniV4Unified.UniV4Configs",
        "name": "univ4Configs",
        "type": "tuple"
      }
    ],
    "name": "quoteBuyOnDeploy",
    "outputs": [
      {
        "internalType": "uint256",
        "name": "totalEthNeeded",
        "type": "uint256"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "renounceOwnership",
    "outputs": [],
    "stateMutability": "nonpayable",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "address",
        "name": "newOwner",
        "type": "address"
      }
    ],
    "name": "transferOwnership",
    "outputs": [],
    "stateMutability": "nonpayable",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "address",
        "name": "newImplementation",
        "type": "address"
      },
      {
        "internalType": "bytes",
        "name": "data",
        "type": "bytes"
      }
    ],
    "name": "upgradeToAndCall",
    "outputs": [],
    "stateMutability": "payable",
    "type": "function"
  }
]

Source code

// SPDX-License-Identifier: MIT
pragma solidity 0.8.28;

import {AntiSniperConfigs} from "src/tokens/SniperProtection.sol";
import {TaxConfigInit, TaxConfigs} from "src/interfaces/ILivoTaxableToken.sol";
import {LivoFactoryAbstract} from "src/factories/LivoFactoryAbstract.sol";
import {LiquidityTier} from "src/types/LiquidityTier.sol";

/// @notice Unified factory for the Uniswap V4 token family. Dispatches between two token
///         implementations (`base`, `tax`) based on whether tax is configured; anti-sniper
///         protection is a gated feature of both, not a separate impl.
///
///         Replaces `LivoFactoryUniV4`, `LivoFactoryTaxToken`, `LivoFactoryUniV4SniperProtected`,
///         and `LivoFactoryTaxTokenSniperProtected`.
contract LivoFactoryUniV4Unified is LivoFactoryAbstract {
    /// @notice V4-specific config bundle for the struct-based `createToken` overload.
    /// @dev `lpFeeBps` is the per-swap LP fee `LivoSwapHook` charges post-graduation. It is stored on
    ///      the token (via `InitializeParams.swapLpFeeBps`) and read back by the hook through
    ///      `getSwapFees`. Only `100` (1%) and `50` (0.5%) are accepted; `_validateUniv4Configs`
    ///      enforces the allowlist so misconfiguration is loud. A single graduator/hook pair serves both
    ///      fees — the hook reads the rate from the token instead of hardcoding it per variant, so the
    ///      graduator is selected by liquidity tier alone (`_resolveGraduator(tier)`), not by fee.
    struct UniV4Configs {
        bool renounceOwnership;
        uint16 lpFeeBps;
    }

    /// @notice Constructor-only bundle of the THIN/THICK tier V4 graduators. One graduator per tier: the
    ///         hook is fee-agnostic (reads the rate from the token), so a tier needs a single graduator
    ///         regardless of `lpFeeBps`. The DEFAULT-tier graduator is `GRADUATOR` in the abstract base.
    struct TierGraduators {
        address thin;
        address thick;
    }

    /// @notice Constructor-only bundle of all the V4 tier additions (curves + graduators), grouped into
    ///         one struct to keep the constructor's parameter count within the ABI-decode stack limit.
    struct V4TierConfig {
        LiquidityTierConfig curves;
        TierGraduators graduators;
    }

    /// @notice THIN/THICK tier graduators, one per tier. Each initializes its pool at the tier-specific
    ///         graduation price and pairs with the single fee-agnostic `LivoSwapHook`. Selected by
    ///         `_resolveGraduator(tier)`.
    address public immutable GRADUATOR_THIN;
    address public immutable GRADUATOR_THICK;

    /// @notice Pre-graduation launchpad LP fee for V4 tokens (bps), charged on every bonding-curve trade
    ///         and split treasury/creator by `V4_LAUNCHPAD_TREASURY_SHARE_BPS`. Fixed at 1% for every V4
    ///         token regardless of the post-graduation hook fee it selects (`UniV4Configs.lpFeeBps`, 50 or
    ///         100): the pre-graduation rate is a constant launchpad policy, decoupled from the LP fee the
    ///         hook charges after graduation.
    uint16 internal constant V4_LAUNCHPAD_LP_FEE_BPS = 100;

    /// @notice Treasury share of the V4 pre-graduation LP fee (bps): 60 treasury / 40 creator.
    uint16 internal constant V4_LAUNCHPAD_TREASURY_SHARE_BPS = 6_000;

    error InvalidLpFeeBps();

    constructor(
        address launchpad,
        TokenImpls memory impls,
        address bondingCurve,
        address graduator,
        address masterFeeHandler,
        address creatorVaultFactory,
        address[6] memory vaultBondingCurves,
        V4TierConfig memory v4Tier
    )
        LivoFactoryAbstract(
            launchpad,
            impls,
            bondingCurve,
            graduator,
            masterFeeHandler,
            creatorVaultFactory,
            vaultBondingCurves,
            v4Tier.curves
        )
    {
        GRADUATOR_THIN = v4Tier.graduators.thin;
        GRADUATOR_THICK = v4Tier.graduators.thick;
    }

    /////////////////////// EXTERNAL FUNCTIONS /////////////////////////

    // V4-only event-emission rule: any event whose presence is meant to signal "this is a V4 token"
    // (today: `LpFeeBpsSet`) MUST be emitted here in the V4 factory overloads, never inside the
    // shared `_createToken` umbrella in `LivoFactoryAbstract`. The umbrella runs for V2 deploys
    // too, so emitting V4-only events from there would leak them onto V2 tokens and break indexers
    // that use the event as a V4 marker. When adding a new V4-only event, follow this same pattern
    // (emit after `_createToken(...)` returns, in both overloads below).

    /// @notice Deploys a V4-family Livo token and registers it in the launchpad.
    ///         Dispatches between four implementations based on `taxCfg` and `antiSniperCfg`.
    ///         The per-token fee config is registered with the master fee handler at deploy time.
    ///         If `msg.value > 0`, buys supply and distributes it across `supplyShares`.
    /// @dev DEPRECATED: legacy positional overload, kept for backwards compatibility (unchanged
    ///      signature). New integrations should use the struct-based overload that takes `creatorVaults`
    ///      and the full `TaxConfigs`. Always deploys with the DEFAULT-tier graduator and a 100-bps swap
    ///      fee, no creator vaults and no launch-tax decay — the `TaxConfigInit` is lifted into a
    ///      `TaxConfigs` with the decay fields zeroed.
    function createToken(
        string calldata name,
        string calldata symbol,
        bytes32 salt,
        FeeShare[] calldata feeReceivers,
        SupplyShare[] calldata supplyShares,
        bool renounceOwnership_,
        TaxConfigInit calldata taxCfg,
        AntiSniperConfigs calldata antiSniperCfg
    ) external payable returns (address token) {
        // Positional overload always uses the 100-bps swap fee — only the struct-based overloads below
        // expose the 50-bps variant. See the "V4-only event-emission rule" comment above for why the
        // emit lives here.
        // Build `tokenSetup` first (consuming the deep `name`/`symbol`/`salt`/`feeReceivers` calldata
        // params) before introducing the `taxConfigs` memory local, to keep the stack shallow enough
        // to compile without `via_ir`.
        // Legacy overload always uses the DEFAULT liquidity tier + the 100-bps swap fee.
        TokenSetupTiered memory tokenSetup = TokenSetupTiered({
            name: name, symbol: symbol, salt: salt, feeShares: feeReceivers, liquidityTier: LiquidityTier.DEFAULT
        });
        TaxConfigs memory taxConfigs = _toTaxConfigs(taxCfg);
        _validateTotalFee(100, taxConfigs);
        token = _createToken(
            tokenSetup,
            renounceOwnership_ ? address(0) : msg.sender,
            address(GRADUATOR),
            100, // default swap fee for the legacy overload
            supplyShares,
            taxConfigs,
            antiSniperCfg,
            new CreatorVault[](0)
        );
        emit LpFeeBpsSet(token, 100);
    }

    /// @notice Struct-based overload taking the full `TaxConfigs` (static tax + optional linear launch-tax
    ///         decay), a `creatorVaults` array (pass empty for none) and a `TokenSetupTiered` selecting the
    ///         liquidity tier. `univ4Configs.lpFeeBps` is the post-graduation swap fee stored on the token
    ///         (100 or 50). Kept for backwards compatibility; new integrations should use the `referral`
    ///         overload below (the current recommended overload).
    function createToken(
        TokenSetupTiered calldata tokenSetup,
        TaxConfigs calldata taxConfigs,
        UniV4Configs calldata univ4Configs,
        SupplyShare[] calldata buyOnDeployShares,
        AntiSniperConfigs calldata antiSniperConfigs,
        CreatorVault[] calldata creatorVaults
    ) external payable returns (address token) {
        token = _createV4(tokenSetup, univ4Configs, buyOnDeployShares, taxConfigs, antiSniperConfigs, creatorVaults);
    }

    /// @notice Recommended overload: same as the `TokenSetupTiered` overload plus a `referral` address for
    ///         relayers that forward the creation and are entitled to a cut of the fees. When `referral` is
    ///         non-zero a `TokenReferral(token, referral)` event is emitted; no token storage or on-chain
    ///         payout is wired to it yet — it is purely an off-chain signal for now.
    function createToken(
        TokenSetupTiered calldata tokenSetup,
        TaxConfigs calldata taxConfigs,
        UniV4Configs calldata univ4Configs,
        SupplyShare[] calldata buyOnDeployShares,
        AntiSniperConfigs calldata antiSniperConfigs,
        CreatorVault[] calldata creatorVaults,
        address referral
    ) external payable returns (address token) {
        token = _createV4(tokenSetup, univ4Configs, buyOnDeployShares, taxConfigs, antiSniperConfigs, creatorVaults);
        if (referral != address(0)) emit TokenReferral(token, referral);
    }

    ///////////////////////// INTERNAL FUNCTIONS /////////////////////////

    /// @dev Shared tail of the two struct-based `createToken` overloads: validates the V4 config, resolves
    ///      the tier's graduator, deploys via the shared umbrella storing `univ4Configs.lpFeeBps` on the
    ///      token, and emits the V4-only `LpFeeBpsSet` marker. Factored out to keep each overload's stack
    ///      shallow enough to compile without `via_ir`. `tokenOwner`/`graduator` are inlined for the same
    ///      reason. Private to this V4 factory, so the "V4-only event-emission rule" above still holds —
    ///      the emit never runs for a V2 deploy.
    function _createV4(
        TokenSetupTiered calldata tokenSetup,
        UniV4Configs calldata univ4Configs,
        SupplyShare[] calldata buyOnDeployShares,
        TaxConfigs calldata taxConfigs,
        AntiSniperConfigs calldata antiSniperConfigs,
        CreatorVault[] calldata creatorVaults
    ) private returns (address token) {
        _validateUniv4Configs(univ4Configs);
        _validateTotalFee(univ4Configs.lpFeeBps, taxConfigs);
        token = _createToken(
            tokenSetup,
            univ4Configs.renounceOwnership ? address(0) : msg.sender,
            _resolveGraduator(tokenSetup.liquidityTier),
            univ4Configs.lpFeeBps,
            buyOnDeployShares,
            taxConfigs,
            antiSniperConfigs,
            creatorVaults
        );
        emit LpFeeBpsSet(token, univ4Configs.lpFeeBps);
    }

    /// @dev V4-specific config validation. `lpFeeBps` is the per-swap LP fee stored on the token and
    ///      read by the hook via `getSwapFees` — only the two supported tiers (100 = 1%, 50 = 0.5%)
    ///      are accepted, so a typo reverts instead of silently storing an unsupported fee. Add further
    ///      V4-only invariants here as the struct grows.
    function _validateUniv4Configs(UniV4Configs calldata configs) internal pure {
        require(configs.lpFeeBps == 100 || configs.lpFeeBps == 50, InvalidLpFeeBps());
    }

    /// @dev Maps a liquidity `tier` to its graduator, which graduates at the tier's price and pairs with
    ///      the single fee-agnostic `LivoSwapHook`. The swap fee is not a selection axis: it is stored on
    ///      the token (`swapLpFeeBps`) and read by the hook, so one graduator serves both 100 and 50 bps.
    function _resolveGraduator(LiquidityTier tier) internal view returns (address) {
        if (tier == LiquidityTier.DEFAULT) return address(GRADUATOR);
        if (tier == LiquidityTier.THIN) return GRADUATOR_THIN;
        return GRADUATOR_THICK; // THICK
    }

    /// @dev Pre-graduation launchpad LP fee, fixed at `V4_LAUNCHPAD_LP_FEE_BPS` (1%) for every V4 token
    ///      regardless of the post-graduation hook fee it selected. The pre-graduation rate is a constant
    ///      launchpad policy, decoupled from the post-graduation LP fee, so `graduator` is ignored.
    function _launchpadLpFeeBps(
        address /* graduator */
    )
        internal
        pure
        override
        returns (uint16)
    {
        return V4_LAUNCHPAD_LP_FEE_BPS;
    }

    /// @inheritdoc LivoFactoryAbstract
    function _launchpadTreasuryShareBps() internal pure override returns (uint16) {
        return V4_LAUNCHPAD_TREASURY_SHARE_BPS;
    }

    /// @notice Returns which token implementation `createToken(...)` would clone for the given inputs.
    /// @dev Mirrors the dispatch-relevant `createToken` inputs minus the identity fields (`name`,
    ///      `symbol`, `salt`) and ownership flag so the ABI stays stable when future features change
    ///      which inputs participate in dispatch. Today `taxCfg.taxDurationSeconds`,
    ///      `taxCfg.taxDecayDuration` (a decay-only token still clones the taxable impl) and
    ///      `antiSniperCfg.protectionWindowSeconds` matter for dispatch; disabled configs must
    ///      have all other tax/anti-sniper fields
    ///      empty/zero. Used by frontends to compute the initcode hash before mining a salt.
    function previewTokenImplementation(
        FeeShare[] calldata, /* feeReceivers */
        SupplyShare[] calldata, /* supplyShares */
        TaxConfigs calldata taxCfg,
        AntiSniperConfigs calldata antiSniperCfg
    ) external view returns (address) {
        _validateAntiSniperConfig(antiSniperCfg);
        _validateTaxConfig(taxCfg);
        return _previewTokenImplementation(taxCfg, antiSniperCfg);
    }

    /// @notice Quotes the ETH (msg.value) needed to receive ~`tokenAmount` tokens via the deployer buy.
    ///         Pass the same `taxCfg` and `univ4Configs` you'll pass to `createToken`; the buy fee is
    ///         derived from them (the fixed pre-graduation launchpad LP fee plus the buy tax) so the
    ///         frontend doesn't recompute it.
    /// @param tokenAmount Amount of tokens to receive
    /// @param totalLockedInVaultsBps Sum of `supplyBps` across the creator vaults (0 for none); selects
    ///        the same curve `createToken` uses. See `_quoteBuyOnDeploy`.
    /// @param taxCfg The tax config the token will be created with; only `buyTaxBps` affects the buy,
    ///        and only when the window is creation-anchored (`startTaxFromLaunch`) — a graduation-anchored
    ///        tax is not charged on the deploy buy (see `_deployBuyTaxBps`).
    /// @param univ4Configs The V4 config the token will be created with; `lpFeeBps` selects the
    ///        post-graduation hook fee. Validated here so the fee is one of the supported hook variants.
    ///        The deploy buy is a pre-graduation trade, so it is quoted at the fixed
    ///        `V4_LAUNCHPAD_LP_FEE_BPS`, not `lpFeeBps`.
    /// @return totalEthNeeded The msg.value to pass to createToken
    function quoteBuyOnDeploy(
        LiquidityTier liquidityTier,
        uint256 tokenAmount,
        uint256 totalLockedInVaultsBps,
        TaxConfigs calldata taxCfg,
        UniV4Configs calldata univ4Configs
    ) external view returns (uint256 totalEthNeeded) {
        _validateUniv4Configs(univ4Configs);
        return _quoteBuyOnDeploy(
            liquidityTier,
            tokenAmount,
            totalLockedInVaultsBps,
            uint256(V4_LAUNCHPAD_LP_FEE_BPS) + _deployBuyTaxBps(taxCfg)
        );
    }
}
Chain explorer3454msChain node82ms