// SPDX-License-Identifier: MIT pragma solidity ^0.8.24; import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol"; import {MoonRushBondingCurve} from "./MoonRushBondingCurve.sol"; /// @title DegenZFunBondingCurveFactory — DegenZ Fun fair-launch bonding curve factory ($5 create → treasury). contract DegenZFunBondingCurveFactory is Ownable { address public treasury; address public router; uint256 public createFee; uint256 public graduationMarketCapEth; uint256 public treasuryGraduationFeeBps; uint256 public treasuryTradeFeeBps; MoonRushBondingCurve[] public curves; event CoinCreated( address indexed creator, address indexed curve, address indexed token, string name, string symbol, string metadataUri ); event CreateFeeUpdated(uint256 fee); event TreasuryUpdated(address indexed treasury); event RouterUpdated(address indexed router); event GraduationMarketCapUpdated(uint256 mcapEth); event TreasuryGraduationFeeUpdated(uint256 bps); event TreasuryTradeFeeUpdated(uint256 bps); constructor( address treasury_, address router_, uint256 createFee_, uint256 graduationMarketCapEth_, uint256 treasuryGraduationFeeBps_, uint256 treasuryTradeFeeBps_ ) Ownable(msg.sender) { require(treasury_ != address(0) && router_ != address(0), "zero addr"); treasury = treasury_; router = router_; createFee = createFee_; graduationMarketCapEth = graduationMarketCapEth_; treasuryGraduationFeeBps = treasuryGraduationFeeBps_; treasuryTradeFeeBps = treasuryTradeFeeBps_; } function createCoin( string calldata name_, string calldata symbol_, string calldata metadataUri_ ) external payable returns (address curveAddr, address tokenAddr) { require(msg.value >= createFee, "fee too low"); require(bytes(name_).length > 0 && bytes(symbol_).length > 0, "name/symbol"); (bool feeOk,) = treasury.call{value: createFee}(""); require(feeOk, "fee transfer failed"); // Refund excess ETH if (msg.value > createFee) { (bool refundOk,) = msg.sender.call{value: msg.value - createFee}(""); require(refundOk, "refund failed"); } MoonRushBondingCurve curve = new MoonRushBondingCurve( name_, symbol_, metadataUri_, msg.sender, router, treasury, graduationMarketCapEth, treasuryGraduationFeeBps, treasuryTradeFeeBps ); curveAddr = address(curve); tokenAddr = address(curve.token()); curves.push(curve); emit CoinCreated(msg.sender, curveAddr, tokenAddr, name_, symbol_, metadataUri_); } function curveCount() external view returns (uint256) { return curves.length; } function setCreateFee(uint256 fee) external onlyOwner { createFee = fee; emit CreateFeeUpdated(fee); } function setTreasury(address t) external onlyOwner { require(t != address(0), "treasury=0"); treasury = t; emit TreasuryUpdated(t); } function setRouter(address r) external onlyOwner { require(r != address(0), "router=0"); router = r; emit RouterUpdated(r); } function setGraduationMarketCapEth(uint256 mcap) external onlyOwner { require(mcap > 0, "mcap=0"); graduationMarketCapEth = mcap; emit GraduationMarketCapUpdated(mcap); } function setTreasuryGraduationFeeBps(uint256 bps) external onlyOwner { require(bps <= 2000, "too high"); treasuryGraduationFeeBps = bps; emit TreasuryGraduationFeeUpdated(bps); } function setTreasuryTradeFeeBps(uint256 bps) external onlyOwner { require(bps <= 1000, "too high"); treasuryTradeFeeBps = bps; emit TreasuryTradeFeeUpdated(bps); } }