{"language":"Solidity","sources":{"contracts/NasdaqLaunchFactory.sol":{"content":"// SPDX-License-Identifier: MIT\r\npragma solidity ^0.8.24;\r\n\r\ncontract NasdaqCommunityToken {\r\n    string public name;\r\n    string public symbol;\r\n    string public referenceTicker;\r\n    string public website;\r\n    string public twitter;\r\n    string public telegram;\r\n    uint8 public constant decimals = 18;\r\n    uint16 public constant sellFeeBps = 100;\r\n    uint256 public immutable totalSupply;\r\n    uint256 public immutable tokensPerBNB;\r\n    address public immutable creator;\r\n    uint256 public creatorFees;\r\n    bool private entered;\r\n\r\n    mapping(address => uint256) public balanceOf;\r\n    mapping(address => mapping(address => uint256)) public allowance;\r\n\r\n    event Transfer(address indexed from, address indexed to, uint256 value);\r\n    event Approval(address indexed owner, address indexed spender, uint256 value);\r\n    event Bought(address indexed account, uint256 bnbIn, uint256 tokensOut);\r\n    event Sold(address indexed account, uint256 tokensIn, uint256 bnbOut, uint256 fee);\r\n    event FeesClaimed(address indexed creator, uint256 amount);\r\n\r\n    error InvalidConfiguration();\r\n    error InsufficientBalance();\r\n    error InsufficientAllowance();\r\n    error Slippage();\r\n    error SoldOut();\r\n    error InsufficientReserve();\r\n    error CreatorOnly();\r\n    error TransferFailed();\r\n    error ReentrantCall();\r\n\r\n    modifier nonReentrant() { if (entered) revert ReentrantCall(); entered = true; _; entered = false; }\r\n\r\n    constructor(string memory tokenName, string memory tokenSymbol, string memory ticker, string memory site, string memory x, string memory tg, uint256 supplyTokens, uint256 rate, address tokenCreator) {\r\n        if (block.chainid != 56 || bytes(tokenName).length < 3 || bytes(tokenName).length > 40 || bytes(tokenSymbol).length < 2 || bytes(tokenSymbol).length > 9 || supplyTokens < 1_000 || supplyTokens > 1_000_000_000 || rate == 0 || rate > 1_000_000_000 || tokenCreator == address(0)) revert InvalidConfiguration();\r\n        name = tokenName; symbol = tokenSymbol; referenceTicker = ticker; website = site; twitter = x; telegram = tg;\r\n        totalSupply = supplyTokens * 1 ether;\r\n        tokensPerBNB = rate;\r\n        creator = tokenCreator;\r\n        balanceOf[address(this)] = totalSupply;\r\n        emit Transfer(address(0), address(this), totalSupply);\r\n    }\r\n\r\n    function buy(uint256 minTokensOut) external payable nonReentrant returns (uint256 tokensOut) {\r\n        if (msg.value == 0) revert InvalidConfiguration();\r\n        tokensOut = msg.value * tokensPerBNB;\r\n        if (tokensOut < minTokensOut) revert Slippage();\r\n        if (balanceOf[address(this)] < tokensOut) revert SoldOut();\r\n        _transfer(address(this), msg.sender, tokensOut);\r\n        emit Bought(msg.sender, msg.value, tokensOut);\r\n    }\r\n\r\n    function sell(uint256 tokenAmount, uint256 minBnbOut) external nonReentrant returns (uint256 bnbOut) {\r\n        if (tokenAmount == 0) revert InvalidConfiguration();\r\n        uint256 gross = tokenAmount / tokensPerBNB;\r\n        uint256 fee = gross * sellFeeBps / 10_000;\r\n        bnbOut = gross - fee;\r\n        if (bnbOut < minBnbOut) revert Slippage();\r\n        if (address(this).balance < gross) revert InsufficientReserve();\r\n        _transfer(msg.sender, address(this), tokenAmount);\r\n        creatorFees += fee;\r\n        (bool sent,) = payable(msg.sender).call{value: bnbOut}(\"\");\r\n        if (!sent) revert TransferFailed();\r\n        emit Sold(msg.sender, tokenAmount, bnbOut, fee);\r\n    }\r\n\r\n    function claimFees() external nonReentrant {\r\n        if (msg.sender != creator) revert CreatorOnly();\r\n        uint256 amount = creatorFees;\r\n        creatorFees = 0;\r\n        (bool sent,) = payable(creator).call{value: amount}(\"\");\r\n        if (!sent) revert TransferFailed();\r\n        emit FeesClaimed(creator, amount);\r\n    }\r\n\r\n    function quoteBuy(uint256 bnbIn) external view returns (uint256) { return bnbIn * tokensPerBNB; }\r\n    function quoteSell(uint256 tokenAmount) external view returns (uint256) { uint256 gross = tokenAmount / tokensPerBNB; return gross - (gross * sellFeeBps / 10_000); }\r\n    function reserveBNB() external view returns (uint256) { return address(this).balance - creatorFees; }\r\n    function circulatingSupply() external view returns (uint256) { return totalSupply - balanceOf[address(this)]; }\r\n\r\n    function transfer(address to, uint256 amount) external returns (bool) { _transfer(msg.sender, to, amount); return true; }\r\n    function approve(address spender, uint256 amount) external returns (bool) { allowance[msg.sender][spender] = amount; emit Approval(msg.sender, spender, amount); return true; }\r\n    function transferFrom(address from, address to, uint256 amount) external returns (bool) {\r\n        uint256 available = allowance[from][msg.sender];\r\n        if (available != type(uint256).max) {\r\n            if (available < amount) revert InsufficientAllowance();\r\n            unchecked { allowance[from][msg.sender] = available - amount; }\r\n            emit Approval(from, msg.sender, allowance[from][msg.sender]);\r\n        }\r\n        _transfer(from, to, amount); return true;\r\n    }\r\n    function _transfer(address from, address to, uint256 amount) private {\r\n        if (to == address(0)) revert InvalidConfiguration();\r\n        uint256 balance = balanceOf[from];\r\n        if (balance < amount) revert InsufficientBalance();\r\n        unchecked { balanceOf[from] = balance - amount; balanceOf[to] += amount; }\r\n        emit Transfer(from, to, amount);\r\n    }\r\n}\r\n\r\ncontract NasdaqLaunchFactory {\r\n    mapping(bytes32 => address) public marketFor;\r\n    address[] public allMarkets;\r\n\r\n    event MarketCreated(bytes32 indexed key, address indexed market, address indexed creator, string referenceTicker, string symbol, uint256 supplyTokens, uint256 tokensPerBNB);\r\n    error InvalidConfiguration();\r\n    error SymbolTaken();\r\n\r\n    constructor() { if (block.chainid != 56) revert InvalidConfiguration(); }\r\n\r\n    function createMarket(string calldata tokenName, string calldata tokenSymbol, string calldata referenceTicker, string calldata website, string calldata twitter, string calldata telegram, uint256 supplyTokens, uint256 tokensPerBNB) external returns (address market) {\r\n        _validateSymbol(bytes(tokenSymbol));\r\n        _validateTicker(bytes(referenceTicker));\r\n        bytes32 key = keccak256(bytes(tokenSymbol));\r\n        if (marketFor[key] != address(0)) revert SymbolTaken();\r\n        market = address(new NasdaqCommunityToken{salt: key}(tokenName, tokenSymbol, referenceTicker, website, twitter, telegram, supplyTokens, tokensPerBNB, msg.sender));\r\n        marketFor[key] = market;\r\n        allMarkets.push(market);\r\n        emit MarketCreated(key, market, msg.sender, referenceTicker, tokenSymbol, supplyTokens, tokensPerBNB);\r\n    }\r\n\r\n    function marketsLength() external view returns (uint256) { return allMarkets.length; }\r\n    function _validateSymbol(bytes memory value) private pure {\r\n        if (value.length < 2 || value.length > 9) revert InvalidConfiguration();\r\n        for (uint256 i; i < value.length; ++i) { bytes1 c = value[i]; if (!((c >= 0x41 && c <= 0x5A) || (c >= 0x30 && c <= 0x39))) revert InvalidConfiguration(); }\r\n    }\r\n    function _validateTicker(bytes memory value) private pure {\r\n        if (value.length == 0 || value.length > 8) revert InvalidConfiguration();\r\n        for (uint256 i; i < value.length; ++i) { bytes1 c = value[i]; if (!((c >= 0x41 && c <= 0x5A) || (c >= 0x30 && c <= 0x39))) revert InvalidConfiguration(); }\r\n    }\r\n}\r\n"}},"settings":{"evmVersion":"shanghai","optimizer":{"enabled":true,"runs":1000},"viaIR":true,"outputSelection":{"*":{"*":["abi","evm.bytecode.object","evm.deployedBytecode.object"]}}}}