MemeStrategyViews

Description:

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

Blockchain: Ethereum

Source Code: View Code On The Blockchain

Solidity Source Code:

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

import {IUniswapV2Router} from "./interfaces/IUniswapV2Router.sol";

interface IMemeStrategy {
    struct MemeToken {
        address v2Router;
        bool isWhitelisted;
    }

    struct QueuedPurchase {
        uint256 queueId;
        address targetAddress;
        uint256 ethAmount;
        uint256 targetMultiplier;
        uint256 maxSlippage;
        uint256 targetEntryPrice;
        uint256 queuedAt;
        bool executed;
        bool exists;
        bool executeToTreasury;
    }

    struct Purchase {
        uint256 purchaseId;
        address tokenAddress;
        uint256 tokenAmount;
        uint256 buyPricePerUnit;
        uint256 targetPrice;
        uint256 ethSpent;
        uint256 timestamp;
        bool sold;
        uint256 soldPrice;
        uint256 soldTimestamp;
        bool isProfit;
        uint256 profitOrLoss;
        uint256 slippageUsed;
        bool executeToTreasury;
    }

    // Getters
    function queuedPurchases(uint256) external view returns (QueuedPurchase memory);
    function whitelistedTokens(address) external view returns (MemeToken memory);
    function purchases(uint256) external view returns (Purchase memory);
    function nextQueueId() external view returns (uint256);
    function activeQueueCount() external view returns (uint256);
    function totalQueues() external view returns (uint256);
    function executorReward() external view returns (uint256);
    function paused() external view returns (bool);
    function totalPurchases() external view returns (uint256);
    function totalProfit() external view returns (uint256);
    function totalLoss() external view returns (uint256);
    function totalTokensBurned() external view returns (uint256);
    function successfulFlips() external view returns (uint256);
    function getActivePurchaseCount() external view returns (uint256);
    function getWETH() external view returns (address);
}

interface IERC20 {
    function balanceOf(address) external view returns (uint256);
}

/// @title MemeStrategyViews
/// @notice Separate contract for large view functions to keep main contract under 24KB
/// @dev Deploy this separately and call with strategy address as first parameter
contract MemeStrategyViews {

    uint256 constant BPS_BASE = 10_000;
    uint256 constant MAX_BATCH_SIZE = 50;

    /* ═══════════════════════════════════════════════════════════════════════════ */
    /*                            QUEUE VIEW FUNCTIONS                              */
    /* ═══════════════════════════════════════════════════════════════════════════ */

    /// @notice Get queue items by IDs (backend provides the IDs in desired order)
    /// @dev Backend maintains queue order off-chain and provides IDs to query
    /// @param strategy Strategy contract address
    /// @param queueIds Array of queue IDs to fetch
    /// @return Array of queued purchases
    function getQueuedPurchasesByIds(
        address strategy,
        uint256[] calldata queueIds
    ) external view returns (IMemeStrategy.QueuedPurchase[] memory) {
        IMemeStrategy strat = IMemeStrategy(strategy);
        
        uint256 length = queueIds.length > MAX_BATCH_SIZE ? MAX_BATCH_SIZE : queueIds.length;
        IMemeStrategy.QueuedPurchase[] memory queued = new IMemeStrategy.QueuedPurchase[](length);
        
        for (uint256 i = 0; i < length; i++) {
            queued[i] = strat.queuedPurchases(queueIds[i]);
        }
        
        return queued;
    }

    /// @notice Get basic queue stats
    /// @param strategy Strategy contract address
    /// @return totalQueues Total number of queues ever created
    /// @return activeCount Number of active queues
    /// @return nextId Next queue ID to be assigned
    function getQueueStats(
        address strategy
    ) external view returns (
        uint256 totalQueues,
        uint256 activeCount,
        uint256 nextId
    ) {
        IMemeStrategy strat = IMemeStrategy(strategy);
        return (
            strat.totalQueues(),
            strat.activeQueueCount(),
            strat.nextQueueId()
        );
    }

    /* ═══════════════════════════════════════════════════════════════════════════ */
    /*                          EXECUTABLE QUEUE HELPERS                            */
    /* ═══════════════════════════════════════════════════════════════════════════ */

    /// @notice Check if a queued purchase can be executed
    /// @param strategy Strategy contract address
    /// @param queueId Queue ID to check
    function canExecuteQueue(address strategy, uint256 queueId)
        external
        view
        returns (
            bool executable,
            string memory reason,
            uint256 estimatedGas,
            uint256 profitability
        )
    {
        IMemeStrategy strat = IMemeStrategy(strategy);

        // Direct access by queueId
        IMemeStrategy.QueuedPurchase memory queue = strat.queuedPurchases(queueId);

        if (!queue.exists || queue.executed) {
            return (false, "Queue item not found", 0, 0);
        }

        if (strat.paused()) {
            return (false, "Contract paused", 0, 0);
        }

        uint256 executorReward = strat.executorReward();
        if (strategy.balance < queue.ethAmount + executorReward) {
            return (false, "Insufficient ETH fees", 0, 0);
        }

        // Check target entry price if set
        if (queue.targetEntryPrice > 0) {
            IMemeStrategy.MemeToken memory tokenInfo = strat.whitelistedTokens(queue.targetAddress);
            IUniswapV2Router v2Router = IUniswapV2Router(tokenInfo.v2Router);

            address[] memory path = new address[](2);
            path[0] = strat.getWETH();
            path[1] = queue.targetAddress;

            try v2Router.getAmountsOut(1e18, path) returns (uint256[] memory amounts) {
                uint256 currentPricePerToken = amounts[1];
                uint256 pricePerToken = (1e18 * 1e18) / currentPricePerToken;

                if (pricePerToken > queue.targetEntryPrice) {
                    return (false, "Entry price not reached", 0, 0);
                }
            } catch {
                return (false, "No V2 liquidity", 0, 0);
            }
        }

        estimatedGas = 150_000;
        uint256 gasCost = estimatedGas * tx.gasprice;
        profitability = executorReward > gasCost ? executorReward - gasCost : 0;

        return (true, "", estimatedGas, profitability);
    }

    /// @notice Check multiple queue IDs for executability (backend provides IDs)
    /// @dev Backend maintains queue order and provides IDs to check
    /// @param strategy Strategy contract address
    /// @param queueIds Array of queue IDs to check
    /// @return executableIds Array of executable queue IDs
    /// @return reasons Array of execution status reasons
    function checkQueueExecutability(
        address strategy,
        uint256[] calldata queueIds
    ) external view returns (
        uint256[] memory executableIds,
        string[] memory reasons
    ) {
        IMemeStrategy strat = IMemeStrategy(strategy);
        uint256 length = queueIds.length > MAX_BATCH_SIZE ? MAX_BATCH_SIZE : queueIds.length;
        
        uint256 executorReward = strat.executorReward();
        bool isPaused = strat.paused();
        address weth = strat.getWETH();

        // First pass: count executable items
        uint256 count = 0;
        bool[] memory isExecutable = new bool[](length);
        
        for (uint256 i = 0; i < length; i++) {
            IMemeStrategy.QueuedPurchase memory queue = strat.queuedPurchases(queueIds[i]);
            
            if (!queue.exists || queue.executed) continue;
            if (isPaused) continue;
            if (strategy.balance < queue.ethAmount + executorReward) continue;

            bool priceOk = true;
            if (queue.targetEntryPrice > 0) {
                IMemeStrategy.MemeToken memory tokenInfo = strat.whitelistedTokens(queue.targetAddress);
                IUniswapV2Router v2Router = IUniswapV2Router(tokenInfo.v2Router);

                address[] memory path = new address[](2);
                path[0] = weth;
                path[1] = queue.targetAddress;

                try v2Router.getAmountsOut(1e18, path) returns (uint256[] memory amounts) {
                    uint256 currentPricePerToken = amounts[1];
                    uint256 pricePerToken = (1e18 * 1e18) / currentPricePerToken;

                    if (pricePerToken > queue.targetEntryPrice) {
                        priceOk = false;
                    }
                } catch {
                    priceOk = false;
                }
            }

            if (priceOk) {
                isExecutable[i] = true;
                count++;
            }
        }

        // Second pass: collect executable IDs
        executableIds = new uint256[](count);
        reasons = new string[](count);
        uint256 index = 0;
        
        for (uint256 i = 0; i < length; i++) {
            if (isExecutable[i]) {
                executableIds[index] = queueIds[i];
                reasons[index] = "Executable";
                index++;
            }
        }

        return (executableIds, reasons);
    }

    /* ═══════════════════════════════════════════════════════════════════════════ */
    /*                          PURCHASE VIEW FUNCTIONS                             */
    /* ═══════════════════════════════════════════════════════════════════════════ */

    /// @notice Check if a purchase can be sold
    function canExecuteSale(address strategy, uint256 _purchaseId)
        external
        view
        returns (
            bool canSell,
            uint256 currentPrice,
            uint256 targetPrice,
            string memory reason
        )
    {
        IMemeStrategy strat = IMemeStrategy(strategy);
        IMemeStrategy.Purchase memory purchase = strat.purchases(_purchaseId);

        if (purchase.purchaseId == 0) {
            return (false, 0, 0, "Purchase not found");
        }

        if (purchase.sold) {
            return (false, 0, 0, "Already sold");
        }

        if (strat.paused()) {
            return (false, 0, 0, "Contract paused");
        }

        IERC20 token = IERC20(purchase.tokenAddress);
        uint256 balance = token.balanceOf(strategy);
        if (balance < purchase.tokenAmount) {
            return (false, 0, 0, "Insufficient token balance");
        }

        IMemeStrategy.MemeToken memory tokenInfo = strat.whitelistedTokens(purchase.tokenAddress);
        IUniswapV2Router v2Router = IUniswapV2Router(tokenInfo.v2Router);

        address[] memory path = new address[](2);
        path[0] = purchase.tokenAddress;
        path[1] = strat.getWETH();

        try v2Router.getAmountsOut(balance, path) returns (
            uint256[] memory amounts
        ) {
            currentPrice = amounts[1] * 1e18 / balance;
        } catch {
            currentPrice = 0;
        }

        targetPrice = purchase.targetPrice;

        if (currentPrice < targetPrice) {
            return (
                false,
                currentPrice,
                targetPrice,
                "Target price not reached"
            );
        }

        return (true, currentPrice, targetPrice, "");
    }

    /// @notice Get strategy statistics
    function getStrategyStats(address strategy)
        external
        view
        returns (
            uint256 _totalPurchases,
            uint256 _activePurchases,
            uint256 _completedPurchases,
            bool isNetProfit,
            uint256 netProfitOrLossETH,
            uint256 _totalBurned,
            uint256 successRateX100,
            uint256 _currentFeesETH,
            uint256 strategyTokenPrice
        )
    {
        IMemeStrategy strat = IMemeStrategy(strategy);

        _totalPurchases = strat.totalPurchases();
        _activePurchases = strat.getActivePurchaseCount();
        _completedPurchases = _totalPurchases - _activePurchases;

        uint256 totalProfit = strat.totalProfit();
        uint256 totalLoss = strat.totalLoss();
        isNetProfit = totalProfit > totalLoss;
        netProfitOrLossETH = isNetProfit
            ? totalProfit - totalLoss
            : totalLoss - totalProfit;

        _totalBurned = strat.totalTokensBurned();

        uint256 successfulFlips = strat.successfulFlips();
        successRateX100 = _totalPurchases > 0
            ? ((successfulFlips * 10000) / _totalPurchases)
            : 0;

        _currentFeesETH = strategy.balance;
        strategyTokenPrice = 0; // Removed oracle dependency
    }

    /// @notice Get purchase history
    function getPurchaseHistory(
        address strategy,
        uint256 offset,
        uint256 limit
    ) external view returns (IMemeStrategy.Purchase[] memory) {
        IMemeStrategy strat = IMemeStrategy(strategy);
        uint256 totalPurchases = strat.totalPurchases();

        if (limit > MAX_BATCH_SIZE) limit = MAX_BATCH_SIZE;
        if (offset >= totalPurchases) return new IMemeStrategy.Purchase[](0);

        uint256 end = offset + limit;
        if (end > totalPurchases) end = totalPurchases;

        uint256 length = end - offset;
        IMemeStrategy.Purchase[] memory history = new IMemeStrategy.Purchase[](length);

        for (uint256 i = 0; i < length; i++) {
            history[i] = strat.purchases(offset + i + 1); // purchaseId starts at 1
        }

        return history;
    }
}
"
    },
    "src/interfaces/IUniswapV2Router.sol": {
      "content": "// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

interface IUniswapV2Router {
    function swapExactETHForTokens(
        uint256 amountOutMin,
        address[] calldata path,
        address to,
        uint256 deadline
    ) external payable returns (uint256[] memory amounts);

    function swapExactTokensForETH(
        uint256 amountIn,
        uint256 amountOutMin,
        address[] calldata path,
        address to,
        uint256 deadline
    ) external returns (uint256[] memory amounts);

    function swapExactTokensForTokens(
        uint256 amountIn,
        uint256 amountOutMin,
        address[] calldata path,
        address to,
        uint256 deadline
    ) external returns (uint256[] memory amounts);
    
    // Fee-on-transfer token support (critical for meme tokens with taxes)
    function swapExactETHForTokensSupportingFeeOnTransferTokens(
        uint256 amountOutMin,
        address[] calldata path,
        address to,
        uint256 deadline
    ) external payable;
    
    function swapExactTokensForETHSupportingFeeOnTransferTokens(
        uint256 amountIn,
        uint256 amountOutMin,
        address[] calldata path,
        address to,
        uint256 deadline
    ) external;
    
    function swapExactTokensForTokensSupportingFeeOnTransferTokens(
        uint256 amountIn,
        uint256 amountOutMin,
        address[] calldata path,
        address to,
        uint256 deadline
    ) external;
    
    function getAmountsOut(
        uint256 amountIn,
        address[] calldata path
    ) external view returns (uint256[] memory amounts);
    
    function WETH() external view returns (address);
}
"
    }
  },
  "settings": {
    "remappings": [
      "solady/=lib/solady/src/",
      "permit2/=lib/permit2/",
      "@uniswap/v4-core/=lib/v4-core/",
      "@uniswap/v4-periphery/=lib/v4-periphery/",
      "v4-router/=lib/v4-periphery/lib/v4-router/",
      "@ensdomains/=lib/v4-core/node_modules/@ensdomains/",
      "@openzeppelin/=lib/v4-core/lib/openzeppelin-contracts/",
      "ds-test/=lib/v4-core/lib/forge-std/lib/ds-test/src/",
      "erc4626-tests/=lib/v4-core/lib/openzeppelin-contracts/lib/erc4626-tests/",
      "forge-gas-snapshot/=lib/permit2/lib/forge-gas-snapshot/src/",
      "forge-std/=lib/forge-std/src/",
      "hardhat/=lib/v4-core/node_modules/hardhat/",
      "openzeppelin-contracts/=lib/v4-core/lib/openzeppelin-contracts/",
      "solmate/=lib/v4-core/lib/solmate/",
      "v4-core/=lib/v4-core/src/",
      "v4-periphery/=lib/v4-periphery/"
    ],
    "optimizer": {
      "enabled": true,
      "runs": 200
    },
    "metadata": {
      "useLiteralContent": false,
      "bytecodeHash": "ipfs",
      "appendCBOR": true
    },
    "outputSelection": {
      "*": {
        "*": [
          "evm.bytecode",
          "evm.deployedBytecode",
          "devdoc",
          "userdoc",
          "metadata",
          "abi"
        ]
      }
    },
    "evmVersion": "cancun",
    "viaIR": true
  }
}}

Tags:
DeFi, Swap, Liquidity, Factory, Oracle|addr:0x508fbc2c26c687ee4f6dbc208eb764de39a2db13|verified:true|block:23691411|tx:0x986a3406279b1a0f309f89d0f14b11a6fc7db850cae00100aa6f456cdb548a37|first_check:1761841931

Submitted on: 2025-10-30 17:32:13

Comments

Log in to comment.

No comments yet.