HoodMarketsV3

0x9bddc8ddf28f5629c989a36eb5bb6c73cba60df5

Verification
Verified
v0.8.28+commit.7893614a
Type
Contract
20,038 bytes
ABI entries
62
23 read · 13 write
License
none

Contract information

Address
0x9bddc8ddf28f5629c989a36eb5bb6c73cba60df5
Chain
Robinhood Chain (4663)
Compiler
v0.8.28+commit.7893614a
Optimization
Enabled
Creation tx
0xf291bfe094…7c000bad8e

Token

Not a token

This contract does not expose ERC-20 metadata.

Read contract (23)

FRACTION_COUNT()uint256
FRACTION_VAULT_PERCENTAGE()uint8
MAX_CREATOR_REWARD()uint256
MAX_TICK()int24
MAX_VAULT_PERCENTAGE()uint256
POOL_FEE()uint24
TICK_SPACING()int24
TOKEN_SUPPLY()uint256
admins(address)bool
buyerRewardRelay()address
deploymentInfoForToken(address)address, uint256, address, address
deprecated()bool
fractionCollectionForToken(address)address
fractionDeployer()address
getTokensDeployedByUser(address)tuple[]
liquidityLocker()address
owner()address
positionManager()address
swapRouter()address
tokensDeployedByUsers(address, uint256)address, uint256, address, address
uniswapV3Factory()address
vault()address
weth()address

Events (9)

BuyerRewardRelayUpdatedBuyerShareIssuedHoodMarketsV3DeployerUpdatedLiquidityLockerUpdatedOwnershipTransferredSetAdminSetDeprecatedTokenCreatedVaultUpdated

ABI

[
  {
    "inputs": [
      {
        "internalType": "address",
        "name": "owner_",
        "type": "address"
      }
    ],
    "stateMutability": "nonpayable",
    "type": "constructor"
  },
  {
    "inputs": [],
    "name": "Deprecated",
    "type": "error"
  },
  {
    "inputs": [],
    "name": "InvalidBuyerRewardShareCount",
    "type": "error"
  },
  {
    "inputs": [],
    "name": "InvalidCreatorInfo",
    "type": "error"
  },
  {
    "inputs": [],
    "name": "InvalidCreatorReward",
    "type": "error"
  },
  {
    "inputs": [],
    "name": "InvalidInterfaceInfo",
    "type": "error"
  },
  {
    "inputs": [],
    "name": "InvalidTick",
    "type": "error"
  },
  {
    "inputs": [],
    "name": "InvalidVaultConfiguration",
    "type": "error"
  },
  {
    "inputs": [],
    "name": "LegacyVaultDisabled",
    "type": "error"
  },
  {
    "inputs": [],
    "name": "NotFound",
    "type": "error"
  },
  {
    "inputs": [],
    "name": "OnlyNonOriginatingChains",
    "type": "error"
  },
  {
    "inputs": [],
    "name": "OnlyOriginatingChain",
    "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": [],
    "name": "ReentrancyGuardReentrantCall",
    "type": "error"
  },
  {
    "inputs": [],
    "name": "Unauthorized",
    "type": "error"
  },
  {
    "inputs": [],
    "name": "ZeroTeamRewardRecipient",
    "type": "error"
  },
  {
    "anonymous": false,
    "inputs": [
      {
        "indexed": false,
        "internalType": "address",
        "name": "oldRelay",
        "type": "address"
      },
      {
        "indexed": false,
        "internalType": "address",
        "name": "newRelay",
        "type": "address"
      }
    ],
    "name": "BuyerRewardRelayUpdated",
    "type": "event"
  },
  {
    "anonymous": false,
    "inputs": [
      {
        "indexed": true,
        "internalType": "address",
        "name": "token",
        "type": "address"
      },
      {
        "indexed": true,
        "internalType": "address",
        "name": "buyer",
        "type": "address"
      },
      {
        "indexed": true,
        "internalType": "address",
        "name": "fractionCollection",
        "type": "address"
      }
    ],
    "name": "BuyerShareIssued",
    "type": "event"
  },
  {
    "anonymous": false,
    "inputs": [
      {
        "indexed": false,
        "internalType": "address",
        "name": "oldHoodMarketsV3Deployer",
        "type": "address"
      },
      {
        "indexed": false,
        "internalType": "address",
        "name": "newHoodMarketsV3Deployer",
        "type": "address"
      }
    ],
    "name": "HoodMarketsV3DeployerUpdated",
    "type": "event"
  },
  {
    "anonymous": false,
    "inputs": [
      {
        "indexed": false,
        "internalType": "address",
        "name": "oldLocker",
        "type": "address"
      },
      {
        "indexed": false,
        "internalType": "address",
        "name": "newLocker",
        "type": "address"
      }
    ],
    "name": "LiquidityLockerUpdated",
    "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": false,
        "internalType": "address",
        "name": "admin",
        "type": "address"
      },
      {
        "indexed": false,
        "internalType": "bool",
        "name": "isAdmin",
        "type": "bool"
      }
    ],
    "name": "SetAdmin",
    "type": "event"
  },
  {
    "anonymous": false,
    "inputs": [
      {
        "indexed": false,
        "internalType": "bool",
        "name": "deprecated",
        "type": "bool"
      }
    ],
    "name": "SetDeprecated",
    "type": "event"
  },
  {
    "anonymous": false,
    "inputs": [
      {
        "indexed": true,
        "internalType": "address",
        "name": "tokenAddress",
        "type": "address"
      },
      {
        "indexed": true,
        "internalType": "address",
        "name": "creatorAdmin",
        "type": "address"
      },
      {
        "indexed": true,
        "internalType": "address",
        "name": "interfaceAdmin",
        "type": "address"
      },
      {
        "indexed": false,
        "internalType": "address",
        "name": "creatorRewardRecipient",
        "type": "address"
      },
      {
        "indexed": false,
        "internalType": "address",
        "name": "interfaceRewardRecipient",
        "type": "address"
      },
      {
        "indexed": false,
        "internalType": "uint256",
        "name": "positionId",
        "type": "uint256"
      },
      {
        "indexed": false,
        "internalType": "string",
        "name": "name",
        "type": "string"
      },
      {
        "indexed": false,
        "internalType": "string",
        "name": "symbol",
        "type": "string"
      },
      {
        "indexed": false,
        "internalType": "int24",
        "name": "startingTickIfToken0IsNewToken",
        "type": "int24"
      },
      {
        "indexed": false,
        "internalType": "string",
        "name": "metadata",
        "type": "string"
      },
      {
        "indexed": false,
        "internalType": "uint256",
        "name": "amountTokensBought",
        "type": "uint256"
      },
      {
        "indexed": false,
        "internalType": "uint256",
        "name": "vaultDuration",
        "type": "uint256"
      },
      {
        "indexed": false,
        "internalType": "uint8",
        "name": "vaultPercentage",
        "type": "uint8"
      },
      {
        "indexed": false,
        "internalType": "address",
        "name": "fractionCollection",
        "type": "address"
      },
      {
        "indexed": false,
        "internalType": "uint256",
        "name": "fractionVaultAmount",
        "type": "uint256"
      },
      {
        "indexed": false,
        "internalType": "address",
        "name": "msgSender",
        "type": "address"
      }
    ],
    "name": "TokenCreated",
    "type": "event"
  },
  {
    "anonymous": false,
    "inputs": [
      {
        "indexed": false,
        "internalType": "address",
        "name": "oldVault",
        "type": "address"
      },
      {
        "indexed": false,
        "internalType": "address",
        "name": "newVault",
        "type": "address"
      }
    ],
    "name": "VaultUpdated",
    "type": "event"
  },
  {
    "inputs": [],
    "name": "FRACTION_COUNT",
    "outputs": [
      {
        "internalType": "uint256",
        "name": "",
        "type": "uint256"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "FRACTION_VAULT_PERCENTAGE",
    "outputs": [
      {
        "internalType": "uint8",
        "name": "",
        "type": "uint8"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "MAX_CREATOR_REWARD",
    "outputs": [
      {
        "internalType": "uint256",
        "name": "",
        "type": "uint256"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "MAX_TICK",
    "outputs": [
      {
        "internalType": "int24",
        "name": "",
        "type": "int24"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "MAX_VAULT_PERCENTAGE",
    "outputs": [
      {
        "internalType": "uint256",
        "name": "",
        "type": "uint256"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "POOL_FEE",
    "outputs": [
      {
        "internalType": "uint24",
        "name": "",
        "type": "uint24"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "TICK_SPACING",
    "outputs": [
      {
        "internalType": "int24",
        "name": "",
        "type": "int24"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "TOKEN_SUPPLY",
    "outputs": [
      {
        "internalType": "uint256",
        "name": "",
        "type": "uint256"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "address",
        "name": "",
        "type": "address"
      }
    ],
    "name": "admins",
    "outputs": [
      {
        "internalType": "bool",
        "name": "",
        "type": "bool"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "buyerRewardRelay",
    "outputs": [
      {
        "internalType": "address",
        "name": "",
        "type": "address"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "address",
        "name": "token",
        "type": "address"
      }
    ],
    "name": "claimRewards",
    "outputs": [],
    "stateMutability": "nonpayable",
    "type": "function"
  },
  {
    "inputs": [
      {
        "components": [
          {
            "components": [
              {
                "internalType": "string",
                "name": "name",
                "type": "string"
              },
              {
                "internalType": "string",
                "name": "symbol",
                "type": "string"
              },
              {
                "internalType": "bytes32",
                "name": "salt",
                "type": "bytes32"
              },
              {
                "internalType": "string",
                "name": "image",
                "type": "string"
              },
              {
                "internalType": "string",
                "name": "metadata",
                "type": "string"
              },
              {
                "internalType": "string",
                "name": "context",
                "type": "string"
              },
              {
                "internalType": "uint256",
                "name": "originatingChainId",
                "type": "uint256"
              }
            ],
            "internalType": "struct IHoodMarketsV3.TokenConfig",
            "name": "tokenConfig",
            "type": "tuple"
          },
          {
            "components": [
              {
                "internalType": "uint8",
                "name": "vaultPercentage",
                "type": "uint8"
              },
              {
                "internalType": "uint256",
                "name": "vaultDuration",
                "type": "uint256"
              }
            ],
            "internalType": "struct IHoodMarketsV3.VaultConfig",
            "name": "vaultConfig",
            "type": "tuple"
          },
          {
            "components": [
              {
                "internalType": "address",
                "name": "pairedToken",
                "type": "address"
              },
              {
                "internalType": "int24",
                "name": "tickIfToken0IsNewToken",
                "type": "int24"
              }
            ],
            "internalType": "struct IHoodMarketsV3.PoolConfig",
            "name": "poolConfig",
            "type": "tuple"
          },
          {
            "components": [
              {
                "internalType": "uint24",
                "name": "pairedTokenPoolFee",
                "type": "uint24"
              },
              {
                "internalType": "uint256",
                "name": "pairedTokenSwapAmountOutMinimum",
                "type": "uint256"
              }
            ],
            "internalType": "struct IHoodMarketsV3.InitialBuyConfig",
            "name": "initialBuyConfig",
            "type": "tuple"
          },
          {
            "components": [
              {
                "internalType": "uint256",
                "name": "creatorReward",
                "type": "uint256"
              },
              {
                "internalType": "address",
                "name": "creatorAdmin",
                "type": "address"
              },
              {
                "internalType": "address",
                "name": "creatorRewardRecipient",
                "type": "address"
              },
              {
                "internalType": "address",
                "name": "interfaceAdmin",
                "type": "address"
              },
              {
                "internalType": "address",
                "name": "interfaceRewardRecipient",
                "type": "address"
              }
            ],
            "internalType": "struct IHoodMarketsV3.RewardsConfig",
            "name": "rewardsConfig",
            "type": "tuple"
          },
          {
            "components": [
              {
                "internalType": "uint16",
                "name": "buyerRewardShareCount",
                "type": "uint16"
              }
            ],
            "internalType": "struct IHoodMarketsV3.FractionConfig",
            "name": "fractionConfig",
            "type": "tuple"
          }
        ],
        "internalType": "struct IHoodMarketsV3.DeploymentConfig",
        "name": "deploymentConfig",
        "type": "tuple"
      }
    ],
    "name": "deployToken",
    "outputs": [
      {
        "internalType": "address",
        "name": "tokenAddress",
        "type": "address"
      },
      {
        "internalType": "uint256",
        "name": "positionId",
        "type": "uint256"
      }
    ],
    "stateMutability": "payable",
    "type": "function"
  },
  {
    "inputs": [
      {
        "components": [
          {
            "components": [
              {
                "internalType": "string",
                "name": "name",
                "type": "string"
              },
              {
                "internalType": "string",
                "name": "symbol",
                "type": "string"
              },
              {
                "internalType": "bytes32",
                "name": "salt",
                "type": "bytes32"
              },
              {
                "internalType": "string",
                "name": "image",
                "type": "string"
              },
              {
                "internalType": "string",
                "name": "metadata",
                "type": "string"
              },
              {
                "internalType": "string",
                "name": "context",
                "type": "string"
              },
              {
                "internalType": "uint256",
                "name": "originatingChainId",
                "type": "uint256"
              }
            ],
            "internalType": "struct IHoodMarketsV3.TokenConfig",
            "name": "tokenConfig",
            "type": "tuple"
          },
          {
            "components": [
              {
                "internalType": "uint8",
                "name": "vaultPercentage",
                "type": "uint8"
              },
              {
                "internalType": "uint256",
                "name": "vaultDuration",
                "type": "uint256"
              }
            ],
            "internalType": "struct IHoodMarketsV3.VaultConfig",
            "name": "vaultConfig",
            "type": "tuple"
          },
          {
            "components": [
              {
                "internalType": "address",
                "name": "pairedToken",
                "type": "address"
              },
              {
                "internalType": "int24",
                "name": "tickIfToken0IsNewToken",
                "type": "int24"
              }
            ],
            "internalType": "struct IHoodMarketsV3.PoolConfig",
            "name": "poolConfig",
            "type": "tuple"
          },
          {
            "components": [
              {
                "internalType": "uint24",
                "name": "pairedTokenPoolFee",
                "type": "uint24"
              },
              {
                "internalType": "uint256",
                "name": "pairedTokenSwapAmountOutMinimum",
                "type": "uint256"
              }
            ],
            "internalType": "struct IHoodMarketsV3.InitialBuyConfig",
            "name": "initialBuyConfig",
            "type": "tuple"
          },
          {
            "components": [
              {
                "internalType": "uint256",
                "name": "creatorReward",
                "type": "uint256"
              },
              {
                "internalType": "address",
                "name": "creatorAdmin",
                "type": "address"
              },
              {
                "internalType": "address",
                "name": "creatorRewardRecipient",
                "type": "address"
              },
              {
                "internalType": "address",
                "name": "interfaceAdmin",
                "type": "address"
              },
              {
                "internalType": "address",
                "name": "interfaceRewardRecipient",
                "type": "address"
              }
            ],
            "internalType": "struct IHoodMarketsV3.RewardsConfig",
            "name": "rewardsConfig",
            "type": "tuple"
          },
          {
            "components": [
              {
                "internalType": "uint16",
                "name": "buyerRewardShareCount",
                "type": "uint16"
              }
            ],
            "internalType": "struct IHoodMarketsV3.FractionConfig",
            "name": "fractionConfig",
            "type": "tuple"
          }
        ],
        "internalType": "struct IHoodMarketsV3.DeploymentConfig",
        "name": "deploymentConfig",
        "type": "tuple"
      },
      {
        "internalType": "address",
        "name": "teamRewardRecipient",
        "type": "address"
      }
    ],
    "name": "deployTokenWithCustomTeamRewardRecipient",
    "outputs": [
      {
        "internalType": "address",
        "name": "tokenAddress",
        "type": "address"
      },
      {
        "internalType": "uint256",
        "name": "positionId",
        "type": "uint256"
      }
    ],
    "stateMutability": "payable",
    "type": "function"
  },
  {
    "inputs": [
      {
        "components": [
          {
            "internalType": "string",
            "name": "name",
            "type": "string"
          },
          {
            "internalType": "string",
            "name": "symbol",
            "type": "string"
          },
          {
            "internalType": "bytes32",
            "name": "salt",
            "type": "bytes32"
          },
          {
            "internalType": "string",
            "name": "image",
            "type": "string"
          },
          {
            "internalType": "string",
            "name": "metadata",
            "type": "string"
          },
          {
            "internalType": "string",
            "name": "context",
            "type": "string"
          },
          {
            "internalType": "uint256",
            "name": "originatingChainId",
            "type": "uint256"
          }
        ],
        "internalType": "struct IHoodMarketsV3.TokenConfig",
        "name": "tokenConfig",
        "type": "tuple"
      },
      {
        "internalType": "address",
        "name": "tokenAdmin",
        "type": "address"
      }
    ],
    "name": "deployTokenZeroSupply",
    "outputs": [
      {
        "internalType": "address",
        "name": "tokenAddress",
        "type": "address"
      }
    ],
    "stateMutability": "nonpayable",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "address",
        "name": "",
        "type": "address"
      }
    ],
    "name": "deploymentInfoForToken",
    "outputs": [
      {
        "internalType": "address",
        "name": "token",
        "type": "address"
      },
      {
        "internalType": "uint256",
        "name": "positionId",
        "type": "uint256"
      },
      {
        "internalType": "address",
        "name": "locker",
        "type": "address"
      },
      {
        "internalType": "address",
        "name": "fractionCollection",
        "type": "address"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "deprecated",
    "outputs": [
      {
        "internalType": "bool",
        "name": "",
        "type": "bool"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "address",
        "name": "",
        "type": "address"
      }
    ],
    "name": "fractionCollectionForToken",
    "outputs": [
      {
        "internalType": "address",
        "name": "",
        "type": "address"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "fractionDeployer",
    "outputs": [
      {
        "internalType": "contract HoodMarketsV3FractionDeployer",
        "name": "",
        "type": "address"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "address",
        "name": "user",
        "type": "address"
      }
    ],
    "name": "getTokensDeployedByUser",
    "outputs": [
      {
        "components": [
          {
            "internalType": "address",
            "name": "token",
            "type": "address"
          },
          {
            "internalType": "uint256",
            "name": "positionId",
            "type": "uint256"
          },
          {
            "internalType": "address",
            "name": "locker",
            "type": "address"
          },
          {
            "internalType": "address",
            "name": "fractionCollection",
            "type": "address"
          }
        ],
        "internalType": "struct IHoodMarketsV3.DeploymentInfo[]",
        "name": "",
        "type": "tuple[]"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "address",
        "name": "uniswapV3Factory_",
        "type": "address"
      },
      {
        "internalType": "address",
        "name": "positionManager_",
        "type": "address"
      },
      {
        "internalType": "address",
        "name": "swapRouter_",
        "type": "address"
      },
      {
        "internalType": "address",
        "name": "weth_",
        "type": "address"
      },
      {
        "internalType": "address",
        "name": "liquidityLocker_",
        "type": "address"
      },
      {
        "internalType": "address",
        "name": "vault_",
        "type": "address"
      },
      {
        "internalType": "address",
        "name": "fractionDeployer_",
        "type": "address"
      }
    ],
    "name": "initialize",
    "outputs": [],
    "stateMutability": "nonpayable",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "address",
        "name": "token",
        "type": "address"
      },
      {
        "internalType": "address",
        "name": "buyer",
        "type": "address"
      }
    ],
    "name": "issueBuyerShare",
    "outputs": [],
    "stateMutability": "nonpayable",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "liquidityLocker",
    "outputs": [
      {
        "internalType": "contract IHoodMarketsV3LpLocker",
        "name": "",
        "type": "address"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "owner",
    "outputs": [
      {
        "internalType": "address",
        "name": "",
        "type": "address"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "positionManager",
    "outputs": [
      {
        "internalType": "contract INonfungiblePositionManager",
        "name": "",
        "type": "address"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "renounceOwnership",
    "outputs": [],
    "stateMutability": "nonpayable",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "address",
        "name": "admin",
        "type": "address"
      },
      {
        "internalType": "bool",
        "name": "isAdmin",
        "type": "bool"
      }
    ],
    "name": "setAdmin",
    "outputs": [],
    "stateMutability": "nonpayable",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "address",
        "name": "relay",
        "type": "address"
      }
    ],
    "name": "setBuyerRewardRelay",
    "outputs": [],
    "stateMutability": "nonpayable",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "bool",
        "name": "deprecated_",
        "type": "bool"
      }
    ],
    "name": "setDeprecated",
    "outputs": [],
    "stateMutability": "nonpayable",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "swapRouter",
    "outputs": [
      {
        "internalType": "contract ISwapRouter",
        "name": "",
        "type": "address"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "address",
        "name": "",
        "type": "address"
      },
      {
        "internalType": "uint256",
        "name": "",
        "type": "uint256"
      }
    ],
    "name": "tokensDeployedByUsers",
    "outputs": [
      {
        "internalType": "address",
        "name": "token",
        "type": "address"
      },
      {
        "internalType": "uint256",
        "name": "positionId",
        "type": "uint256"
      },
      {
        "internalType": "address",
        "name": "locker",
        "type": "address"
      },
      {
        "internalType": "address",
        "name": "fractionCollection",
        "type": "address"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "address",
        "name": "newOwner",
        "type": "address"
      }
    ],
    "name": "transferOwnership",
    "outputs": [],
    "stateMutability": "nonpayable",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "uniswapV3Factory",
    "outputs": [
      {
        "internalType": "contract IUniswapV3Factory",
        "name": "",
        "type": "address"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "address",
        "name": "newLocker",
        "type": "address"
      }
    ],
    "name": "updateLiquidityLocker",
    "outputs": [],
    "stateMutability": "nonpayable",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "address",
        "name": "newVault",
        "type": "address"
      }
    ],
    "name": "updateVault",
    "outputs": [],
    "stateMutability": "nonpayable",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "vault",
    "outputs": [
      {
        "internalType": "contract IHoodMarketsV3Vault",
        "name": "",
        "type": "address"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "weth",
    "outputs": [
      {
        "internalType": "address",
        "name": "",
        "type": "address"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  }
]

Source code

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

import {HoodMarketsAsciiBanner} from "../HoodMarketsAsciiBanner.sol";
import {HoodMarketsV3Deployer} from "./HoodMarketsV3Deployer.sol";
import {HoodMarketsV3FractionDeployer} from "./HoodMarketsV3FractionDeployer.sol";

import {IHoodMarketsV3} from "./interfaces/IHoodMarketsV3.sol";
import {IHoodMarketsV3TokenFraction} from "./interfaces/IHoodMarketsV3TokenFraction.sol";
import {IHoodMarketsV3Vault} from "./interfaces/IHoodMarketsV3Vault.sol";
import {IHoodMarketsV3LpLocker} from "./interfaces/IHoodMarketsV3LpLocker.sol";
import {
    INonfungiblePositionManager,
    ISwapRouter,
    IUniswapV3Factory,
    IUniswapV3Pool
} from "./interfaces/uniswapv3.sol";
import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol";
import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import {ReentrancyGuard} from "@openzeppelin/contracts/utils/ReentrancyGuard.sol";
import {TickMath} from "@uniswap/v3-core/contracts/libraries/TickMath.sol";

/// @notice hood.markets V3 token launcher (Uniswap V3)
contract HoodMarketsV3 is Ownable, ReentrancyGuard, IHoodMarketsV3 {
    using TickMath for int24;

    string constant version = "0.6.0";

    IUniswapV3Factory public uniswapV3Factory;
    INonfungiblePositionManager public positionManager;
    ISwapRouter public swapRouter;
    address public weth;

    uint256 public constant TOKEN_SUPPLY = 100_000_000_000_000_000_000_000_000_000; // 100b with 18 decimals
    uint24 public constant POOL_FEE = 10_000; // 1%
    int24 public constant TICK_SPACING = 200;
    int24 public constant MAX_TICK = 887_200;

    IHoodMarketsV3LpLocker public liquidityLocker;
    IHoodMarketsV3Vault public vault;
    HoodMarketsV3FractionDeployer public fractionDeployer;
    uint256 public constant MAX_CREATOR_REWARD = 95;
    uint256 public constant MAX_VAULT_PERCENTAGE = 30;
    uint256 public constant FRACTION_COUNT = 1000;
    uint8 public constant FRACTION_VAULT_PERCENTAGE = 10;

    bool public deprecated;

    mapping(address => bool) public admins;
    mapping(address => address) public fractionCollectionForToken;

    address public buyerRewardRelay;

    mapping(address => DeploymentInfo[]) public tokensDeployedByUsers;
    mapping(address => DeploymentInfo) public deploymentInfoForToken;

    constructor(address owner_) Ownable(owner_) {
        // only non-originating tokens deployments are enabled
        // before initialization
        deprecated = true;
    }

    function initialize(
        address uniswapV3Factory_,
        address positionManager_,
        address swapRouter_,
        address weth_,
        address liquidityLocker_,
        address vault_,
        address fractionDeployer_
    ) external onlyOwner {
        // uniswap configurations
        uniswapV3Factory = IUniswapV3Factory(uniswapV3Factory_);
        positionManager = INonfungiblePositionManager(positionManager_);
        swapRouter = ISwapRouter(swapRouter_);

        // weth configurations
        weth = weth_;
        IERC20(weth).approve(address(positionManager), type(uint256).max);

        // liquidity locker configurations
        liquidityLocker = IHoodMarketsV3LpLocker(liquidityLocker_);

        // vault configurations
        vault = IHoodMarketsV3Vault(vault_);

        fractionDeployer = HoodMarketsV3FractionDeployer(fractionDeployer_);

        // enable deployments
        deprecated = false;
    }

    function getTokensDeployedByUser(address user)
        external
        view
        returns (DeploymentInfo[] memory)
    {
        return tokensDeployedByUsers[user];
    }

    function updateLiquidityLocker(address newLocker) external onlyOwner {
        address oldLocker = address(liquidityLocker);
        liquidityLocker = IHoodMarketsV3LpLocker(newLocker);
        emit LiquidityLockerUpdated(oldLocker, newLocker);
    }

    function updateVault(address newVault) external onlyOwner {
        address oldVault = address(vault);
        vault = IHoodMarketsV3Vault(newVault);
        emit VaultUpdated(oldVault, newVault);
    }

    function setDeprecated(bool deprecated_) external onlyOwner {
        deprecated = deprecated_;
        emit SetDeprecated(deprecated_);
    }

    function setAdmin(address admin, bool isAdmin) external onlyOwner {
        admins[admin] = isAdmin;
        emit SetAdmin(admin, isAdmin);
    }

    function setBuyerRewardRelay(address relay) external onlyOwner {
        address oldRelay = buyerRewardRelay;
        buyerRewardRelay = relay;
        emit BuyerRewardRelayUpdated(oldRelay, relay);
    }

    /// @notice Issue one buyer-reward share to a first-time pool buyer (hood.markets relay or fee admin).
    function issueBuyerShare(address token, address buyer) external {
        if (msg.sender != buyerRewardRelay && !admins[msg.sender] && msg.sender != owner()) {
            revert Unauthorized();
        }
        address fractionCollection = fractionCollectionForToken[token];
        if (fractionCollection == address(0)) revert NotFound();
        IHoodMarketsV3TokenFraction(fractionCollection).issueBuyerShare(buyer);
        emit BuyerShareIssued(token, buyer, fractionCollection);
    }

    function claimRewards(address token) external {
        DeploymentInfo memory deploymentInfo = deploymentInfoForToken[token];

        if (deploymentInfo.token == address(0)) revert NotFound();

        IHoodMarketsV3LpLocker(deploymentInfo.locker).collectRewards(deploymentInfo.positionId);
    }

    // deploy a token on a non-originating chain with 0 supply,
    // this can be used to bridge tokens between superchains.
    function deployTokenZeroSupply(TokenConfig memory tokenConfig, address tokenAdmin)
        external
        returns (address tokenAddress)
    {
        if (block.chainid == tokenConfig.originatingChainId) revert OnlyNonOriginatingChains();
        tokenAddress = HoodMarketsV3Deployer.deployToken(tokenConfig, tokenAdmin, TOKEN_SUPPLY);
    }

    // Deploy a token with a custom protocol reward recipient,
    // only protocol admins can call this function
    function deployTokenWithCustomTeamRewardRecipient(
        DeploymentConfig memory deploymentConfig,
        address teamRewardRecipient
    ) external payable returns (address tokenAddress, uint256 positionId) {
        if (!admins[msg.sender]) revert Unauthorized();
        if (teamRewardRecipient == address(0)) revert ZeroTeamRewardRecipient();

        (tokenAddress, positionId) = deployToken(deploymentConfig);

        // set the override protocol reward recipient for the token
        liquidityLocker.setOverrideTeamRewardRecipientForToken(positionId, teamRewardRecipient);
    }

    // Deploy a token and pool with the option to vault the token and buy an initial amount
    function deployToken(DeploymentConfig memory deploymentConfig)
        public
        payable
        nonReentrant
        returns (address tokenAddress, uint256 positionId)
    {
        if (deprecated) revert Deprecated();
        if (block.chainid != deploymentConfig.tokenConfig.originatingChainId) {
            revert OnlyOriginatingChain();
        }

        // deploy the token
        tokenAddress = HoodMarketsV3Deployer.deployToken(
            deploymentConfig.tokenConfig, deploymentConfig.rewardsConfig.creatorAdmin, TOKEN_SUPPLY
        );

        if (
            deploymentConfig.vaultConfig.vaultDuration > 0
                || deploymentConfig.vaultConfig.vaultPercentage > 0
        ) {
            revert LegacyVaultDisabled();
        }

        if (deploymentConfig.fractionConfig.buyerRewardShareCount > FRACTION_COUNT) {
            revert InvalidBuyerRewardShareCount();
        }

        uint256 fractionVaultAmount = (TOKEN_SUPPLY * FRACTION_VAULT_PERCENTAGE) / 100;
        uint256 poolSupply = TOKEN_SUPPLY - fractionVaultAmount;

        address fractionCollection = address(0);
        if (address(fractionDeployer) != address(0)) {
            IERC20(tokenAddress).approve(address(fractionDeployer), fractionVaultAmount);
            fractionCollection = fractionDeployer.deployFraction(
                tokenAddress,
                deploymentConfig.rewardsConfig.creatorAdmin,
                fractionVaultAmount,
                deploymentConfig.fractionConfig.buyerRewardShareCount
            );
            fractionCollectionForToken[tokenAddress] = fractionCollection;
        }

        // configure the pool
        IERC20(tokenAddress).approve(address(positionManager), poolSupply);
        address poolAddress;
        (positionId, poolAddress) = _configurePool(
            tokenAddress,
            deploymentConfig.poolConfig.pairedToken,
            deploymentConfig.poolConfig.tickIfToken0IsNewToken,
            poolSupply
        );

        RewardsConfig memory rewardsConfig = deploymentConfig.rewardsConfig;
        if (fractionCollection != address(0)) {
            (,, address token0, address token1,,,,,,,,) =
                positionManager.positions(positionId);
            IHoodMarketsV3TokenFraction(fractionCollection).configureFeeRewards(
                positionId, token0, token1, poolAddress
            );
            // Route creator fees to share holders unless a custom recipient was chosen
            // (e.g. platform-only rate limit uses the platform treasury wallet).
            if (rewardsConfig.creatorRewardRecipient == rewardsConfig.creatorAdmin) {
                rewardsConfig.creatorRewardRecipient = fractionCollection;
            }
        }

        // lock the lp tokens
        _lockLPTokens(positionId, rewardsConfig);

        // perform initial buy if eth was sent, use the creator admin as the recipient
        uint256 amountTokensBought = msg.value > 0
            ? _initialBuy(
                tokenAddress,
                deploymentConfig.poolConfig.pairedToken,
                deploymentConfig.initialBuyConfig.pairedTokenPoolFee,
                deploymentConfig.initialBuyConfig.pairedTokenSwapAmountOutMinimum,
                deploymentConfig.rewardsConfig.creatorAdmin
            )
            : 0;

        // add the deployment info to the deployment info for token
        DeploymentInfo memory deploymentInfo = DeploymentInfo({
            token: tokenAddress,
            positionId: positionId,
            locker: address(liquidityLocker),
            fractionCollection: fractionCollection
        });
        deploymentInfoForToken[tokenAddress] = deploymentInfo;
        tokensDeployedByUsers[deploymentConfig.rewardsConfig.creatorAdmin].push(deploymentInfo);

        emit TokenCreated({
            tokenAddress: tokenAddress,
            positionId: positionId,
            creatorAdmin: deploymentConfig.rewardsConfig.creatorAdmin,
            creatorRewardRecipient: deploymentConfig.rewardsConfig.creatorRewardRecipient,
            interfaceAdmin: deploymentConfig.rewardsConfig.interfaceAdmin,
            interfaceRewardRecipient: deploymentConfig.rewardsConfig.interfaceRewardRecipient,
            name: deploymentConfig.tokenConfig.name,
            symbol: deploymentConfig.tokenConfig.symbol,
            startingTickIfToken0IsNewToken: deploymentConfig.poolConfig.tickIfToken0IsNewToken,
            metadata: deploymentConfig.tokenConfig.metadata,
            amountTokensBought: amountTokensBought,
            vaultDuration: 0,
            vaultPercentage: FRACTION_VAULT_PERCENTAGE,
            fractionCollection: fractionCollection,
            fractionVaultAmount: fractionVaultAmount,
            msgSender: msg.sender
        });
    }

    // Lock the lp tokens and add the user reward recipient to the liquidity locker
    function _lockLPTokens(uint256 positionId, RewardsConfig memory rewardsConfig) internal {
        // ensure the creator reward is not greater than the max creator reward or zero
        if (rewardsConfig.creatorReward > MAX_CREATOR_REWARD || rewardsConfig.creatorReward == 0) {
            revert InvalidCreatorReward();
        }

        // ensure that the creator admin is set
        if (rewardsConfig.creatorAdmin == address(0)) {
            revert InvalidCreatorInfo();
        }

        // if the creator reward is not max, ensure the interface admin is set
        if (
            rewardsConfig.creatorReward < MAX_CREATOR_REWARD
                && rewardsConfig.interfaceAdmin == address(0)
        ) {
            revert InvalidInterfaceInfo();
        }

        // transfer the lp position to the liquidity locker
        positionManager.safeTransferFrom(address(this), address(liquidityLocker), positionId);

        // add the user reward recipient to the liquidity locker
        liquidityLocker.addTokenReward(
            IHoodMarketsV3LpLocker.TokenRewardInfo({
                lpTokenId: positionId,
                creatorReward: rewardsConfig.creatorReward,
                creator: IHoodMarketsV3LpLocker.RewardRecipient({
                    admin: rewardsConfig.creatorAdmin,
                    recipient: rewardsConfig.creatorRewardRecipient
                }),
                interfacer: IHoodMarketsV3LpLocker.RewardRecipient({
                    admin: rewardsConfig.interfaceAdmin,
                    recipient: rewardsConfig.interfaceRewardRecipient
                })
            })
        );
    }

    function _configurePool(
        address newToken,
        address pairedToken,
        int24 tickIfToken0IsNewToken,
        uint256 supplyPerPool
    ) internal returns (uint256 positionId, address poolAddress) {
        // check tick spacing
        if (tickIfToken0IsNewToken % TICK_SPACING != 0) {
            revert InvalidTick();
        }

        // Pool ordering
        bool token0IsNewToken = newToken < pairedToken;

        // flip tick if token0 is not the new token
        int24 tick = token0IsNewToken ? tickIfToken0IsNewToken : -tickIfToken0IsNewToken;

        uint160 sqrtPriceX96 = tick.getSqrtRatioAtTick();

        // Create pool
        poolAddress = uniswapV3Factory.createPool(newToken, pairedToken, POOL_FEE);

        // Initialize pool
        IUniswapV3Pool(poolAddress).initialize(sqrtPriceX96);

        INonfungiblePositionManager.MintParams memory params = INonfungiblePositionManager
            .MintParams(
            token0IsNewToken ? newToken : pairedToken,
            token0IsNewToken ? pairedToken : newToken,
            POOL_FEE,
            token0IsNewToken ? tick : -MAX_TICK,
            token0IsNewToken ? MAX_TICK : tick,
            token0IsNewToken ? supplyPerPool : 0,
            token0IsNewToken ? 0 : supplyPerPool,
            0,
            0,
            address(this),
            block.timestamp
        );
        (positionId,,,) = positionManager.mint(params);
    }

    function _initialBuy(
        address token,
        address pairedToken,
        uint24 pairedTokenPoolFee,
        uint256 pairedTokenSwapAmountOutMinimum,
        address recipient
    ) internal returns (uint256 amountTokensBought) {
        // amount in is the amount of eth sent to perform the intial buy with
        uint256 pairedTokenAmountIn = msg.value;

        // if the paired token is not weth, we need to swap from weth to paired token
        if (pairedToken != weth) {
            // swap from weth to paired token
            ISwapRouter.ExactInputSingleParams memory swapParams = ISwapRouter
                .ExactInputSingleParams({
                tokenIn: weth, // The token we are exchanging from (ETH wrapped as WETH)
                tokenOut: pairedToken, // The token we are exchanging to
                fee: pairedTokenPoolFee, // The pool fee
                recipient: address(this), // The recipient address
                amountIn: msg.value, // The amount of ETH (WETH) to be swapped
                amountOutMinimum: pairedTokenSwapAmountOutMinimum, // Minimum amount to receive
                sqrtPriceLimitX96: 0 // No price limit
            });

            // execute the swap to get pair tokens for the initial buy
            pairedTokenAmountIn = swapRouter.exactInputSingle{value: msg.value}(swapParams);

            // approve the swap router to spend the paired token
            IERC20(pairedToken).approve(address(swapRouter), pairedTokenAmountIn);
        }

        // swap from paired token to token
        ISwapRouter.ExactInputSingleParams memory swapParamsToken = ISwapRouter
            .ExactInputSingleParams({
            tokenIn: pairedToken, // The token we are exchanging from
            tokenOut: token, // The token we are exchanging to
            fee: POOL_FEE, // The pool fee
            recipient: recipient, // The recipient address
            amountIn: pairedTokenAmountIn, // The amount of paired token to be swapped
            amountOutMinimum: 0, // Minimum amount to receive
            sqrtPriceLimitX96: 0 // No price limit
        });

        // execute the swap
        amountTokensBought =
            swapRouter.exactInputSingle{value: pairedToken == weth ? msg.value : 0}(swapParamsToken);
    }
}
Chain explorer3808msChain node94ms