AllTokensToLPFactoryFixed

Description:

Decentralized Finance (DeFi) protocol contract providing Mintable, Swap, Liquidity, Factory functionality.

Blockchain: Ethereum

Source Code: View Code On The Blockchain

Solidity Source Code:

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

interface IUniswapV3Factory {
    function createPool(address tokenA, address tokenB, uint24 fee) external returns (address pool);
}

interface INonfungiblePositionManager {
    struct MintParams {
        address token0;
        address token1;
        uint24 fee;
        int24 tickLower;
        int24 tickUpper;
        uint256 amount0Desired;
        uint256 amount1Desired;
        uint256 amount0Min;
        uint256 amount1Min;
        address recipient;
        uint256 deadline;
    }

    function mint(MintParams calldata params) external payable returns (
        uint256 tokenId,
        uint128 liquidity,
        uint256 amount0,
        uint256 amount1
    );

    function createAndInitializePoolIfNecessary(
        address token0,
        address token1,
        uint24 fee,
        uint160 sqrtPriceX96
    ) external payable returns (address pool);
    
    struct CollectParams {
        uint256 tokenId;
        address recipient;
        uint128 amount0Max;
        uint128 amount1Max;
    }
    
    function collect(CollectParams calldata params) external payable returns (uint256 amount0, uint256 amount1);
}

interface ISwapRouter {
    struct ExactInputSingleParams {
        address tokenIn;
        address tokenOut;
        uint24 fee;
        address recipient;
        uint256 deadline;
        uint256 amountIn;
        uint256 amountOutMinimum;
        uint160 sqrtPriceLimitX96;
    }

    function exactInputSingle(ExactInputSingleParams calldata params) external payable returns (uint256 amountOut);
}

interface IERC20 {
    function transfer(address to, uint256 amount) external returns (bool);
    function transferFrom(address from, address to, uint256 amount) external returns (bool);
    function balanceOf(address account) external view returns (uint256);
    function approve(address spender, uint256 amount) external returns (bool);
    function totalSupply() external view returns (uint256);
}

interface IWETH {
    function deposit() external payable;
    function balanceOf(address) external view returns (uint256);
    function transfer(address, uint256) external returns (bool);
    function approve(address spender, uint256 amount) external returns (bool);
    function withdraw(uint256) external;
}

// Simple anti-sniper ERC20 with minimal restrictions
contract AutoAntiSniperERC20 {
    string public name;
    string public symbol;
    uint8 public decimals = 18;
    uint256 public totalSupply = 1000000000 * 10**18; // 1 billion tokens
    
    mapping(address => uint256) public balanceOf;
    mapping(address => mapping(address => uint256)) public allowance;
    
    // Anti-sniper variables
    address public factory;
    address public creator;
    uint256 public launchTime; // When token was created
    uint256 public devBuyWindow = 300; // 5 minutes for dev exclusive access
    
    // Ethereum Uniswap addresses that should always be allowed
    address constant POSITION_MANAGER = 0xC36442b4a4522E871399CD717aBDD847Ab11FE88;
    address constant SWAP_ROUTER = 0xE592427A0AEce92De3Edee1F18E0157C05861564;
    address constant WETH = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2;
    
    event Transfer(address indexed from, address indexed to, uint256 value);
    event Approval(address indexed owner, address indexed spender, uint256 value);
    
    modifier tradingAllowed() {
        // Always allow factory, creator, and core Uniswap contracts
        if (msg.sender == creator || 
            msg.sender == factory || 
            msg.sender == POSITION_MANAGER ||
            msg.sender == SWAP_ROUTER ||
            tx.origin == creator) {
            _;
            return;
        }
        
        // For everyone else, check dev buy window
        if (block.timestamp < launchTime + devBuyWindow) {
            revert();
        }
        _;
    }
    
    constructor(string memory _name, string memory _symbol, address _creator) {
        name = _name;
        symbol = _symbol;
        creator = _creator;
        factory = msg.sender;
        launchTime = block.timestamp; // Record launch time automatically
        balanceOf[factory] = totalSupply; // All tokens start in factory
        emit Transfer(address(0), factory, totalSupply);
    }
    
    function transfer(address to, uint256 amount) external tradingAllowed returns (bool) {
        require(to != address(0));
        require(balanceOf[msg.sender] >= amount);
        
        balanceOf[msg.sender] -= amount;
        balanceOf[to] += amount;
        emit Transfer(msg.sender, to, amount);
        return true;
    }
    
    function approve(address spender, uint256 amount) external returns (bool) {
        require(spender != address(0));
        allowance[msg.sender][spender] = amount;
        emit Approval(msg.sender, spender, amount);
        return true;
    }
    
    function transferFrom(address from, address to, uint256 amount) external tradingAllowed returns (bool) {
        require(from != address(0));
        require(to != address(0));
        require(balanceOf[from] >= amount);
        require(allowance[from][msg.sender] >= amount);
        
        balanceOf[from] -= amount;
        balanceOf[to] += amount;
        allowance[from][msg.sender] -= amount;
        emit Transfer(from, to, amount);
        return true;
    }
}

// Enhanced factory with automatic anti-sniper time windows
contract AllTokensToLPFactoryFixed {
    
    struct TokenInfo {
        address tokenAddress;
        address creator;
        string name;
        string symbol;
        uint256 tokenId;
        uint256 createdAt;
        address pool;
        int24 tickLower;
        int24 tickUpper;
        uint256 totalFeesETH;
    }
    
    TokenInfo[] public allTokens;
    mapping(address => TokenInfo[]) public createdTokens;
    mapping(uint256 => address) public tokenCreators;
    mapping(address => uint256) public creatorFeesETH;

    address public platformAdmin;
    uint256 public platformFeesETH;
    
    // ETHEREUM MAINNET V3 addresses
    address constant POSITION_MANAGER = 0xC36442b4a4522E871399CD717aBDD847Ab11FE88;
    address constant SWAP_ROUTER = 0xE592427A0AEce92De3Edee1F18E0157C05861564;
    address constant WETH = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2;
    uint24 constant POOL_FEE = 10000;
    
    // Price range ticks
    int24 constant TICK_LOWER = -887200;
    int24 constant TICK_UPPER = 207200;
    
    uint256 constant MIN_SWAP_AMOUNT = 1000 * 10**18;
    uint256 constant CREATOR_SHARE = 50;
    uint256 constant PLATFORM_SHARE = 50;
    uint256 constant REQUIRED_ETH = 0.001 ether; // Updated to match mainnet fee
    
    event TokenCreated(address indexed creator, address indexed tokenAddress, string name, string symbol, uint256 tokenId, address pool, int24 tickLower, int24 tickUpper);
    event ExcessFundsSent(address indexed creator, uint256 amount, address indexed recipient);
    event FeesCollected(uint256 indexed tokenId, uint256 ethAmount, uint256 tokenAmount, uint256 swappedETH);
    event TokensDirectToCreator(address indexed creator, address indexed tokenAddress, uint256 amount);
    event CreatorWithdraw(address indexed creator, uint256 ethAmount);
    event PlatformWithdraw(uint256 ethAmount);
    event AllTokensDeposited(address indexed tokenAddress, uint256 totalTokens, uint256 finalBalance);
    
    modifier onlyCreatorOrAdmin(uint256 tokenId) {
        address creator = tokenCreators[tokenId];
        require(creator != address(0));
        require(msg.sender == creator || msg.sender == platformAdmin);
        _;
    }
    
    constructor() {
        platformAdmin = 0x9360c80CA79409b5e315A9791bB0208C02D6ae32;
    }
    
    // Calculate sqrt price
    function calculateSqrtPriceX96(address token) internal pure returns (uint160) {
        bool tokenIsToken0 = token < WETH;
        
        if (tokenIsToken0) {
            // token0 = TOKEN, token1 = WETH
            return 2505414483750479500000000;
        } else {
            // token0 = WETH, token1 = TOKEN
            return 2505414483750479200000000000000000;
        }
    }
    
    function createToken(string memory name, string memory symbol) external payable returns (address tokenAddress, uint256 tokenId) {
        require(msg.value >= REQUIRED_ETH);
        require(bytes(name).length > 0 && bytes(name).length <= 32);
        require(bytes(symbol).length > 0 && bytes(symbol).length <= 10);
        
        uint256 liquidityAmount = REQUIRED_ETH;
        uint256 excessAmount = msg.value - liquidityAmount;
        
        // Deploy the automatic anti-sniper ERC20 token with salt iteration
        tokenAddress = _deployTokenWithValidAddress(name, symbol, msg.sender);
        
        // Create pool and deposit ALL tokens using full range
        address pool;
        (tokenId, pool) = _createFullRangeLP(tokenAddress, liquidityAmount);
        
        tokenCreators[tokenId] = msg.sender;
        
        // Send excess funds to platform admin
        if (excessAmount > 0) {
            (bool success, ) = platformAdmin.call{value: excessAmount}("");
            require(success);
            emit ExcessFundsSent(msg.sender, excessAmount, platformAdmin);
        }
        
        // Store token info
        TokenInfo memory tokenInfo = TokenInfo({
            tokenAddress: tokenAddress,
            creator: msg.sender,
            name: name,
            symbol: symbol,
            tokenId: tokenId,
            createdAt: block.timestamp,
            pool: pool,
            tickLower: TICK_LOWER,
            tickUpper: TICK_UPPER,
            totalFeesETH: 0
        });
        
        createdTokens[msg.sender].push(tokenInfo);
        allTokens.push(tokenInfo);
        
        emit TokenCreated(msg.sender, tokenAddress, name, symbol, tokenId, pool, TICK_LOWER, TICK_UPPER);
        
        return (tokenAddress, tokenId);
    }
    
    // Deploy token with salt iteration to ensure address > WETH
    function _deployTokenWithValidAddress(string memory name, string memory symbol, address creator) internal returns (address) {
        uint256 saltNonce = 0;
        address predictedAddress;
        
        // Keep trying until we get an address > WETH
        do {
            bytes32 salt = keccak256(abi.encodePacked(name, symbol, creator, block.timestamp, saltNonce));
            predictedAddress = _computeCreate2Address(salt, name, symbol, creator);
            saltNonce++;
            
            // Prevent infinite loop (should never happen based on our testing)
            require(saltNonce < 100, "Could not find valid address");
        } while (predictedAddress <= WETH);
        
        // Deploy with the valid salt
        bytes32 finalSalt = keccak256(abi.encodePacked(name, symbol, creator, block.timestamp, saltNonce - 1));
        return _deployTokenWithSalt(finalSalt, name, symbol, creator);
    }
    
    // Compute CREATE2 address without deploying
    function _computeCreate2Address(bytes32 salt, string memory name, string memory symbol, address creator) internal view returns (address) {
        bytes memory bytecode = abi.encodePacked(
            type(AutoAntiSniperERC20).creationCode,
            abi.encode(name, symbol, creator)
        );
        
        bytes32 hash = keccak256(
            abi.encodePacked(
                bytes1(0xff),
                address(this),
                salt,
                keccak256(bytecode)
            )
        );
        
        return address(uint160(uint256(hash)));
    }
    
    // Deploy token using CREATE2 with specific salt
    function _deployTokenWithSalt(bytes32 salt, string memory name, string memory symbol, address creator) internal returns (address) {
        bytes memory bytecode = abi.encodePacked(
            type(AutoAntiSniperERC20).creationCode,
            abi.encode(name, symbol, creator)
        );
        
        address tokenAddress;
        assembly {
            tokenAddress := create2(0, add(bytecode, 0x20), mload(bytecode), salt)
        }
        
        require(tokenAddress != address(0), "Token deployment failed");
        require(tokenAddress > WETH, "Invalid token address generated");
        
        return tokenAddress;
    }



    function _createFullRangeLP(address tokenAddress, uint256 ethAmount) internal returns (uint256 tokenId, address pool) {
        // Convert ETH to WETH
        IWETH(WETH).deposit{value: ethAmount}();
        
        uint256 totalTokens = IERC20(tokenAddress).balanceOf(address(this));
        require(totalTokens == 1000000000 * 10**18);
        
        // Determine token order
        bool tokenIsToken0 = tokenAddress < WETH;
        address token0 = tokenIsToken0 ? tokenAddress : WETH;
        address token1 = tokenIsToken0 ? WETH : tokenAddress;
        
        uint160 sqrtPriceX96 = calculateSqrtPriceX96(tokenAddress);
        
        pool = INonfungiblePositionManager(POSITION_MANAGER).createAndInitializePoolIfNecessary(
            token0, token1, POOL_FEE, sqrtPriceX96
        );
        
        IERC20(tokenAddress).approve(POSITION_MANAGER, totalTokens);
        IWETH(WETH).approve(POSITION_MANAGER, ethAmount);
        
        (tokenId, , ,) = INonfungiblePositionManager(POSITION_MANAGER).mint(
            INonfungiblePositionManager.MintParams({
                token0: token0,
                token1: token1,
                fee: POOL_FEE,
                tickLower: TICK_LOWER,
                tickUpper: TICK_UPPER,
                amount0Desired: tokenIsToken0 ? totalTokens : ethAmount,
                amount1Desired: tokenIsToken0 ? ethAmount : totalTokens,
                amount0Min: 0, 
                amount1Min: 0,
                recipient: address(this),
                deadline: block.timestamp + 300
            })
        );
        
        uint256 finalBalance = IERC20(tokenAddress).balanceOf(address(this));
        emit AllTokensDeposited(tokenAddress, totalTokens, finalBalance);
        
        return (tokenId, pool);
    }
    
    function collectFees(uint256 tokenId) external onlyCreatorOrAdmin(tokenId) {
        INonfungiblePositionManager.CollectParams memory params = INonfungiblePositionManager.CollectParams({
            tokenId: tokenId,
            recipient: address(this),
            amount0Max: type(uint128).max,
            amount1Max: type(uint128).max
        });
        
        (uint256 amount0, uint256 amount1) = INonfungiblePositionManager(POSITION_MANAGER).collect(params);
        
        if (amount0 == 0 && amount1 == 0) return;
        
        address creator = tokenCreators[tokenId];
        uint256 ethAmount = 0;
        uint256 tokenAmount = 0;
        address tokenAddress;
        
        for (uint i = 0; i < allTokens.length; i++) {
            if (allTokens[i].tokenId == tokenId) {
                tokenAddress = allTokens[i].tokenAddress;
                break;
            }
        }
        
        bool tokenIsToken0 = tokenAddress < WETH;
        if (tokenIsToken0) {
            tokenAmount = amount0;
            ethAmount = amount1;
        } else {
            tokenAmount = amount1;
            ethAmount = amount0;
        }
        
        if (ethAmount > 0) {
            IWETH(WETH).withdraw(ethAmount);
        }
        
        uint256 swappedETH = 0;
        if (tokenAmount >= MIN_SWAP_AMOUNT) {
            swappedETH = _swapTokensForETH(tokenAddress, tokenAmount);
            // If swap fails, send tokens directly to creator
            if (swappedETH == 0 && tokenAmount > 0) {
                IERC20(tokenAddress).transfer(creator, tokenAmount);
                emit TokensDirectToCreator(creator, tokenAddress, tokenAmount);
            }
        } else if (tokenAmount > 0) {
            // For small amounts, try to swap first
            swappedETH = _swapTokensForETH(tokenAddress, tokenAmount);
            if (swappedETH == 0) {
                // If swap fails, send tokens directly to creator instead of accumulating
                IERC20(tokenAddress).transfer(creator, tokenAmount);
                emit TokensDirectToCreator(creator, tokenAddress, tokenAmount);
            }
        }
        
        uint256 totalETH = ethAmount + swappedETH;
        
        if (totalETH > 0) {
            uint256 platformETH = (totalETH * PLATFORM_SHARE) / 100;
            uint256 creatorETH = totalETH - platformETH;
            
            creatorFeesETH[creator] += creatorETH;
            platformFeesETH += platformETH;
            
            for (uint i = 0; i < allTokens.length; i++) {
                if (allTokens[i].tokenId == tokenId) {
                    allTokens[i].totalFeesETH += totalETH;
                    break;
                }
            }
        }
        
        emit FeesCollected(tokenId, ethAmount, tokenAmount, swappedETH);
    }
    
    // CRITICAL: This is the missing function that the frontend expects!
    function collectTokenFees(address tokenAddress) external {
        // Find all tokens for this creator and collect fees from them
        for (uint i = 0; i < allTokens.length; i++) {
            if (allTokens[i].tokenAddress == tokenAddress && allTokens[i].creator == msg.sender) {
                try this.collectFees(allTokens[i].tokenId) {
                } catch {
                }
                break;
            }
        }
    }
    

    

    
    function _swapTokensForETH(address tokenAddress, uint256 tokenAmount) internal returns (uint256 ethReceived) {
        if (tokenAmount == 0) return 0;
        
        IERC20(tokenAddress).approve(SWAP_ROUTER, tokenAmount);
        
        try ISwapRouter(SWAP_ROUTER).exactInputSingle(
            ISwapRouter.ExactInputSingleParams({
                tokenIn: tokenAddress,
                tokenOut: WETH,
                fee: POOL_FEE,
                recipient: address(this),
                deadline: block.timestamp + 300,
                amountIn: tokenAmount,
                amountOutMinimum: 0,
                sqrtPriceLimitX96: 0
            })
        ) returns (uint256 amountOut) {
            IWETH(WETH).withdraw(amountOut);
            return amountOut;
        } catch {
            return 0;
        }
    }
    
    function withdrawCreatorFees() external {
        uint256 amount = creatorFeesETH[msg.sender];
        require(amount > 0);
        
        creatorFeesETH[msg.sender] = 0;
        (bool success, ) = msg.sender.call{value: amount}("");
        require(success);
        
        emit CreatorWithdraw(msg.sender, amount);
    }
    
    function withdrawPlatformFees() external {
        require(msg.sender == platformAdmin);
        uint256 amount = platformFeesETH;
        require(amount > 0);
        
        platformFeesETH = 0;
        (bool success, ) = platformAdmin.call{value: amount}("");
        require(success);
        
        emit PlatformWithdraw(amount);
    }
    
    function getCreatorFees(address creator) external view returns (uint256) {
        return creatorFeesETH[creator];
    }
    
    function getPlatformFees() external view returns (uint256) {
        return platformFeesETH;
    }
    
    function getTokenCount() external view returns (uint256) {
        return allTokens.length;
    }
    

    
    receive() external payable {}
}

Tags:
ERC20, DeFi, Mintable, Swap, Liquidity, Factory|addr:0xc089fab8b099cf6b99e38ffeb1f462ee6458ea7d|verified:true|block:23665810|tx:0xf344d0e8f4d495a909702aa7f38ec8098056492528e627c0dd1467e1e3bd6594|first_check:1761561646

Submitted on: 2025-10-27 11:40:46

Comments

Log in to comment.

No comments yet.