FlowFactoryC

0x7fd56360a20c3ebc8537a6b3aef2a6b827c2ffc8

Verification
Verified
v0.8.26+commit.8a97fa7a
Type
Contract
4,126 bytes
ABI entries
22
19 read · 1 write
License
none

Contract information

Address
0x7fd56360a20c3ebc8537a6b3aef2a6b827c2ffc8
Chain
Robinhood Chain (4663)
Compiler
v0.8.26+commit.8a97fa7a
Optimization
Enabled
Creation tx
0x3458ea2bc2…618e6d00a8

Token

Not a token

This contract does not expose ERC-20 metadata.

Read contract (19)

LP_FEE()uint24
TICK_SPACING()int24
curveOf(address)address
curveSupplyWhole()uint256
graduationTarget()uint256
graduationTick()int24
hook()address
launcherDeployer()address
platformVault()address
poolManager()address
positionManager()address
supplyWhole()uint256
tickLower()int24
tickUpper()int24
tokenDeployer()address
tokens(uint256)address
tokensCount()uint256
universalRouter()address
usdg()address

Events (1)

Launched

ABI

[
  {
    "inputs": [
      {
        "internalType": "address",
        "name": "usdg_",
        "type": "address"
      },
      {
        "internalType": "address",
        "name": "poolManager_",
        "type": "address"
      },
      {
        "internalType": "address",
        "name": "hook_",
        "type": "address"
      },
      {
        "internalType": "address",
        "name": "positionManager_",
        "type": "address"
      },
      {
        "internalType": "address",
        "name": "universalRouter_",
        "type": "address"
      },
      {
        "internalType": "address",
        "name": "tokenDeployer_",
        "type": "address"
      },
      {
        "internalType": "address",
        "name": "launcherDeployer_",
        "type": "address"
      },
      {
        "internalType": "address",
        "name": "platformVault_",
        "type": "address"
      },
      {
        "internalType": "uint256",
        "name": "supplyWhole_",
        "type": "uint256"
      },
      {
        "internalType": "uint256",
        "name": "curveSupplyWhole_",
        "type": "uint256"
      },
      {
        "internalType": "uint256",
        "name": "graduationTarget_",
        "type": "uint256"
      },
      {
        "internalType": "int24",
        "name": "tickLower_",
        "type": "int24"
      },
      {
        "internalType": "int24",
        "name": "tickUpper_",
        "type": "int24"
      },
      {
        "internalType": "int24",
        "name": "graduationTick_",
        "type": "int24"
      }
    ],
    "stateMutability": "nonpayable",
    "type": "constructor"
  },
  {
    "anonymous": false,
    "inputs": [
      {
        "indexed": true,
        "internalType": "address",
        "name": "token",
        "type": "address"
      },
      {
        "indexed": true,
        "internalType": "address",
        "name": "curve",
        "type": "address"
      },
      {
        "indexed": true,
        "internalType": "address",
        "name": "creator",
        "type": "address"
      },
      {
        "indexed": false,
        "internalType": "string",
        "name": "name",
        "type": "string"
      },
      {
        "indexed": false,
        "internalType": "string",
        "name": "symbol",
        "type": "string"
      },
      {
        "indexed": false,
        "internalType": "uint16",
        "name": "feeBps",
        "type": "uint16"
      },
      {
        "indexed": false,
        "internalType": "uint16[5]",
        "name": "split",
        "type": "uint16[5]"
      },
      {
        "indexed": false,
        "internalType": "string",
        "name": "image",
        "type": "string"
      }
    ],
    "name": "Launched",
    "type": "event"
  },
  {
    "inputs": [],
    "name": "LP_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": [
      {
        "internalType": "address",
        "name": "",
        "type": "address"
      }
    ],
    "name": "curveOf",
    "outputs": [
      {
        "internalType": "address",
        "name": "",
        "type": "address"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "curveSupplyWhole",
    "outputs": [
      {
        "internalType": "uint256",
        "name": "",
        "type": "uint256"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "graduationTarget",
    "outputs": [
      {
        "internalType": "uint256",
        "name": "",
        "type": "uint256"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "graduationTick",
    "outputs": [
      {
        "internalType": "int24",
        "name": "",
        "type": "int24"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "hook",
    "outputs": [
      {
        "internalType": "address",
        "name": "",
        "type": "address"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "string",
        "name": "name",
        "type": "string"
      },
      {
        "internalType": "string",
        "name": "symbol",
        "type": "string"
      },
      {
        "internalType": "uint16",
        "name": "feeBps",
        "type": "uint16"
      },
      {
        "internalType": "uint16[5]",
        "name": "split",
        "type": "uint16[5]"
      },
      {
        "internalType": "string",
        "name": "image",
        "type": "string"
      }
    ],
    "name": "launch",
    "outputs": [
      {
        "internalType": "address",
        "name": "token",
        "type": "address"
      },
      {
        "internalType": "address",
        "name": "launcher",
        "type": "address"
      }
    ],
    "stateMutability": "nonpayable",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "launcherDeployer",
    "outputs": [
      {
        "internalType": "address",
        "name": "",
        "type": "address"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "platformVault",
    "outputs": [
      {
        "internalType": "address",
        "name": "",
        "type": "address"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "poolManager",
    "outputs": [
      {
        "internalType": "address",
        "name": "",
        "type": "address"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "positionManager",
    "outputs": [
      {
        "internalType": "address",
        "name": "",
        "type": "address"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "supplyWhole",
    "outputs": [
      {
        "internalType": "uint256",
        "name": "",
        "type": "uint256"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "tickLower",
    "outputs": [
      {
        "internalType": "int24",
        "name": "",
        "type": "int24"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "tickUpper",
    "outputs": [
      {
        "internalType": "int24",
        "name": "",
        "type": "int24"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "tokenDeployer",
    "outputs": [
      {
        "internalType": "address",
        "name": "",
        "type": "address"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "uint256",
        "name": "",
        "type": "uint256"
      }
    ],
    "name": "tokens",
    "outputs": [
      {
        "internalType": "address",
        "name": "",
        "type": "address"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "tokensCount",
    "outputs": [
      {
        "internalType": "uint256",
        "name": "",
        "type": "uint256"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "universalRouter",
    "outputs": [
      {
        "internalType": "address",
        "name": "",
        "type": "address"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "usdg",
    "outputs": [
      {
        "internalType": "address",
        "name": "",
        "type": "address"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  }
]

Source code

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

/* ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
    FLOW — FlowFactoryC (v3 launchpad)  ⚠️ WIP, NOT AUDITED

    USDG-quoted launches on the v3 stack (FlowTokenV3 + FlowHookV3 + LaunchPoolV4c). The creator picks
    their tax (feeBps, 0.5–10%) AND how the LAUNCHER portion of every trade splits across 5 buckets:

        split = [holder, lp, treasury, buyback, ref]  (bps, sum 10000, holder ≥ 50%)

    The platform cut is taken by the hook at the platform tier (min(tax/2, cap)); ~20% of it funds the FLOW
    burn pot, the rest the platform wallet. The token address is mined ABOVE USDG so USDG is currency0.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ */

import {IHooks} from "@uniswap/v4-core/src/interfaces/IHooks.sol";
import {PoolKey} from "@uniswap/v4-core/src/types/PoolKey.sol";
import {Currency} from "@uniswap/v4-core/src/types/Currency.sol";

interface IFlowHookV3Register {
    function register(PoolKey calldata key, address token, uint16 feeBps, address initializer, address treasury, uint16[5] calldata split) external;
}
interface ITokenDeployerV3 {
    function deploy(string calldata name, string calldata symbol, address treasury, uint256 supplyWhole,
        address poolManager, address positionManager, address universalRouter, address to, uint256 saltSeed) external returns (address);
}
interface ILauncherDeployerC {
    function deploy(address token, address usdg, address poolManager, address hook,
        uint256 curveSupplyWei, uint256 gradReserveWei, uint256 graduationTarget,
        int24 tickLower, int24 tickUpper, int24 graduationTick,
        uint256 feeBps, address platformVault, address to) external returns (address);
}
interface ITokenAdmin {
    function setCurve(address) external;
    function setHook(address) external;
    function transfer(address, uint256) external returns (bool);
    function transferOwnership(address) external;
}
interface ILauncherAdmin {
    function open() external;
    function transferOwnership(address) external;
}

contract FlowFactoryC {
    uint24 public constant LP_FEE = 3000;
    int24 public constant TICK_SPACING = 60;
    // No per-bucket minimum: a launcher is free to send 0% to holders (not every token is a reward token —
    // some are plain "buy what you see" coins that route the tax to lp/treasury/buyback instead). The split
    // is fully the creator's choice; it's transparent on-chain and shown on the launch UI. Only the sum is fixed.

    address public immutable usdg;
    address public immutable poolManager;
    address public immutable hook;              // FlowHookV3
    address public immutable positionManager;
    address public immutable universalRouter;
    address public immutable tokenDeployer;
    address public immutable launcherDeployer;
    address public immutable platformVault;     // 0 in v3 (no supply cut; platform earns via the hook)

    uint256 public immutable supplyWhole;
    uint256 public immutable curveSupplyWhole;
    uint256 public immutable graduationTarget;  // USDG (informational)
    int24 public immutable tickLower;
    int24 public immutable tickUpper;
    int24 public immutable graduationTick;

    address[] public tokens;
    mapping(address => address) public curveOf;

    event Launched(
        address indexed token, address indexed curve, address indexed creator,
        string name, string symbol, uint16 feeBps, uint16[5] split, string image
    );

    constructor(
        address usdg_, address poolManager_, address hook_,
        address positionManager_, address universalRouter_,
        address tokenDeployer_, address launcherDeployer_, address platformVault_,
        uint256 supplyWhole_, uint256 curveSupplyWhole_, uint256 graduationTarget_,
        int24 tickLower_, int24 tickUpper_, int24 graduationTick_
    ) {
        require(usdg_ != address(0) && poolManager_ != address(0) && hook_ != address(0), "zero");
        require(tokenDeployer_ != address(0) && launcherDeployer_ != address(0), "zero");
        require(supplyWhole_ > 0 && curveSupplyWhole_ > 0 && curveSupplyWhole_ < supplyWhole_, "supply");
        require(graduationTarget_ > 0, "params");
        require(tickLower_ < graduationTick_ && graduationTick_ < tickUpper_, "ticks");
        require(tickLower_ % TICK_SPACING == 0 && tickUpper_ % TICK_SPACING == 0 && graduationTick_ % TICK_SPACING == 0, "align");
        usdg = usdg_; poolManager = poolManager_; hook = hook_;
        positionManager = positionManager_; universalRouter = universalRouter_;
        tokenDeployer = tokenDeployer_; launcherDeployer = launcherDeployer_; platformVault = platformVault_;
        supplyWhole = supplyWhole_; curveSupplyWhole = curveSupplyWhole_; graduationTarget = graduationTarget_;
        tickLower = tickLower_; tickUpper = tickUpper_; graduationTick = graduationTick_;
    }

    /// Launch a v3 basket-token. `split` = [holder, lp, treasury, buyback, ref] bps (sum 10000, holder ≥ 5000).
    /// The caller is the treasury + final owner of both the token and the launcher.
    function launch(string calldata name, string calldata symbol, uint16 feeBps, uint16[5] calldata split, string calldata image)
        external
        returns (address token, address launcher)
    {
        require(feeBps >= 50 && feeBps <= 1_000, "fee 0.5-10%");
        require(uint256(split[0]) + split[1] + split[2] + split[3] + split[4] == 10_000, "split sum");

        uint256 supplyWei = supplyWhole * 1e18;
        uint256 curveSupplyWei = curveSupplyWhole * 1e18;
        uint256 gradReserveWei = supplyWei - curveSupplyWei;

        token = ITokenDeployerV3(tokenDeployer).deploy(
            name, symbol, msg.sender, supplyWhole, poolManager, positionManager, universalRouter, address(this), tokens.length
        );
        launcher = ILauncherDeployerC(launcherDeployer).deploy(
            token, usdg, poolManager, hook, curveSupplyWei, gradReserveWei, graduationTarget,
            tickLower, tickUpper, graduationTick, uint256(feeBps), platformVault, address(this)
        );

        IFlowHookV3Register(hook).register(_poolKey(token), token, feeBps, launcher, msg.sender, split);

        ITokenAdmin(token).setCurve(launcher);
        ITokenAdmin(token).setHook(hook);
        ITokenAdmin(token).transfer(launcher, supplyWei);
        ILauncherAdmin(launcher).open();

        ITokenAdmin(token).transferOwnership(msg.sender);
        ILauncherAdmin(launcher).transferOwnership(msg.sender);

        tokens.push(token);
        curveOf[token] = launcher;
        emit Launched(token, launcher, msg.sender, name, symbol, feeBps, split, image);
    }

    function tokensCount() external view returns (uint256) { return tokens.length; }

    function _poolKey(address token_) internal view returns (PoolKey memory) {
        return PoolKey({
            currency0: Currency.wrap(usdg),
            currency1: Currency.wrap(token_),
            fee: LP_FEE,
            tickSpacing: TICK_SPACING,
            hooks: IHooks(hook)
        });
    }
}
Chain explorer3446msChain node76ms