TokenFactory

Description:

Multi-signature wallet contract requiring multiple confirmations for transaction execution.

Blockchain: Ethereum

Source Code: View Code On The Blockchain

Solidity Source Code:

{{
  "language": "Solidity",
  "sources": {
    "laxwin contracts/TokenFactory.sol": {
      "content": "// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
import "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/utils/ReentrancyGuardUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/utils/PausableUpgradeable.sol";

import "./ILaxcePadInterfaces.sol";
import "./LaxcePadToken.sol";
import "./ValidationLibrary.sol";

contract TokenFactory is
    Initializable,
    ReentrancyGuardUpgradeable,
    UUPSUpgradeable,
    AccessControlUpgradeable,
    PausableUpgradeable,
    ITokenFactory,
    IDEXIntegration
{

    bytes32 public constant ADMIN_ROLE = keccak256("ADMIN_ROLE");
    bytes32 public constant OPERATOR_ROLE = keccak256("OPERATOR_ROLE");
    bytes32 public constant UPGRADER_ROLE = keccak256("UPGRADER_ROLE");

    uint256 public constant MIN_CREATION_FEE = 0;
    uint256 public constant MAX_CREATION_FEE = 1 ether;

    address public tokenRegistry;
    address public poolFactory;
    address public dexEngine;
    address public coreRegistry;
    address public bondingCurve;

    struct FactorySettings {
        uint256 creationFee;
        uint256 defaultMaxSupply;
        address feeRecipient;
        bool requireApproval;
        uint256 minCreationDelay;
    }

    FactorySettings public factorySettings;
    ITokenFactory.SupplyLimits public supplyLimits;

    mapping(address => ITokenFactory.TokenParams) public tokenInfo;

    mapping(address => address[]) public creatorTokens;

    address[] public allTokens;

    mapping(string => address) public symbolToToken;

    mapping(address => uint256) public creatorLastCreation;
    mapping(address => uint256) public creatorTokenCount;

    mapping(address => bool) public creatorWhitelist;
    mapping(address => bool) public creatorBlacklist;

    struct FactoryStats {
        uint256 totalTokens;
        uint256 totalCreators;
        uint256 totalFeesCollected;
        uint256 averageCreationFee;
    }

    FactoryStats public factoryStats;

    event TokenCreated(
        address indexed token,
        address indexed creator,
        string name,
        string symbol,
        uint256 maxSupply,
        uint256 creationFee
    );

    event FactorySettingsUpdated(FactorySettings settings);

    event DEXIntegrationUpdated(
        address tokenRegistry,
        address poolFactory,
        address dexEngine,
        address coreRegistry
    );

    event CreatorWhitelisted(address indexed creator, bool whitelisted);
    event CreatorBlacklisted(address indexed creator, bool blacklisted);

    error InvalidParams();
    error InsufficientFee();
    error SymbolExists();
    error Blacklisted();
    error DelayNotMet();
    error InvalidAddr();
    error NotFound();
    error NotAuth();
    error InvalidLen();

    function initialize(
        address _admin,
        FactorySettings memory _settings,
        address _coreRegistry
    ) external initializer {
        _initializeContracts();
        _setupAdmin(_admin);
        _configureSettings(_settings, _coreRegistry);
        _setDefaultLimits();
    }

    function _setDefaultLimits() internal {
        supplyLimits = ITokenFactory.SupplyLimits({
            minTotalSupply: 1000000 * 1e18,
            maxTotalSupply: 1000000000000 * 1e18,
            minBondingCurvePercent: 1000,
            maxBondingCurvePercent: 9000,
            minStartPrice: 1e12,
            maxStartPrice: 1e17,
            minTargetMarketCap: 10 ether,
            maxTargetMarketCap: 1000 ether
        });
    }

    function _initializeContracts() internal {
        __ReentrancyGuard_init();
        __UUPSUpgradeable_init();
        __AccessControl_init();
        __Pausable_init();
    }

    function _setupAdmin(address _admin) internal {
        if (_admin == address(0)) {
            revert InvalidAddr();
        }

        _grantRole(DEFAULT_ADMIN_ROLE, _admin);
        _grantRole(ADMIN_ROLE, _admin);
        _grantRole(OPERATOR_ROLE, _admin);
        _grantRole(UPGRADER_ROLE, _admin);
    }

    function _configureSettings(FactorySettings memory _settings, address _coreRegistry) internal {
        factorySettings = _settings;
        coreRegistry = _coreRegistry;
    }

    function _updateFactoryStats(uint256 feeAmount, bool isFirstToken) internal {
        factoryStats.totalTokens++;
        if (isFirstToken) {
            factoryStats.totalCreators++;
        }
        factoryStats.totalFeesCollected += feeAmount;
        factoryStats.averageCreationFee = factoryStats.totalFeesCollected / factoryStats.totalTokens;
    }

    function _initializeToken(address token, ITokenFactory.TokenParams calldata params) internal {
        uint256 maxSupply = params.totalSupply > 0 ? params.totalSupply : factorySettings.defaultMaxSupply;
        _initializeTokenWithParams(token, params, maxSupply);
    }

    function _initializeTokenWithParams(address token, ITokenFactory.TokenParams calldata params, uint256 maxSupply) internal {
        _tempTokenData.token = token;
        _tempTokenData.maxSupply = maxSupply;
        _tempTokenData.creator = msg.sender;
        _tempTokenData.factory = address(this);
        
        _performTokenInitialization(params);
    }

    struct TempTokenData {
        address token;
        uint256 maxSupply;
        address creator;
        address factory;
    }
    
    TempTokenData private _tempTokenData;

    string[] private _tempSocialLinks;
    string private _tempName;
    string private _tempSymbol;
    string private _tempDescription;
    string private _tempImageUrl;

    function _performTokenInitialization(ITokenFactory.TokenParams calldata params) internal {
        _storeTokenParams(params);
        _callTokenInitialize();
        _clearTempData();
    }

    function _storeTokenParams(ITokenFactory.TokenParams calldata params) internal {
        _tempName = params.name;
        _tempSymbol = params.symbol;
        _tempDescription = params.description;
        _tempImageUrl = params.imageUrl;
        
        delete _tempSocialLinks;
        for (uint256 i = 0; i < params.socialLinks.length; i++) {
            _tempSocialLinks.push(params.socialLinks[i]);
        }
    }

    function _callTokenInitialize() internal {
        LaxcePadToken(_tempTokenData.token).initialize(
            _tempName,
            _tempSymbol,
            _tempDescription,
            _tempImageUrl,
            _tempSocialLinks,
            _tempTokenData.maxSupply,
            _tempTokenData.creator,
            _tempTokenData.factory
        );
    }

    function _clearTempData() internal {
        delete _tempTokenData;
        delete _tempSocialLinks;
        delete _tempName;
        delete _tempSymbol;
        delete _tempDescription;
        delete _tempImageUrl;
    }

    function _registerToken(address token, ITokenFactory.TokenParams calldata params) internal {
        tokenInfo[token] = params;
        creatorTokens[msg.sender].push(token);
        allTokens.push(token);
        symbolToToken[params.symbol] = token;
    }

    function _updateStats() internal {
        creatorLastCreation[msg.sender] = block.timestamp;
        creatorTokenCount[msg.sender]++;
        bool isFirstToken = (creatorTokenCount[msg.sender] == 1);
        _updateFactoryStats(msg.value, isFirstToken);
    }

    mapping(address => address) private pendingTokens;

    function createToken(
        ITokenFactory.TokenParams calldata params
    ) external payable nonReentrant whenNotPaused returns (address token) {
        _performAllValidations(params);
        token = _deployAndSetupToken(params);
        return token;
    }

    function _performAllValidations(ITokenFactory.TokenParams calldata params) internal view {
        if (creatorBlacklist[msg.sender]) revert Blacklisted();
        if (factorySettings.requireApproval && !creatorWhitelist[msg.sender] && !hasRole(ADMIN_ROLE, msg.sender)) {
            revert NotAuth();
        }
        
        if (block.timestamp < creatorLastCreation[msg.sender] + factorySettings.minCreationDelay) {
            revert DelayNotMet();
        }
        
        _validateTokenParams(params);
        _validateCreationRequirements(params);
    }

    function _validateCreationRequirements(ITokenFactory.TokenParams calldata params) internal view {
        if (msg.value < factorySettings.creationFee) revert InsufficientFee();
        if (symbolToToken[params.symbol] != address(0)) revert SymbolExists();
    }

    function _deployAndSetupToken(ITokenFactory.TokenParams calldata params) internal returns (address token) {
        LaxcePadToken newToken = new LaxcePadToken();
        token = address(newToken);
        
        pendingTokens[msg.sender] = token;
        _initializeToken(token, params);
        _registerToken(token, params);
        _completeTokenFinalization(token, params);
        delete pendingTokens[msg.sender];
    }

    function _completeTokenFinalization(address token, ITokenFactory.TokenParams calldata params) internal {
        _updateStats();
        
        if (bondingCurve != address(0)) {
            _initializeBondingCurve(token, params);
        }
        
        if (msg.value > 0 && factorySettings.feeRecipient != address(0)) {
            payable(factorySettings.feeRecipient).transfer(msg.value);
        }
        
        emit TokenCreated(token, msg.sender, params.name, params.symbol, params.totalSupply, msg.value);
    }

    function _validateTokenParams(ITokenFactory.TokenParams calldata params) internal view {
        ValidationLibrary.validateTokenParams(params);
        
        if (params.totalSupply < supplyLimits.minTotalSupply || 
            params.totalSupply > supplyLimits.maxTotalSupply) {
            revert InvalidParams();
        }
        
        if (params.bondingCurveSupply > 0) {
            uint256 bondingCurvePercent = (params.bondingCurveSupply * 10000) / params.totalSupply;
            if (bondingCurvePercent < supplyLimits.minBondingCurvePercent || 
                bondingCurvePercent > supplyLimits.maxBondingCurvePercent) {
                revert InvalidParams();
            }
        }
        
        if (params.startPrice > 0) {
            if (params.startPrice < supplyLimits.minStartPrice || 
                params.startPrice > supplyLimits.maxStartPrice) {
                revert InvalidParams();
            }
        }
        
        if (params.targetMarketCap > 0) {
            if (params.targetMarketCap < supplyLimits.minTargetMarketCap || 
                params.targetMarketCap > supplyLimits.maxTargetMarketCap) {
                revert InvalidParams();
            }
        }
    }

    function _initializeBondingCurve(address token, ITokenFactory.TokenParams calldata params) internal {
        if (bondingCurve == address(0)) return;
        if (params.bondingCurveSupply == 0) return;
        
        uint256 startPrice = params.startPrice > 0 
            ? params.startPrice 
            : supplyLimits.minStartPrice * 10;
            
        uint256 targetMarketCap = params.targetMarketCap > 0 
            ? params.targetMarketCap 
            : 85 ether;
        
        IBondingCurve(bondingCurve).initializeCurve(
            token,
            params.bondingCurveSupply,
            startPrice,
            targetMarketCap
        );
    }

    function getTokenInfo(address token) external view returns (ITokenFactory.TokenParams memory) {
        if (tokenInfo[token].totalSupply == 0) revert NotFound();
        return tokenInfo[token];
    }

    function isTokenCreated(address token) external view returns (bool) {
        return tokenInfo[token].totalSupply > 0;
    }

    function getSupplyLimits() external view returns (ITokenFactory.SupplyLimits memory) {
        return supplyLimits;
    }

    function getTokenRegistry() external view returns (address) {
        return tokenRegistry;
    }

    function getPoolFactory() external view returns (address) {
        return poolFactory;
    }

    function getDEXEngine() external view returns (address) {
        return dexEngine;
    }

    function getCoreRegistry() external view returns (address) {
        return coreRegistry;
    }

    function updateFactorySettings(FactorySettings calldata settings) external onlyRole(ADMIN_ROLE) {
        if (settings.creationFee > MAX_CREATION_FEE) {
            revert InvalidParams();
        }
        if (settings.feeRecipient == address(0)) revert InvalidAddr();

        factorySettings = settings;
        emit FactorySettingsUpdated(settings);
    }

    function updateCreationFee(uint256 newFee) external onlyRole(ADMIN_ROLE) {
        if (newFee > MAX_CREATION_FEE) {
            revert InvalidParams();
        }
        factorySettings.creationFee = newFee;
        emit FactorySettingsUpdated(factorySettings);
    }

    function updateSupplyLimits(ITokenFactory.SupplyLimits calldata newLimits) external onlyRole(ADMIN_ROLE) {
        if (newLimits.minTotalSupply == 0 || newLimits.maxTotalSupply == 0) {
            revert InvalidParams();
        }
        if (newLimits.minTotalSupply > newLimits.maxTotalSupply) {
            revert InvalidParams();
        }
        if (newLimits.minBondingCurvePercent > newLimits.maxBondingCurvePercent) {
            revert InvalidParams();
        }
        if (newLimits.minStartPrice > newLimits.maxStartPrice) {
            revert InvalidParams();
        }
        if (newLimits.minTargetMarketCap > newLimits.maxTargetMarketCap) {
            revert InvalidParams();
        }
        
        supplyLimits = newLimits;
        emit SupplyLimitsUpdated(newLimits);
    }

    event SupplyLimitsUpdated(ITokenFactory.SupplyLimits limits);

    function updateDEXIntegration(
        address _tokenRegistry,
        address _poolFactory,
        address _dexEngine,
        address _bondingCurve
    ) external onlyRole(ADMIN_ROLE) {
        _setDEXAddresses(_tokenRegistry, _poolFactory, _dexEngine, _bondingCurve);
        emit DEXIntegrationUpdated(_tokenRegistry, _poolFactory, _dexEngine, coreRegistry);
    }

    function _setDEXAddresses(
        address _tokenRegistry,
        address _poolFactory,
        address _dexEngine,
        address _bondingCurve
    ) internal {
        tokenRegistry = _tokenRegistry;
        poolFactory = _poolFactory;
        dexEngine = _dexEngine;
        bondingCurve = _bondingCurve;
    }

    function setCreatorWhitelist(address creator, bool whitelisted) external onlyRole(ADMIN_ROLE) {
        creatorWhitelist[creator] = whitelisted;
        emit CreatorWhitelisted(creator, whitelisted);
    }

    function setCreatorBlacklist(address creator, bool blacklisted) external onlyRole(ADMIN_ROLE) {
        creatorBlacklist[creator] = blacklisted;
        emit CreatorBlacklisted(creator, blacklisted);
    }

    function pause() external onlyRole(ADMIN_ROLE) {
        _pause();
    }

    function unpause() external onlyRole(ADMIN_ROLE) {
        _unpause();
    }

    function withdrawFees(address to) external onlyRole(ADMIN_ROLE) {
        if (to == address(0)) revert InvalidAddr();
        uint256 balance = address(this).balance;
        if (balance > 0) {
            payable(to).transfer(balance);
        }
    }

    function _authorizeUpgrade(address newImplementation) internal view override onlyRole(UPGRADER_ROLE) {
        newImplementation;
    }
}
"
    },
    "laxwin contracts/ValidationLibrary.sol": {
      "content": "// SPDX-License-Identifier: MIT\r
pragma solidity ^0.8.20;\r
\r
import "./ILaxcePadInterfaces.sol";\r
\r
/**\r
 * @title ValidationLibrary\r
 * @dev Library to reduce TokenFactory contract size by moving validation logic\r
 */\r
library ValidationLibrary {\r
    uint256 public constant MAX_NAME_LENGTH = 50;\r
    uint256 public constant MAX_SYMBOL_LENGTH = 10;\r
    uint256 public constant MAX_DESCRIPTION_LENGTH = 500;\r
    uint256 public constant MAX_SOCIAL_LINKS = 10;\r
\r
    error InvalidParams();\r
    error InvalidLen();\r
\r
    function validateTokenParams(ITokenFactory.TokenParams calldata params) external pure {\r
        validateStringParams(params);\r
        validateSupplyParams(params);\r
    }\r
\r
    function validateStringParams(ITokenFactory.TokenParams calldata params) public pure {\r
        validateName(params.name);\r
        validateSymbol(params.symbol);\r
        validateDescription(params.description);\r
        validateSocialLinks(params.socialLinks);\r
    }\r
\r
    function validateName(string calldata name) public pure {\r
        if (bytes(name).length == 0 || bytes(name).length > MAX_NAME_LENGTH) {\r
            revert InvalidLen();\r
        }\r
    }\r
\r
    function validateSymbol(string calldata symbol) public pure {\r
        if (bytes(symbol).length == 0 || bytes(symbol).length > MAX_SYMBOL_LENGTH) {\r
            revert InvalidLen();\r
        }\r
    }\r
\r
    function validateDescription(string calldata description) public pure {\r
        if (bytes(description).length > MAX_DESCRIPTION_LENGTH) {\r
            revert InvalidLen();\r
        }\r
    }\r
\r
    function validateSocialLinks(string[] calldata socialLinks) public pure {\r
        if (socialLinks.length > MAX_SOCIAL_LINKS) {\r
            revert InvalidParams();\r
        }\r
    }\r
\r
    function validateSupplyParams(ITokenFactory.TokenParams calldata params) public pure {\r
        validateTotalSupply(params.totalSupply);\r
        validateSupplyDistribution(params.totalSupply, params.bondingCurveSupply, params.liquiditySupply);\r
    }\r
\r
    function validateTotalSupply(uint256 totalSupply) public pure {\r
        if (totalSupply == 0) {\r
            revert InvalidParams();\r
        }\r
    }\r
\r
    function validateSupplyDistribution(\r
        uint256 totalSupply,\r
        uint256 bondingCurveSupply,\r
        uint256 liquiditySupply\r
    ) public pure {\r
        if (bondingCurveSupply > totalSupply) {\r
            revert InvalidParams();\r
        }\r
        if (liquiditySupply > totalSupply) {\r
            revert InvalidParams();\r
        }\r
        if (bondingCurveSupply + liquiditySupply > totalSupply) {\r
            revert InvalidParams();\r
        }\r
    }\r
\r
    function stringContains(string memory str, string memory substr) external pure returns (bool) {\r
        bytes memory strBytes = bytes(str);\r
        bytes memory substrBytes = bytes(substr);\r
\r
        if (substrBytes.length > strBytes.length) return false;\r
        if (substrBytes.length == 0) return true;\r
\r
        for (uint256 i = 0; i <= strBytes.length - substrBytes.length; i++) {\r
            bool found = true;\r
            for (uint256 j = 0; j < substrBytes.length; j++) {\r
                if (strBytes[i + j] != substrBytes[j]) {\r
                    found = false;\r
                    break;\r
                }\r
            }\r
            if (found) return true;\r
        }\r
\r
        return false;\r
    }\r
}\r
"
    },
    "laxwin contracts/LaxcePadToken.sol": {
      "content": "// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
import "./ILaxcePadInterfaces.sol";

contract LaxcePadToken is ERC20, Ownable, ILaxcePadToken {
    string private _name;
    string private _symbol;

    string private _description;
    string private _imageUrl;
    string[] private _socialLinks;

    address public creator;
    uint256 public createdAt;

    mapping(address => bool) public authorizedMinters;
    mapping(address => bool) public authorizedBurners;

    uint256 public maxSupply;
    bool public mintingFinished;

    event MetadataUpdated(string description, string imageUrl);
    event SocialLinksUpdated(string[] socialLinks);
    event AuthorizedMinterAdded(address indexed minter);
    event AuthorizedMinterRemoved(address indexed minter);
    event AuthorizedBurnerAdded(address indexed burner);
    event AuthorizedBurnerRemoved(address indexed burner);
    event MintingFinished();

    error Token__NotAuthorized();
    error Token__ExceedsMaxSupply();
    error Token__MintingFinished();
    error Token__InvalidAddress();
    error Token__InvalidAmount();

    modifier onlyAuthorizedMinter() {
        if (!authorizedMinters[msg.sender] && msg.sender != owner()) {
            revert Token__NotAuthorized();
        }
        _;
    }

    modifier onlyAuthorizedBurner() {
        if (!authorizedBurners[msg.sender] && msg.sender != owner()) {
            revert Token__NotAuthorized();
        }
        _;
    }

    modifier whenMintingNotFinished() {
        if (mintingFinished) revert Token__MintingFinished();
        _;
    }

    bool private _initialized;

    constructor() ERC20("", "") Ownable(msg.sender) {
    }

    function initialize(
        string memory name,
        string memory symbol,
        string memory desc,
        string memory imgUrl,
        string[] memory socLinks,
        uint256 _maxSupply,
        address _creator,
        address _owner
    ) external {
        if (_initialized) revert Token__NotAuthorized();
        if (_creator == address(0) || _owner == address(0)) revert Token__InvalidAddress();
        if (_maxSupply == 0) revert Token__InvalidAmount();

        _initialized = true;
        
        _name = name;
        _symbol = symbol;
        
        _transferOwnership(_owner);

        _description = desc;
        _imageUrl = imgUrl;
        _socialLinks = socLinks;
        maxSupply = _maxSupply;
        creator = _creator;
        createdAt = block.timestamp;
        
        authorizedMinters[_owner] = true;
        authorizedBurners[_owner] = true;

        emit MetadataUpdated(desc, imgUrl);
        emit SocialLinksUpdated(socLinks);
    }

    function mint(address to, uint256 amount) external onlyAuthorizedMinter whenMintingNotFinished {
        if (to == address(0)) revert Token__InvalidAddress();
        if (amount == 0) revert Token__InvalidAmount();
        if (totalSupply() + amount > maxSupply) revert Token__ExceedsMaxSupply();

        _mint(to, amount);
    }

    function burn(uint256 amount) external {
        if (amount == 0) revert Token__InvalidAmount();
        _burn(msg.sender, amount);
    }

    function burnFrom(address from, uint256 amount) external onlyAuthorizedBurner {
        if (from == address(0)) revert Token__InvalidAddress();
        if (amount == 0) revert Token__InvalidAmount();

        uint256 currentAllowance = allowance(from, msg.sender);
        if (currentAllowance < amount) {
            revert ERC20InsufficientAllowance(msg.sender, currentAllowance, amount);
        }

        _spendAllowance(from, msg.sender, amount);
        _burn(from, amount);
    }

    function setMetadata(
        string calldata desc,
        string calldata imgUrl,
        string[] calldata socLinks
    ) external {

        if (msg.sender != creator && msg.sender != owner()) revert Token__NotAuthorized();

        _description = desc;
        _imageUrl = imgUrl;

        delete _socialLinks;

        for (uint256 i = 0; i < socLinks.length; i++) {
            _socialLinks.push(socLinks[i]);
        }

        emit MetadataUpdated(desc, imgUrl);
        emit SocialLinksUpdated(socLinks);
    }

    function getMetadata() external view returns (
        string memory desc,
        string memory imgUrl,
        string[] memory socLinks
    ) {
        return (_description, _imageUrl, _socialLinks);
    }

    function addAuthorizedMinter(address minter) external onlyOwner {
        if (minter == address(0)) revert Token__InvalidAddress();
        authorizedMinters[minter] = true;
        emit AuthorizedMinterAdded(minter);
    }

    function removeAuthorizedMinter(address minter) external onlyOwner {
        authorizedMinters[minter] = false;
        emit AuthorizedMinterRemoved(minter);
    }

    function addAuthorizedBurner(address burner) external onlyOwner {
        if (burner == address(0)) revert Token__InvalidAddress();
        authorizedBurners[burner] = true;
        emit AuthorizedBurnerAdded(burner);
    }

    function removeAuthorizedBurner(address burner) external onlyOwner {
        authorizedBurners[burner] = false;
        emit AuthorizedBurnerRemoved(burner);
    }

    function finishMinting() external onlyOwner {
        mintingFinished = true;
        emit MintingFinished();
    }

    function description() external view returns (string memory) {
        return _description;
    }

    function imageUrl() external view returns (string memory) {
        return _imageUrl;
    }

    function socialLinks() external view returns (string[] memory) {
        return _socialLinks;
    }

    function socialLinksCount() external view returns (uint256) {
        return _socialLinks.length;
    }

    function socialLink(uint256 index) external view returns (string memory) {
        require(index < _socialLinks.length, "Index out of bounds");
        return _socialLinks[index];
    }

    function isAuthorizedMinter(address account) external view returns (bool) {
        return authorizedMinters[account] || account == owner();
    }

    function isAuthorizedBurner(address account) external view returns (bool) {
        return authorizedBurners[account] || account == owner();
    }

    function getTokenInfo() external view returns (
        string memory tokenName,
        string memory tokenSymbol,
        uint8 tokenDecimals,
        uint256 tokenTotalSupply,
        uint256 tokenMaxSupply,
        address tokenCreator,
        uint256 tokenCreatedAt,
        bool tokenMintingFinished,
        string memory tokenDesc,
        string memory tokenImgUrl,
        string[] memory tokenSocLinks
    ) {
        return (
            name(),
            symbol(),
            decimals(),
            totalSupply(),
            maxSupply,
            creator,
            createdAt,
            mintingFinished,
            _description,
            _imageUrl,
            _socialLinks
        );
    }
}
"
    },
    "laxwin contracts/ILaxcePadInterfaces.sol": {
      "content": "// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

interface ITokenFactory {
    struct TokenParams {
        string name;
        string symbol;
        string description;
        string imageUrl;
        string[] socialLinks;
        uint256 totalSupply;
        uint256 bondingCurveSupply;
        uint256 liquiditySupply;
        uint256 startPrice;
        uint256 targetMarketCap;
    }

    struct SupplyLimits {
        uint256 minTotalSupply;
        uint256 maxTotalSupply;
        uint256 minBondingCurvePercent;
        uint256 maxBondingCurvePercent;
        uint256 minStartPrice;
        uint256 maxStartPrice;
        uint256 minTargetMarketCap;
        uint256 maxTargetMarketCap;
    }

    function createToken(TokenParams calldata params) external payable returns (address token);
    function getTokenInfo(address token) external view returns (TokenParams memory);
    function isTokenCreated(address token) external view returns (bool);
    function getSupplyLimits() external view returns (SupplyLimits memory);
}

interface IBondingCurve {
    struct CurveParams {
        uint256 startPrice;
        uint256 targetMarketCap;
        uint256 currentMarketCap;
        uint256 totalSupply;
        uint256 availableSupply;
        uint256 reserveETH;
        bool isGraduated;
    }

    function initializeCurve(
        address token,
        uint256 supply,
        uint256 startPrice,
        uint256 targetMarketCap
    ) external;

    function updateCurveParams(
        address token,
        uint256 newSupply,
        uint256 newStartPrice,
        uint256 newTargetMarketCap
    ) external;

    function buy(address token, uint256 minTokensOut) external payable returns (uint256 tokensOut);
    function sell(address token, uint256 tokenAmount, uint256 minETHOut) external returns (uint256 ethOut);

    function getCurrentPrice(address token) external view returns (uint256);
    function getMarketCap(address token) external view returns (uint256);
    function canGraduate(address token) external view returns (bool);
    function graduateToken(address token) external returns (bool);
    function getCurveParams(address token) external view returns (CurveParams memory);

    event TokenBought(address indexed token, address indexed buyer, uint256 ethAmount, uint256 tokenAmount, uint256 newPrice);
    event TokenSold(address indexed token, address indexed seller, uint256 tokenAmount, uint256 ethAmount, uint256 newPrice);
    event CurveInitialized(address indexed token, uint256 supply, uint256 startPrice, uint256 targetMarketCap);
    event CurveParamsUpdated(address indexed token, uint256 supply, uint256 startPrice, uint256 targetMarketCap);
}

interface IGraduationManager {
    function graduateToken(address token) external returns (address pool);
    function isGraduated(address token) external view returns (bool);
    function getGraduatedPool(address token) external view returns (address);

    event TokenGraduated(address indexed token, address indexed pool, uint256 marketCap, uint256 liquidityAdded);
}

interface IRevenueDistribution {
    struct RevenueShare {
        address recipient;
        uint256 percentage;
        string description;
    }

    function distributeRevenue() external;
    function setRevenueShare(address recipient, uint256 percentage, string calldata description) external;
    function getRevenueShare(address recipient) external view returns (uint256);
    function getTotalRevenue() external view returns (uint256);

    event RevenueDistributed(uint256 totalAmount, uint256 timestamp);
    event RevenueShareUpdated(address indexed recipient, uint256 percentage);
}

interface ILaxcePadToken {
    function mint(address to, uint256 amount) external;
    function burn(uint256 amount) external;
    function setMetadata(string calldata description, string calldata imageUrl, string[] calldata socialLinks) external;
    function getMetadata() external view returns (string memory description, string memory imageUrl, string[] memory socialLinks);
    function creator() external view returns (address);
    function createdAt() external view returns (uint256);
}

interface IDEXIntegration {
    function getTokenRegistry() external view returns (address);
    function getPoolFactory() external view returns (address);
    function getDEXEngine() external view returns (address);
    function getCoreRegistry() external view returns (address);
}
"
    },
    "@openzeppelin/contracts-upgradeable/utils/PausableUpgradeable.sol": {
      "content": "// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.3.0) (utils/Pausable.sol)

pragma solidity ^0.8.20;

import {ContextUpgradeable} from "../utils/ContextUpgradeable.sol";
import {Initializable} from "../proxy/utils/Initializable.sol";

/**
 * @dev Contract module which allows children to implement an emergency stop
 * mechanism that can be triggered by an authorized account.
 *
 * This module is used through inheritance. It will make available the
 * modifiers `whenNotPaused` and `whenPaused`, which can be applied to
 * the functions of your contract. Note that they will not be pausable by
 * simply including this module, only once the modifiers are put in place.
 */
abstract contract PausableUpgradeable is Initializable, ContextUpgradeable {
    /// @custom:storage-location erc7201:openzeppelin.storage.Pausable
    struct PausableStorage {
        bool _paused;
    }

    // keccak256(abi.encode(uint256(keccak256("openzeppelin.storage.Pausable")) - 1)) & ~bytes32(uint256(0xff))
    bytes32 private constant PausableStorageLocation = 0xcd5ed15c6e187e77e9aee88184c21f4f2182ab5827cb3b7e07fbedcd63f03300;

    function _getPausableStorage() private pure returns (PausableStorage storage $) {
        assembly {
            $.slot := PausableStorageLocation
        }
    }

    /**
     * @dev Emitted when the pause is triggered by `account`.
     */
    event Paused(address account);

    /**
     * @dev Emitted when the pause is lifted by `account`.
     */
    event Unpaused(address account);

    /**
     * @dev The operation failed because the contract is paused.
     */
    error EnforcedPause();

    /**
     * @dev The operation failed because the contract is not paused.
     */
    error ExpectedPause();

    /**
     * @dev Modifier to make a function callable only when the contract is not paused.
     *
     * Requirements:
     *
     * - The contract must not be paused.
     */
    modifier whenNotPaused() {
        _requireNotPaused();
        _;
    }

    /**
     * @dev Modifier to make a function callable only when the contract is paused.
     *
     * Requirements:
     *
     * - The contract must be paused.
     */
    modifier whenPaused() {
        _requirePaused();
        _;
    }

    function __Pausable_init() internal onlyInitializing {
    }

    function __Pausable_init_unchained() internal onlyInitializing {
    }
    /**
     * @dev Returns true if the contract is paused, and false otherwise.
     */
    function paused() public view virtual returns (bool) {
        PausableStorage storage $ = _getPausableStorage();
        return $._paused;
    }

    /**
     * @dev Throws if the contract is paused.
     */
    function _requireNotPaused() internal view virtual {
        if (paused()) {
            revert EnforcedPause();
        }
    }

    /**
     * @dev Throws if the contract is not paused.
     */
    function _requirePaused() internal view virtual {
        if (!paused()) {
            revert ExpectedPause();
        }
    }

    /**
     * @dev Triggers stopped state.
     *
     * Requirements:
     *
     * - The contract must not be paused.
     */
    function _pause() internal virtual whenNotPaused {
        PausableStorage storage $ = _getPausableStorage();
        $._paused = true;
        emit Paused(_msgSender());
    }

    /**
     * @dev Returns to normal state.
     *
     * Requirements:
     *
     * - The contract must be paused.
     */
    function _unpause() internal virtual whenPaused {
        PausableStorage storage $ = _getPausableStorage();
        $._paused = false;
        emit Unpaused(_msgSender());
    }
}
"
    },
    "@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol": {
      "content": "// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.4.0) (access/AccessControl.sol)

pragma solidity ^0.8.20;

import {IAccessControl} from "@openzeppelin/contracts/access/IAccessControl.sol";
import {ContextUpgradeable} from "../utils/ContextUpgradeable.sol";
import {IERC165} from "@openzeppelin/contracts/utils/introspection/IERC165.sol";
import {ERC165Upgradeable} from "../utils/introspection/ERC165Upgradeable.sol";
import {Initializable} from "../proxy/utils/Initializable.sol";

/**
 * @dev Contract module that allows children to implement role-based access
 * control mechanisms. This is a lightweight version that doesn't allow enumerating role
 * members except through off-chain means by accessing the contract event logs. Some
 * applications may benefit from on-chain enumerability, for those cases see
 * {AccessControlEnumerable}.
 *
 * Roles are referred to by their `bytes32` identifier. These should be exposed
 * in the external API and be unique. The best way to achieve this is by
 * using `public constant` hash digests:
 *
 * ```solidity
 * bytes32 public constant MY_ROLE = keccak256("MY_ROLE");
 * ```
 *
 * Roles can be used to represent a set of permissions. To restrict access to a
 * function call, use {hasRole}:
 *
 * ```solidity
 * function foo() public {
 *     require(hasRole(MY_ROLE, msg.sender));
 *     ...
 * }
 * ```
 *
 * Roles can be granted and revoked dynamically via the {grantRole} and
 * {revokeRole} functions. Each role has an associated admin role, and only
 * accounts that have a role's admin role can call {grantRole} and {revokeRole}.
 *
 * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means
 * that only accounts with this role will be able to grant or revoke other
 * roles. More complex role relationships can be created by using
 * {_setRoleAdmin}.
 *
 * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to
 * grant and revoke this role. Extra precautions should be taken to secure
 * accounts that have been granted it. We recommend using {AccessControlDefaultAdminRules}
 * to enforce additional security measures for this role.
 */
abstract contract AccessControlUpgradeable is Initializable, ContextUpgradeable, IAccessControl, ERC165Upgradeable {
    struct RoleData {
        mapping(address account => bool) hasRole;
        bytes32 adminRole;
    }

    bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;


    /// @custom:storage-location erc7201:openzeppelin.storage.AccessControl
    struct AccessControlStorage {
        mapping(bytes32 role => RoleData) _roles;
    }

    // keccak256(abi.encode(uint256(keccak256("openzeppelin.storage.AccessControl")) - 1)) & ~bytes32(uint256(0xff))
    bytes32 private constant AccessControlStorageLocation = 0x02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b626800;

    function _getAccessControlStorage() private pure returns (AccessControlStorage storage $) {
        assembly {
            $.slot := AccessControlStorageLocation
        }
    }

    /**
     * @dev Modifier that checks that an account has a specific role. Reverts
     * with an {AccessControlUnauthorizedAccount} error including the required role.
     */
    modifier onlyRole(bytes32 role) {
        _checkRole(role);
        _;
    }

    function __AccessControl_init() internal onlyInitializing {
    }

    function __AccessControl_init_unchained() internal onlyInitializing {
    }
    /// @inheritdoc IERC165
    function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
        return interfaceId == type(IAccessControl).interfaceId || super.supportsInterface(interfaceId);
    }

    /**
     * @dev Returns `true` if `account` has been granted `role`.
     */
    function hasRole(bytes32 role, address account) public view virtual returns (bool) {
        AccessControlStorage storage $ = _getAccessControlStorage();
        return $._roles[role].hasRole[account];
    }

    /**
     * @dev Reverts with an {AccessControlUnauthorizedAccount} error if `_msgSender()`
     * is missing `role`. Overriding this function changes the behavior of the {onlyRole} modifier.
     */
    function _checkRole(bytes32 role) internal view virtual {
        _checkRole(role, _msgSender());
    }

    /**
     * @dev Reverts with an {AccessControlUnauthorizedAccount} error if `account`
     * is missing `role`.
     */
    function _checkRole(bytes32 role, address account) internal view virtual {
        if (!hasRole(role, account)) {
            revert AccessControlUnauthorizedAccount(account, role);
        }
    }

    /**
     * @dev Returns the admin role that controls `role`. See {grantRole} and
     * {revokeRole}.
     *
     * To change a role's admin, use {_setRoleAdmin}.
     */
    function getRoleAdmin(bytes32 role) public view virtual returns (bytes32) {
        AccessControlStorage storage $ = _getAccessControlStorage();
        return $._roles[role].adminRole;
    }

    /**
     * @dev Grants `role` to `account`.
     *
     * If `account` had not been already granted `role`, emits a {RoleGranted}
     * event.
     *
     * Requirements:
     *
     * - the caller must have ``role``'s admin role.
     *
     * May emit a {RoleGranted} event.
     */
    function grantRole(bytes32 role, address account) public virtual onlyRole(getRoleAdmin(role)) {
        _grantRole(role, account);
    }

    /**
     * @dev Revokes `role` from `account`.
     *
     * If `account` had been granted `role`, emits a {RoleRevoked} event.
     *
     * Requirements:
     *
     * - the caller must have ``role``'s admin role.
     *
     * May emit a {RoleRevoked} event.
     */
    function revokeRole(bytes32 role, address account) public virtual onlyRole(getRoleAdmin(role)) {
        _revokeRole(role, account);
    }

    /**
     * @dev Revokes `role` from the calling account.
     *
     * Roles are often managed via {grantRole} and {revokeRole}: this function's
     * purpose is to provide a mechanism for accounts to lose their privileges
     * if they are compromised (such as when a trusted device is misplaced).
     *
     * If the calling account had been revoked `role`, emits a {RoleRevoked}
     * event.
     *
     * Requirements:
     *
     * - the caller must be `callerConfirmation`.
     *
     * May emit a {RoleRevoked} event.
     */
    function renounceRole(bytes32 role, address callerConfirmation) public virtual {
        if (callerConfirmation != _msgSender()) {
            revert AccessControlBadConfirmation();
        }

        _revokeRole(role, callerConfirmation);
    }

    /**
     * @dev Sets `adminRole` as ``role``'s admin role.
     *
     * Emits a {RoleAdminChanged} event.
     */
    function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {
        AccessControlStorage storage $ = _getAccessControlStorage();
        bytes32 previousAdminRole = getRoleAdmin(role);
        $._roles[role].adminRole = adminRole;
        emit RoleAdminChanged(role, previousAdminRole, adminRole);
    }

    /**
     * @dev Attempts to grant `role` to `account` and returns a boolean indicating if `role` was granted.
     *
     * Internal function without access restriction.
     *
     * May emit a {RoleGranted} event.
     */
    function _grantRole(bytes32 role, address account) internal virtual returns (bool) {
        AccessControlStorage storage $ = _getAccessControlStorage();
        if (!hasRole(role, account)) {
            $._roles[role].hasRole[account] = true;
            emit RoleGranted(role, account, _msgSender());
            return true;
        } else {
            return false;
        }
    }

    /**
     * @dev Attempts to revoke `role` from `account` and returns a boolean indicating if `role` was revoked.
     *
     * Internal function without access restriction.
     *
     * May emit a {RoleRevoked} event.
     */
    function _revokeRole(bytes32 role, address account) internal virtual returns (bool) {
        AccessControlStorage storage $ = _getAccessControlStorage();
        if (hasRole(role, account)) {
            $._roles[role].hasRole[account] = false;
            emit RoleRevoked(role, account, _msgSender());
            return true;
        } else {
            return false;
        }
    }
}
"
    },
    "@openzeppelin/contracts-upgradeable/utils/ReentrancyGuardUpgradeable.sol": {
      "content": "// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (utils/ReentrancyGuard.sol)

pragma solidity ^0.8.20;
import {Initializable} from "../proxy/utils/Initializable.sol";

/**
 * @dev Contract module that helps prevent reentrant calls to a function.
 *
 * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier
 * available, which can be applied to functions to make sure there are no nested
 * (reentrant) calls to them.
 *
 * Note that because there is a single `nonReentrant` guard, functions marked as
 * `nonReentrant` may not call one another. This can be worked around by making
 * those functions `private`, and then adding `external` `nonReentrant` entry
 * points to them.
 *
 * TIP: If EIP-1153 (transient storage) is available on the chain you're deploying at,
 * consider using {ReentrancyGuardTransient} instead.
 *
 * TIP: If you would like to learn more about reentrancy and alternative ways
 * to protect against it, check out our blog post
 * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].
 */
abstract contract ReentrancyGuardUpgradeable is Initializable {
    // Booleans are more expensive than uint256 or any type that takes up a full
    // word because each write operation emits an extra SLOAD to first read the
    // slot's contents, replace the bits taken up by the boolean, and then write
    // back. This is the compiler's defense against contract upgrades and
    // pointer aliasing, and it cannot be disabled.

    // The values being non-zero value makes deployment a bit more expensive,
    // but in exchange the refund on every call to nonReentrant will be lower in
    // amount. Since refunds are capped to a percentage of the total
    // transaction's gas, it is best to keep them low in cases like this one, to
    // increase the likelihood of the full refund coming into effect.
    uint256 private constant NOT_ENTERED = 1;
    uint256 private constant ENTERED = 2;

    /// @custom:storage-location erc7201:openzeppelin.storage.ReentrancyGuard
    struct ReentrancyGuardStorage {
        uint256 _status;
    }

    // keccak256(abi.encode(uint256(keccak256("openzeppelin.storage.ReentrancyGuard")) - 1)) & ~bytes32(uint256(0xff))
    bytes32 private constant ReentrancyGuardStorageLocation = 0x9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f00;

    function _getReentrancyGuardStorage() private pure returns (ReentrancyGuardStorage storage $) {
        assembly {
            $.slot := ReentrancyGuardStorageLocation
        }
    }

    /**
     * @dev Unauthorized reentrant call.
     */
    error ReentrancyGuardReentrantCall();

    function __ReentrancyGuard_init() internal onlyInitializing {
        __ReentrancyGuard_init_unchained();
    }

    function __ReentrancyGuard_init_unchained() internal onlyInitializing {
        ReentrancyGuardStorage storage $ = _getReentrancyGuardStorage();
        $._status = NOT_ENTERED;
    }

    /**
     * @dev Prevents a contract from calling itself, directly or indirectly.
     * Calling a `nonReentrant` function from another `nonReentrant`
     * function is not supported. It is possible to prevent this from happening
     * by making the `nonReentrant` function external, and making it call a
     * `private` function that does the actual work.
     */
    modifier nonReentrant() {
        _nonReentrantBefore();
        _;
        _nonReentrantAfter();
    }

    function _nonReentrantBefore() private {
        ReentrancyGuardStorage storage $ = _getReentrancyGuardStorage();
        // On the first call to nonReentrant, _status will be NOT_ENTERED
        if ($._status == ENTERED) {
            revert ReentrancyGuardReentrantCall();
        }

        // Any calls to nonReentrant after this point will fail
        $._status = ENTERED;
    }

    function _nonReentrantAfter() private {
        ReentrancyGuardStorage storage $ = _getReentrancyGuardStorage();
        // By storing the original value once again, a refund is triggered (see
        // https://eips.ethereum.org/EIPS/eip-2200)
        $._status = NOT_ENTERED;
    }

    /**
     * @dev Returns true if the reentrancy guard is currently set to "entered", which indicates there is a
     * `nonReentrant` function in the call stack.
     */
    function _reentrancyGuardEntered() internal view returns (bool) {
        ReentrancyGuardStorage storage $ = _getReentrancyGuardStorage();
        return $._status == ENTERED;
    }
}
"
    },
    "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol": {
      "content": "// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.3.0) (proxy/utils/UUPSUpgradeable.sol)

pragma solidity ^0.8.22;

import {IERC1822Proxiable} from "@openzeppelin/contracts/interfaces/draft-IERC1822.sol";
import {ERC1967Utils} from "@openzeppelin/contracts/proxy/ERC1967/ERC1967Utils.sol";
import {Initializable} from "./Initializable.sol";

/**
 * @dev An upgradeability mechanism designed for UUPS proxies. The functions included here can perform an upgrade of an
 * {ERC1967Proxy}, when this contract is set as the implementation behind such a proxy.
 *
 * A security mechanism ensures that an upgrade does not turn off upgradeability accidentally, although this risk is
 * reinstated if the upgrade retains upgradeability but removes the security mechanism, e.g. by replacing
 * `UUPSUpgradeable` with a custom implementation of upgrades.
 *
 * The {_authorizeUpgrade} function must be overridden to include access restriction to the upgrade mechanism.
 */
abstract contract UUPSUpgradeable is Initializable, IERC1822Proxiable {
    /// @custom:oz-upgrades-unsafe-allow state-variable-immutable
    address private immutable __self = address(this);

    /**
     * @dev The version of the upgrade interface of the contract. If this getter is missing, both `upgradeTo(address)`
     * and `upgradeToAndCall(address,bytes)` are present, and `upgradeTo` must be used if no function should be called,
     * while `upgradeToAndCall` will invoke the `receive` function if the second argument is the empty byte string.
     * If the getter returns `"5.0.0"`, only `upgradeToAndCall(address,bytes)` is present, and the second argument must
     * be the empty byte string if no function should be called, making it impossible to invoke the `receive` function
     * during an upgrade.
     */
    string public constant UPGRADE_INTERFACE_VERSION = "5.0.0";

    /**
     * @dev The call is from an unauthorized context.
     */
    error UUPSUnauthorizedCallContext();

    /**
     * @dev The storage `slot` is unsupported as a UUID.
     */
    error UUPSUnsupportedProxiableUUID(bytes32 slot);

    /**
     * @dev Check that the execution is being performed through a delegatecall call and that the execution context is
     * a proxy contract with an implementation (as defined in ERC-1967) pointing to self. This should only be the case
     * for UUPS and transparent proxies that are using the current contract as their implementation. Execution of a
     * function through ERC-1167 minimal proxies (clones) would not normally pass this test, but is not guaranteed to
     * fail.
     */
    modifier onlyProxy() {
        _checkProxy();
        _;
    }

    /**
     * @dev Check that the execution is not being performed through a delegate call. This allows a function to be
     * callable on the implementing contract but not through proxies.
     */
    modifier notDelegated() {
        _checkNotDelegated();
        _;
    }

    function __UUPSUpgradeable_init() internal onlyInitializing {
    }

    function __UUPSUpgradeable_init_unchained() internal onlyInitializing {
    }
    /**
     * @dev Implementation of the ERC-1822 {proxiableUUID} function. This returns the storage slot used by the
     * implementation. It is used to validate the implementation's compatibility when performing an upgrade.
     *
     * IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks
     * bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this
     * function revert if invoked through a proxy. This is guaranteed by the `notDelegated` modifier.
     */
    function proxiableUUID() external view virtual notDelegated returns (bytes32) {
        return ERC1967Utils.IMPLEMENTATION_SLOT;
    }

    /**
     * @dev Upgrade the implementation of the proxy to `newImplementation`, and subsequently execute the function call
     * encoded in `data`.
     *
     * Calls {_authorizeUpgrade}.
     *
     * Emits an {Upgraded} event.
     *
     * @custom:oz-upgrades-unsafe-allow-reachable delegatecall
     */
    function upgradeToAndCall(address newImplementation, bytes memory data) public payable virtual onlyProxy {
        _authorizeUpgrade(newImplementation);
        _upgradeToAndCallUUPS(newImplementation, data);
    }

    /**
     * @dev Reverts if the execution is not performed via delegatecall or the execution
     * context is not of a proxy with an ERC-1967 compliant implementation pointing to self.
     */
    function _checkProxy() internal view virtual {
        if (
            address(this) == __self || // Must be called through delegatecall
            ERC1967Utils.getImplementation() != __self // Must be called through an active proxy
        ) {
            revert UUPSUnauthorizedCallContext();
        }
    }

    /**
     * @dev Reverts if the execution is performed via delegatecall.
     * See {notDelegated}.
     */
    function _checkNotDelegated() internal view virtual {
        if (address(this) != __self) {
            // Must not be called through delegatecall
            revert UUPSUnauthorizedCallContext();
        }
    }

    /**
     * @dev Function that should revert when `msg.sender` is not authorized to upgrade the contract. Called by
     * {upgradeToAndCall}.
     *
     * Normally, this function will use an xref:access.adoc[access control] modifier such as {Ownable-onlyOwner}.
     *
     * ```solidity
     * function _authorizeUpgrade(address) internal onlyOwner {}
     * ```
     */
    function _authorizeUpgrade(address newImplementation) internal virtual;

    /**
     * @dev Performs an implementation upgrade with a security check for UUPS proxies, and additional setup call.
     *
     * As a security check, {proxiableUUID} is invoked in the new implementation, and the return value
     * is expected to be the implementation slot in ERC-1967.
     *
     * Emits an {IERC1967-Upgraded} event.
     */
    function _upgradeToAndCallUUPS(address newImplementation, bytes memory data) private {
        try IERC1822Proxiable(newImplementation).proxiableUUID() returns (bytes32 slot) {
            if (slot != ERC1967Utils.IMPLEMENTATION_SLOT) {
                revert UUPSUnsupportedProxiableUUID(slot);
            }
            ERC1967Utils.upgradeToAndCall(newImplementation, data);
        } catch {
            // The implementation is not UUPS
            revert ERC1967Utils.ERC1967InvalidImplementation(newImplementation);
        }
    }
}
"
    },
    "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol": {
      "content": "// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.3.0) (proxy/utils/Initializable.sol)

pragma solidity ^0.8.20;

/**
 * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed
 * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an
 * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer
 * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.
 *
 * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be
 * reused. This mechanism prevents re-execution of each "step" but allows the creation of new initialization steps in
 * case an upgrade adds a module that needs to be initialized.
 *
 * For example:
 *
 * [.hljs-theme-light.nopadding]
 * ```solidity
 * contract MyToken is ERC20Upgradeable {
 *     function initialize() initializer public {
 *         __ERC20_init("MyToken", "MTK");
 *     }
 * }
 *
 * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {
 *     function initializeV2() reinitializer(2) public {
 *         __ERC20Permit_init("MyToken");
 *     }
 * }
 * ```
 *
 * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as
 * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.
 *
 * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure
 * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.
 *
 * [CAUTION]
 * ====
 * Avoid leaving a contract uninitialized.
 *
 * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation
 * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke
 * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:
 *
 * [.hljs-theme-light.nopadding]
 * ```
 * /// @custom:oz-upgrades-unsafe-allow constructor
 * constructor() {
 *     _disableInitializers();
 * }
 * ```
 * ====
 */
abstract contract Initializable {
    /**
     * @dev Storage of the initializable contract.
     *
     * It's implemented on a custom ERC-7201 namespace to reduce the risk of storage collisions
     * when using with upgradeable contracts.
     *
     * @custom:storage-location erc7201:openzeppelin.storage.Initializable
     */
    struct InitializableStorage {
        /**
         * @dev Indicates that the contract has been initialized.
         */
        uint64 _initialized;
        /**
         * @dev Indicates that the contract is in the process of being initialized.
         */
        bool _initializing;
    }

    // keccak256(abi.encode(uint256(keccak256("openzeppelin.storage.Initializable")) - 1)) & ~bytes32(uint256(0xff))
    bytes32 private constant INITIALIZABLE_STORAGE = 0xf0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00;

    /**
     * @dev The contract is already initialized.
     */
    error InvalidInitialization();

    /**
     * @dev The contract is not initializing.
     */
    error NotInitializing();

    /**
     * @dev Triggered when the contract has been initialized or reinitialized.
     */
    event Initialized(uint64 version);

    /**
     * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,
     * `onlyInitializing` functions can be used to initialize parent contracts.
     *
     * Similar to `reinitializer(1)`, except that in the context of a constructor an `initializer` may be invoked any
     * number of times. This behavior in the constructor can be useful during testing and is not expected to be used in
     * production.
     *
     * Emits an {Initialized} event.
     */
    modifier initializer() {
        // solhint-disable-next-line var-name-mixedcase
        InitializableStorage storage $ = _getInitializableStorage();

        // Cache values to avoid duplicated sloads
        bool isTopLevelCall = !$._initializing;
        uint64 initialized = $._initialized;

        // Allowed calls:
        // - initialSetup: the contract is not in the initializing state and no previous version was
        //                 initialized
        // - construction: the contract is initialized at version 1 (no reinitialization) and the
        //                 current contract is just being deployed
        bool initialSetup = initialized == 0 && isTopLevelCall;
        bool construction = initialized == 1 && address(this).code.length == 0;

        if (!initialSetup && !construction) {
            revert InvalidInitialization();
        }
        $._initialized = 1;
        if (isTopLevelCall) {
            $._initializing = true;
        }
        _;
        if (isTopLevelCall) {
            $._initializing = false;
            emit Initialized(1);
        }
    }

    /**
     * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the
     * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be
     * used to initialize parent contracts.
     *
     * A reinitializer may be used after the original initialization step. This is essential to configure modules that
     * are added through upgrades and that require initialization.
     *
     * When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer`
     * cannot be nested. If one is invoked in the context of another, execution will revert.
     *
     * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in
     * a contract, executing them in the right order is up to the developer or operator.
     *
     * WARNING: Setting the version to 2**64 - 1 will prevent any future reinitialization.
     *
     * Emits an {Initialized} event.
     */
    modifier reinitializer(uint64 version) {
        // solhint-disable-next-line var-name-mixedcase
        InitializableStorage storage $ = _getInitializableStorage();

        if ($._initializing || $._initialized >= version) {
            revert InvalidInitialization();
        }
        $._initialized = version;
        $._initializing = true;
        _;
        $._initializing = false;
        emit Initialized(version);
    }

    /**
     * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the
     * {initializer} and {reinitializer} modifiers, directly or indirectly.
     */
    modifier onlyInitializing() {
        _checkInitializing();
        _;
    }

    /**
     * @dev Reverts if the contract is not in an initializing state. See {onlyInitializing}.
     */
    function _checkInitializing() internal view virtual {
        if (!_isInitializing()) {
            revert NotInitializing();
        }
    }

    /**
     * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.
     * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized
     * to any version. It is recommended to use this to lock implementation contracts that are designed to be called
     * through proxies.
     *
     * Emits an {Initialized} event the first time it is successfully executed.
     */
    function _disableInitializers() internal virtual {
        // solhint-disable-next-line var-name-mixedcase
        InitializableStorage storage $ = _getInitializableStorage();

        if ($._initializing) {
            revert InvalidInitialization();
        }
        if ($._initialized != type(uint64).max) {
            $._initialized = type(uint64).max;
            emit Initialized(type(uint64).max);
        }
    }

    /**
     * @dev Returns the highest version that has been initialized. See {reinitializer}.
     */
    function _getInitializedVersion() internal view returns (uint64) {
        return _getInitializableStorage()._initialized;
    }

    /**
     * @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}.
     */
    function _isInitializing() internal view returns (bool) {
        return _getInitializableStorage()._initializing;
    }

    /**
     * @dev Pointer to storage slot. Allows integrators to override it with a custom storage location.
     *
     * NOTE: Consider following the ERC-7201 formula to derive storage locations.
     */
    function _initializableStorageSlot() internal pure virtual returns (bytes32) {
        return INITIALIZABLE_STORAGE;
    }

    /**
     * @dev Returns a pointer to the storage namespace.
     */
    // solhint-disable-next-line var-name-mixedcase
    function _getInitializableStorage() private pure returns (InitializableStorage storage $) {
        bytes32 slot = _initializableStorageSlo

Tags:
ERC20, ERC165, Multisig, Mintable, Burnable, Pausable, Liquidity, Upgradeable, Multi-Signature, Factory|addr:0x2628021c95ae288ce9fcb6794576773fe327667d|verified:true|block:23634521|tx:0xead6d703b1311cc178672e738abb569beed63f4aa0603af4a515a1e9d26cdc25|first_check:1761291514

Submitted on: 2025-10-24 09:38:36

Comments

Log in to comment.

No comments yet.