S Price: $0.830822 (-3.11%)

Contract Diff Checker

Contract Name:
Uptown

Contract Source Code:

// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.13;

import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
import "forge-std/console.sol";
import "./Quoter.sol";
import "./Qualifier.sol";

interface IRouter {
    function getAmountsOut(
        uint amountIn,
        address[] calldata path
    ) external view returns (uint[] memory amounts);

    function WETH() external pure returns (address);
}

contract Uptown is Initializable {
    uint256 constant ADAY = 1 days;

    uint256 public registrationFeeUSD;
    uint256 public prestigeRegistrationFeeUSD;
    uint256 classicIndex;
    uint256 traversalDept;
    uint256 public prestigeCount;
    uint256 maxLevel;
    address public admin;
    address miningWallet;
    mapping(uint256 => PlanConfig) public planConfigs;
    mapping(uint256 => AvalancheConfig) public avalancheConfigs;
    mapping(uint256 => User) public users;
    mapping(address => uint256[]) public userIds;

    mapping(uint256 => uint256) public userCountAt;
    mapping(uint256 => uint256) public prestigeLevelEarning;
    // @dev holds the total number of global downlines on each day
    uint256[] classicActivationDays;

    Quoter private ROUTER;
    Qualifier private qualifier;

    struct User {
        uint256 id;
        uint256 uplineId;
        uint256 referralCount;
        uint256 availableBalance;
        uint256 lastWithdrawalAt;
        uint256 prestigeLevel;
        uint256 avalancheLevel;
        address wallet;
        uint256 matrixUplineId;
        uint256[] referrals;
        uint256[] activationDays;
        mapping(address => bool) approvedAddresses;
        mapping(uint256 => uint256) recyclingCount;
        mapping(uint256 => uint256) levelEarningsCount;
        mapping(uint256 => uint256) referralCountAt;
        mapping(uint256 => uint256) prestigeLevelEarningsCount;
        mapping(uint256 => PrestigeMatrix) prestigeMatrices;
        mapping(uint256 => AvalancheMatrix) avalancheMatrices;
        mapping(uint256 => uint256) pendingAvalancheEarnings;
    }

    struct PlanConfig {
        uint256 directReferralRequirement;
        uint256 globalReferralRequirement;
        uint256 dailyEarnings;
        uint256 earningDays;
        uint256 maxRecycling;
        uint256 recyclingFee;
    }

    struct AvalancheConfig {
        uint256 price;
        uint256 g1SlotPayout;
        uint256 g2SlotPayout;
        uint256 miningPayout;
    }

    struct PrestigeMatrix {
        bool registered;
        uint256 uplineId;
        uint256 left;
        uint256 right;
    }

    struct AvalancheMatrix {
        bool registered;
        bool g1Paid;
        bool g2Paid;
        uint256 uplineId;
        uint256[] slots;
    }

    event NewUser(uint256 indexed userId, uint256 indexed uplineId);
    event Withdrawal(uint256 indexed userId, uint256 amount);
    event Recycle(uint256 indexed userId, uint256 level);
    event PrestigeLevelEarning(
        uint256 indexed userId,
        uint256 indexed downlineId,
        uint256 level,
        uint256 amount
    );
    event Deposit(uint256 indexed userId, uint256 amount);
    event MatrixPayout(
        uint256 indexed userId,
        uint256 indexed level,
        uint256 earnerId,
        uint256 amount
    );
    event NewLevel(uint256 indexed userId, uint256 level);
    event AvalanchePayout(
        uint256 indexed userId,
        uint256 payerId,
        uint256 level,
        uint256 amount
    );
    event WalletChanged(
        uint256 indexed userId,
        address oldWallet,
        address newWallet
    );

    function initialize(address _miningWallet) public initializer { }

    function configure(address _miningWallet) external  {
        require(admin == address(0), "Already configured");
        admin = msg.sender;
        miningWallet = _miningWallet;

        ROUTER = Quoter(0x60be6dC7052D37d4649503345FE8D0AcE2145c6C);
        qualifier = Qualifier(0x58Ca1A9169Af3a9ffB59166c578548011CC74c1A);
        registrationFeeUSD = 5e6;
        prestigeRegistrationFeeUSD = 5e6;
        traversalDept = 10;

        uint256 userId = 1;
        User storage user = users[userId];
        user.id = userId;
        user.uplineId = 0;
        user.wallet = msg.sender;
        user.prestigeLevel = 20;
        user.avalancheLevel = 20;
        user.lastWithdrawalAt = block.timestamp;
        for (uint256 i = 1; i <= 20; i++) {
            user.prestigeMatrices[i].registered = true;
        }

        for (uint256 i = 1; i <= 20; i++) {
            user.avalancheMatrices[i].registered = true;
        }

        userIds[msg.sender].push(userId);

        userCountAt[today()]++;

        emit NewUser(userId, 0);
        classicIndex = 1;

        configureStaterPlan();
        configurePrestige();
        configureAvalanche();
    }

    modifier onlyAdmin() {
        require(msg.sender == admin, "Only admin can call this function");
        _;
    }

    function totalUsers() public view returns (uint256) {
        return classicIndex;
    }

    function getGlobalReferralCount(
        uint256 userId
    ) public view returns (uint256) {
        return classicIndex - userId;
    }

    function getAccountsCount(address user) public view returns (uint256) {
        return userIds[user].length;
    }

    function getReferrals(
        uint256 userID,
        uint256 startIndex
    ) external view returns (uint256[20] memory) {
        uint256[20] memory ids;
        if (users[userID].referrals.length > startIndex) {
            for (uint256 i = 0; i < 10; i++) {
                if (i + startIndex >= users[userID].referrals.length) {
                    break;
                }
                ids[i] = users[userID].referrals[i + startIndex];
            }
        }
        return ids;
    }

    function getLevelConfig(
        uint256 level
    ) public view returns (PlanConfig memory) {
        return planConfigs[level];
    }

    function getAvalancheConfig(
        uint256 level
    ) public view returns (AvalancheConfig memory) {
        return avalancheConfigs[level];
    }

    function getUSDCToBNBAmount(
        uint256 usdcAmount
    ) public view returns (uint256) {
        return ROUTER.getUSDCToBNBAmount(usdcAmount);
    }

    function getRegistrationBnbAmount() public view returns (uint256) {
        return getUSDCToBNBAmount(registrationFeeUSD);
    }

    function getPrestigeRegistrationBnbAmount() public view returns (uint256) {
        return getUSDCToBNBAmount(prestigeRegistrationFeeUSD);
    }

    function getAvalancheSlotBnbAmount(
        uint256 level
    ) public view returns (uint256) {
        return getUSDCToBNBAmount(avalancheConfigs[level].price);
    }

    function beginOfDay(uint256 timestamp) public pure returns (uint256) {
        return timestamp - (timestamp % ADAY);
    }

    function today() public view returns (uint256) {
        return beginOfDay(block.timestamp);
    }

    function getUserLevelAt(
        uint256 userId,
        uint256 timestamp
    ) public view returns (uint256) {
        uint256 day = beginOfDay(timestamp);

        User storage user = users[userId];

        if (user.referrals.length == 0) {
            return 0;
        }

        uint256 globalIndex = userCountAt[day];
        for (uint256 i = classicActivationDays.length - 1; i >= 0; i--) {
            if (classicActivationDays[i] <= timestamp) {
                globalIndex = classicActivationDays[i];
                break;
            }
        }

        uint256 globalDownline = globalIndex - userId;

        uint256 directDownline = users[userId].referrals.length;
        for (uint256 i = user.activationDays.length - 1; i >= 0; i--) {
            if (user.activationDays[i] <= timestamp) {
                globalDownline = userCountAt[user.activationDays[i]];
                break;
            }
        }

        for (uint256 level = maxLevel; level >= 1; level--) {
            if (planConfigs[level].directReferralRequirement == 0) {
                continue;
            }
            if (
                directDownline >=
                planConfigs[level].directReferralRequirement &&
                globalDownline >= planConfigs[level].globalReferralRequirement
            ) {
                return level;
            }
        }

        return 0;
    }

    function getUserLevel(uint256 userId) public view returns (uint256) {
        return getUserLevelAt(userId, block.timestamp);
    }

    function currentRecycling(uint256 userId) public view returns (uint256) {
        return users[userId].recyclingCount[getUserLevel(userId)];
    }

    function isApprovedAddress(
        uint256 userId,
        address addressToCheck
    ) public view returns (bool) {
        return users[userId].approvedAddresses[addressToCheck];
    }

    function pendingEarnings(
        uint256 userId
    )
        public
        view
        returns (
            uint256 totalAmount,
            uint256[] memory daysInLevel,
            uint256[] memory levels
        )
    {
        User storage user = users[userId];
        totalAmount = user.availableBalance;

        if (beginOfDay(user.lastWithdrawalAt) == today()) {
            return (totalAmount, daysInLevel, levels);
        }

        // First, count how many level changes we'll have
        uint256 levelChanges = 0;
        uint256 lastLevel = 0;

        for (
            uint256 day = beginOfDay(user.lastWithdrawalAt + ADAY);
            day < today();
            day += ADAY
        ) {
            uint256 level = getUserLevelAt(userId, day);
            if (
                level == 0 ||
                user.levelEarningsCount[level] >= planConfigs[level].earningDays
            ) {
                continue;
            }
            if (lastLevel != level) {
                levelChanges++;
                lastLevel = level;
            }
        }

        // Initialize arrays with the correct size
        daysInLevel = new uint256[](levelChanges);
        levels = new uint256[](levelChanges);

        // If no level changes, just calculate total amount and return
        if (levelChanges == 0) {
            uint256 level = getUserLevelAt(userId, today());
            if (
                level > 0 &&
                user.levelEarningsCount[level] < planConfigs[level].earningDays
            ) {
                uint256 daysSinceLastWithdrawal = (today() -
                    beginOfDay(user.lastWithdrawalAt)) / ADAY;
                uint256 daysLeft = planConfigs[level].earningDays -
                    user.levelEarningsCount[level];

                if (daysSinceLastWithdrawal > daysLeft) {
                    daysSinceLastWithdrawal = daysLeft;
                }
                totalAmount +=
                    daysSinceLastWithdrawal *
                    planConfigs[level].dailyEarnings;
            }
            return (totalAmount, daysInLevel, levels);
        }

        // Reset variables for second pass
        uint256 currentLevel;
        uint256 daysCount;
        uint256 arrayIndex;

        for (
            uint256 day = beginOfDay(user.lastWithdrawalAt) + ADAY;
            day <= today();
            day += ADAY
        ) {
            uint256 level = getUserLevelAt(userId, day);

            if (level == 0) {
                continue;
            }

            if (level == currentLevel) {
                if (
                    user.levelEarningsCount[level] + daysCount <
                    planConfigs[level].earningDays
                ) {
                    totalAmount += planConfigs[level].dailyEarnings;
                    daysCount += 1;
                }
            } else {
                if (currentLevel != 0) {
                    daysInLevel[arrayIndex] = daysCount;
                    levels[arrayIndex] = currentLevel;
                    arrayIndex++;
                }
                currentLevel = level;
                daysCount = 0;
                if (
                    user.levelEarningsCount[level] <
                    planConfigs[level].earningDays
                ) {
                    totalAmount += planConfigs[level].dailyEarnings;
                    daysCount += 1;
                }
            }
        }

        // Store the last level's data if we have one
        if (currentLevel != 0 && arrayIndex < levelChanges) {
            daysInLevel[arrayIndex] = daysCount;
            levels[arrayIndex] = currentLevel;
        }

        currentLevel = getUserLevelAt(userId, today());
    }

    function withdrawableEarnings(
        uint256 userId
    ) public view returns (uint256) {
        (
            uint256 balance,
            uint256[] memory daysInLevel,
            uint256[] memory levels
        ) = pendingEarnings(userId);
        uint256 level = getUserLevel(userId);
        User storage user = users[userId];
        uint256 levelEarnings = planConfigs[level].dailyEarnings *
            (user.levelEarningsCount[level] +
                planConfigs[level].earningDays *
                user.recyclingCount[level]);

        for (uint256 i = 0; i < daysInLevel.length; i++) {
            if (levels[i] != level) {
                continue;
            }
            levelEarnings +=
                daysInLevel[i] *
                planConfigs[levels[i]].dailyEarnings;
        }

        if (balance <= levelEarnings) {
            return 0;
        }
        return balance; // - levelEarnings;
    }

    function getCanRecycle(uint256 userId) public view returns (bool) {
        User storage user = users[userId];
        (uint256 balance, , ) = pendingEarnings(userId);
        return
            balance >= planConfigs[getUserLevel(userId)].recyclingFee &&
            user.recyclingCount[getUserLevel(userId)] <
            planConfigs[getUserLevel(userId)].maxRecycling;
    }

    function canWithdraw(uint256 userId) public view returns (bool) {
        User storage user = users[userId];
        uint256 balance = withdrawableEarnings(userId);
        if (balance < 0) {
            return false;
        }

        uint256 level = getUserLevel(userId);

        if (
            level > 1 &&
            user.prestigeLevel > 0 &&
            user.avalancheLevel > 0 &&
            qualifier.canUserWithdraw(userId, level)
        ) {
            return true;
        }
        return false;
    }

    function getPrestigeMatrix(
        uint256 userId,
        uint256 level
    )
        public
        view
        returns (
            uint256 upline,
            uint256 left,
            uint256 leftLevel,
            uint256 right,
            uint256 rightLevel
        )
    {
        upline = users[userId].prestigeMatrices[level].uplineId;
        left = users[userId].prestigeMatrices[level].left;
        right = users[userId].prestigeMatrices[level].right;
        leftLevel = users[left].prestigeLevel;
        rightLevel = users[right].prestigeLevel;
    }

    function getAvalancheMatrix(
        uint256 userId,
        uint256 level
    )
        public
        view
        returns (
            uint256 upline,
            uint256 slot1,
            uint256 slot2,
            uint256 slot3,
            uint256 slot4
        )
    {
        User storage user = users[userId];
        if (!user.avalancheMatrices[level].registered) {
            return (0, 0, 0, 0, 0);
        }
        upline = user.avalancheMatrices[level].uplineId;
        if (user.avalancheMatrices[level].slots.length == 0) {
            return (upline, 0, 0, 0, 0);
        }
        slot1 = user.avalancheMatrices[level].slots[0];
        if (user.avalancheMatrices[level].slots.length == 1) {
            return (upline, slot1, 0, 0, 0);
        }
        slot2 = user.avalancheMatrices[level].slots[1];
        if (user.avalancheMatrices[level].slots.length == 2) {
            return (upline, slot1, slot2, 0, 0);
        }
        slot3 = user.avalancheMatrices[level].slots[2];
        if (user.avalancheMatrices[level].slots.length == 3) {
            return (upline, slot1, slot2, slot3, 0);
        }
        slot4 = user.avalancheMatrices[level].slots[3];

        return (upline, slot1, slot2, slot3, slot4);
    }

    function hasEmptyPrestigeSlot(
        uint256 userId,
        uint256 level
    ) private view returns (bool) {
        return
            users[userId].prestigeMatrices[level].right == 0 ||
            users[userId].prestigeMatrices[level].left == 0;
    }

    function hasEmptyLegs(
        uint256 userId,
        uint256 level
    ) public view returns (bool) {
        return
            users[userId].prestigeMatrices[level].left == 0 ||
            users[userId].prestigeMatrices[level].right == 0;
    }

    function isADownline(
        uint256 uplineId,
        uint256 userId,
        uint256 generation
    ) public view returns (bool) {
        for (uint256 i = 0; i < generation; i++) {
            if (users[userId].uplineId == uplineId) {
                return true;
            }
            userId = users[userId].uplineId;
            if (userId == 0) {
                return false;
            }
        }
        return false;
    }

    function firstPrestigeAncestor(
        uint256 userId,
        uint256 searchDepth
    ) public view returns (uint256) {
        uint256 uplineId = users[userId].uplineId;
        while (uplineId != 0 && searchDepth > 0) {
            if (users[uplineId].prestigeLevel > 0) {
                return uplineId;
            }
            uplineId = users[uplineId].uplineId;
            searchDepth--;
        }
        return 1;
    }

    function getAvailableUplineInMatrix(
        uint256 uplineID,
        uint256 level,
        bool traverseDown,
        uint256 random
    ) public view returns (uint256) {
        require(uplineID > 0, "ZU");
        require(users[uplineID].prestigeMatrices[level].registered, "UNIP");

        if (hasEmptyLegs(uplineID, level)) {
            return uplineID;
        }

        uint256 arraySize = ((2 ** traversalDept) - 1);
        uint256 previousLineSize = ((2 ** (traversalDept - 1)) - 1);
        
        uint256[] memory referrals = new uint256[](arraySize);
        referrals[0] = users[uplineID].prestigeMatrices[level].left;
        referrals[1] = users[uplineID].prestigeMatrices[level].right;

        uint256 referrer;

        for (uint256 i = 0; i < arraySize; i++) {
            if (hasEmptyLegs(referrals[i], level)) {
                referrer = referrals[i];
                break;
            }

            if (i < previousLineSize) {
                referrals[(i + 1) * 2] = users[referrals[i]]
                    .prestigeMatrices[level]
                    .left;
                referrals[(i + 1) * 2 + 1] = users[referrals[i]]
                    .prestigeMatrices[level]
                    .right;
            }
        }

        if (referrer == 0 && traverseDown) {
            if (random < previousLineSize) {
                random = random + previousLineSize;
            }
            if (random > arraySize) {
                random = arraySize % random;
            }
            referrer = getAvailableUplineInMatrix(
                referrals[random],
                level,
                false,
                random
            );

            if (referrer == 0) {
                for (uint256 i = previousLineSize; i < arraySize; i++) {
                    referrer = getAvailableUplineInMatrix(
                        referrals[i],
                        level,
                        false,
                        random
                    );
                    if (referrer != 0) {
                        break;
                    }
                }
                require(referrer > 0, "RNF");
            }
        }

        return referrer;
    }

    function getNextAvailableAvalencheSlot(
        uint256 uplineID,
        uint256 level,
        bool traverseDown,
        uint256 random
    ) internal view returns (uint256) {
        require(uplineID > 0, "ZU");

        if (users[uplineID].avalancheMatrices[level].slots.length < 4) {
            return uplineID;
        }

        uint256 arraySize = ((4 ** 5) - 1) / 3;
        uint256 previousLineSize = ((4 ** (5 - 1)) - 1) / 3;
        uint256[] memory referrals = new uint256[](arraySize);
        referrals[0] = users[uplineID].avalancheMatrices[level].slots[0];
        referrals[1] = users[uplineID].avalancheMatrices[level].slots[1];
        referrals[2] = users[uplineID].avalancheMatrices[level].slots[2];
        referrals[3] = users[uplineID].avalancheMatrices[level].slots[3];

        uint256 referrer;

        for (uint256 i = 0; i < arraySize; i++) {
            if (users[referrals[i]].avalancheMatrices[level].slots.length < 4) {
                referrer = referrals[i];
                break;
            }

            if (i < previousLineSize) {
                referrals[(i + 1) * 4] = users[referrals[i]]
                    .avalancheMatrices[level]
                    .slots[0];
                referrals[(i + 1) * 4 + 1] = users[referrals[i]]
                    .avalancheMatrices[level]
                    .slots[1];
                referrals[(i + 1) * 4 + 2] = users[referrals[i]]
                    .avalancheMatrices[level]
                    .slots[2];
                referrals[(i + 1) * 4 + 3] = users[referrals[i]]
                    .avalancheMatrices[level]
                    .slots[3];
            }
        }

        if (referrer == 0 && traverseDown) {
            if (random < previousLineSize) {
                random = random + previousLineSize;
            }
            if (random > arraySize) {
                random = arraySize % random;
            }
            referrer = getAvailableUplineInMatrix(
                referrals[random],
                level,
                false,
                random
            );

            if (referrer == 0) {
                for (uint256 i = previousLineSize; i < arraySize; i++) {
                    referrer = getAvailableUplineInMatrix(
                        referrals[random],
                        level,
                        false,
                        random
                    );
                    if (referrer != 0) {
                        break;
                    }
                }
                require(referrer > 0, "RNF");
            }
        }

        return referrer;
    }

    function pendingAvalancheEarning(
        uint256 userId,
        uint256 level
    ) public view returns (uint256) {
        return users[userId].pendingAvalancheEarnings[level];
    }

    function setRegistrationFee(
        uint256 _registrationFeeUSD
    ) external onlyAdmin {
        registrationFeeUSD = _registrationFeeUSD;
    }

    function setPrestigeRegistrationFee(
        uint256 _prestigeRegistrationFeeUSD
    ) external onlyAdmin {
        prestigeRegistrationFeeUSD = _prestigeRegistrationFeeUSD;
    }

    function setPrestigeLevelEarning(uint256 level, uint256 earning) internal {
        prestigeLevelEarning[level] = earning;
    }

    function setTraversalDept(uint256 _traversalDept) external onlyAdmin {
        traversalDept = _traversalDept;
    }

    function setAdmin(address newAdmin) external onlyAdmin {
        admin = newAdmin;
    }

    function setMiningWallet(address _miningWallet) external onlyAdmin {
        miningWallet = _miningWallet;
    }

    function setSwapRouter(address _router) external onlyAdmin {
        ROUTER = Quoter(_router);
    }

    function setQualifier(address _qualifier) external onlyAdmin {
        qualifier = Qualifier(_qualifier);
    }

    function setLevelConfig(
        uint256 level,
        uint256 directReferralRequirement,
        uint256 globalReferralRequirement,
        uint256 dailyEarnings,
        uint256 earningDays,
        uint256 maxRecycling,
        uint256 recyclingFee
    ) internal {
        planConfigs[level] = PlanConfig({
            directReferralRequirement: directReferralRequirement,
            globalReferralRequirement: globalReferralRequirement,
            dailyEarnings: dailyEarnings,
            earningDays: earningDays,
            maxRecycling: maxRecycling,
            recyclingFee: recyclingFee
        });
        if (level > maxLevel) {
            maxLevel = level;
        }
    }

    function configureStaterPlan() internal {
        setLevelConfig(1, 4, 40, 25e4, 40, 4, 5e6);
        setLevelConfig(2, 6, 150, 45e4, 40, 3, 0);
        setLevelConfig(3, 8, 1000, 6e5, 40, 3, 0);
        setLevelConfig(4, 10, 5000, 75e4, 40, 3, 0);
        setLevelConfig(5, 12, 15000, 95e4, 40, 3, 0);
        setLevelConfig(6, 14, 35000, 125e4, 40, 3, 0);
        setLevelConfig(7, 16, 55000, 150e4, 40, 3, 0);
        setLevelConfig(8, 18, 100000, 185e4, 40, 3, 0);
        setLevelConfig(9, 20, 500000, 19e5, 40, 3, 0);
        setLevelConfig(10, 22, 750000, 22e5, 40, 3, 0);
        setLevelConfig(11, 24, 1000000, 255e4, 40, 3, 0);
        setLevelConfig(12, 26, 1500000, 285e4, 40, 3, 0);
        setLevelConfig(13, 28, 2500000, 315e4, 40, 3, 0);
        setLevelConfig(14, 30, 3500000, 35e5, 40, 3, 0);
        setLevelConfig(15, 32, 5000000, 399e5, 40, 3, 0);
        setLevelConfig(16, 34, 15000000, 44e5, 40, 3, 0);
        setLevelConfig(17, 36, 50000000, 5e6, 40, 3, 0);
        setLevelConfig(18, 38, 150000000, 65e5, 40, 3, 0);
        setLevelConfig(19, 40, 300000000, 75e5, 40, 3, 0);
        setLevelConfig(20, 42, 500000000, 1e7, 40, 3, 0);
    }

    function configureAvalanche() internal {
        uint256[] memory prices = new uint256[](20);
        prices[0] = 5e6;
        prices[1] = 75e5;
        prices[2] = 1125e4;
        prices[3] = 16875e3;
        prices[4] = 253125e2;
        prices[5] = 3796875e1;
        prices[6] = 56953125;
        prices[7] = 854296875;
        prices[8] = 1281445313;
        prices[9] = 1922167969;
        prices[10] = 288325195;
        prices[11] = 432487793;
        prices[12] = 648731689;
        prices[13] = 973097534;
        prices[14] = 1459646301;
        prices[15] = 2189469452;
        prices[16] = 3284204178;
        prices[17] = 4926306267;
        prices[18] = 7389459400;
        prices[19] = 11084189100;

        for (uint256 i = 0; i < prices.length; i++) {
            avalancheConfigs[i + 1] = AvalancheConfig({
                price: prices[i],
                g1SlotPayout: (prices[i] * 375) / 1000,
                g2SlotPayout: (prices[i] * 375) / 1000,
                miningPayout: (prices[i] * 250) / 1000
            });
        }
    }

    function configurePrestige() internal {
        setPrestigeLevelEarning(1, 25e5);
        setPrestigeLevelEarning(2, 5e6);
        setPrestigeLevelEarning(3, 1e7);
        setPrestigeLevelEarning(4, 2e7);
        setPrestigeLevelEarning(5, 4e7);
        setPrestigeLevelEarning(6, 8e7);
        setPrestigeLevelEarning(7, 16e7);
        setPrestigeLevelEarning(8, 32e7);
        setPrestigeLevelEarning(9, 64e7);
        setPrestigeLevelEarning(10, 128e7);
        setPrestigeLevelEarning(11, 256e7);
        setPrestigeLevelEarning(12, 512e7);
        setPrestigeLevelEarning(13, 1024e7);
        setPrestigeLevelEarning(14, 2048e7);
        setPrestigeLevelEarning(15, 4096e7);
        setPrestigeLevelEarning(16, 8192e7);
        setPrestigeLevelEarning(17, 16384e7);
        setPrestigeLevelEarning(18, 32768e7);
        setPrestigeLevelEarning(19, 65536e7);
        setPrestigeLevelEarning(20, 131072e7);
    }

    function deposit(uint256 userId) external payable {
        require(msg.value > 0, "Invalid amount");
        uint256 amount = getUSDCToBNBAmount(msg.value);
        users[userId].availableBalance += amount;
        emit Deposit(userId, amount);
    }

    function withdrawEarnings(uint256 userId) external {
        require(
            msg.sender == users[userId].wallet ||
                isApprovedAddress(userId, msg.sender),
            "Access denied"
        );
        require(withdrawableEarnings(userId) > 0, "No withdrawable earnings");
        require(canWithdraw(userId), "Cannot withdraw");

        harvestEarnings(userId);
        require(users[userId].availableBalance > 0, "No available balance");
        uint256 amount = users[userId].availableBalance;
        users[userId].availableBalance = 0;
        uint256 ethAmount = getUSDCToBNBAmount(amount);

        payable(msg.sender).transfer(ethAmount);

        emit Withdrawal(userId, amount);
    }

    function registerUser(
        uint256 uplineId,
        uint256 matrixUplineId,
        address addr
    ) public payable {
        require(registrationFeeUSD > 0, "Registration fee not set");

        require(
            matrixUplineId == 0 ||
                (users[matrixUplineId].prestigeLevel > 0 &&
                    users[matrixUplineId].avalancheLevel > 0),
            "Invalid matrix upline ID"
        );

        uint256 price = getUSDCToBNBAmount(registrationFeeUSD);
        require(msg.value >= price, "Invalid registration fee");

        _registerUser(uplineId, matrixUplineId, addr);
        if (msg.value > price) {
            payable(msg.sender).transfer(msg.value - price);
        }
    }

    function _registerUser(
        uint256 uplineId,
        uint256 matrixUplineId,
        address addr
    ) internal {
        require(uplineId > 0 && uplineId <= classicIndex, "Invalid upline ID");

        classicIndex++;
        uint256 userId = classicIndex;

        User storage user = users[userId];
        user.id = userId;
        user.uplineId = uplineId;
        user.matrixUplineId = matrixUplineId;
        user.wallet = addr;
        user.lastWithdrawalAt = block.timestamp;
        userIds[addr].push(userId);

        uint256 _today = today();
        userCountAt[_today] = classicIndex;

        users[uplineId].referrals.push(userId);
        users[uplineId].referralCount++;
        users[uplineId].referralCountAt[_today]++;

        if (users[uplineId].activationDays.length == 0) {
            users[uplineId].activationDays.push(_today);
        } else if (
            users[uplineId].activationDays[
                users[uplineId].activationDays.length - 1
            ] != today()
        ) {
            users[uplineId].activationDays.push(_today);
        }

        if (classicActivationDays.length == 0) {
            classicActivationDays.push(_today);
        } else if (
            classicActivationDays[classicActivationDays.length - 1] != _today
        ) {
            classicActivationDays.push(_today);
        }

        emit NewUser(userId, uplineId);
    }

    function setApprovedAddress(
        uint256 userId,
        address addressToApprove,
        bool approved
    ) public {
        require(msg.sender == users[userId].wallet, "Access denied");
        users[userId].approvedAddresses[addressToApprove] = approved;
    }

    function changeWallet(uint256 userId, address newWallet) external {
        require(
            msg.sender == users[userId].wallet,
            "Only user can change wallet"
        );
        for (uint256 i = 0; i < userIds[users[userId].wallet].length; i++) {
            if (userIds[users[userId].wallet][i] == userId) {
                userIds[users[userId].wallet][i] = userIds[
                    users[userId].wallet
                ][userIds[users[userId].wallet].length - 1];
                userIds[users[userId].wallet].pop();
                break;
            }
        }
        userIds[newWallet].push(userId);
        users[userId].wallet = newWallet;
        emit WalletChanged(userId, msg.sender, newWallet);
    }

    function registerMultipleAccounts(
        uint256 uplineID,
        uint256 matrixUplineId,
        address addr,
        uint256 no
    ) external payable {
        require(no <= 50, "TOO_MANY");
        uint256 price = getUSDCToBNBAmount(registrationFeeUSD);
        require(msg.value >= price * no, "Invalid registration fee");

        for (uint256 i = 0; i < no; i++) {
            _registerUser(uplineID, matrixUplineId, addr);
        }

        if (msg.value > price * no) {
            payable(msg.sender).transfer(msg.value - price * no);
        }
    }

    function recycle(uint256 userId) external {
        require(msg.sender == users[userId].wallet, "Access denied");
        require(getCanRecycle(userId), "Cannot recycle");
        User storage user = users[userId];
        uint256 level = getUserLevel(userId);
        harvestEarnings(userId);
        user.availableBalance -= planConfigs[level].recyclingFee;
        user.recyclingCount[level] += 1;
        user.levelEarningsCount[level] = 0;
        emit Recycle(userId, level);
    }

    function harvestEarnings(uint256 userId) private {
        (
            uint256 totalAmount,
            uint256[] memory daysInLevel,
            uint256[] memory levels
        ) = pendingEarnings(userId);
        if (totalAmount == 0) {
            return;
        }

        users[userId].availableBalance += totalAmount;
        users[userId].lastWithdrawalAt = block.timestamp;

        User storage user = users[userId];
        for (uint256 i = 0; i < levels.length; i++) {
            user.levelEarningsCount[levels[i]] += daysInLevel[i];
        }
    }

    function registerPrestigeUser(
        uint256 userId,
        uint256 uplineId,
        uint256 random
    ) external payable {
        require(
            prestigeRegistrationFeeUSD > 0,
            "Prestige registration fee not set"
        );
        require(userId > 0 && userId <= classicIndex, "Invalid user ID");
        require(uplineId >= 0 && uplineId <= classicIndex, "Invalid upline ID");
        require(uplineId != userId, "Upline cannot be the same as user");

        if (uplineId == 0) {
            uplineId = firstPrestigeAncestor(userId, 10);
        }

        User storage user = users[userId];
        harvestEarnings(userId);
        uint256 priceEth = getUSDCToBNBAmount(prestigeRegistrationFeeUSD);
        require(
            user.availableBalance >= prestigeRegistrationFeeUSD ||
                msg.value >= priceEth,
            "Insufficient balance"
        );

        require(user.prestigeLevel == 0, "User already in prestige plan");

        user.prestigeLevel = 1;
        if (msg.value == 0) {
            user.availableBalance -= prestigeRegistrationFeeUSD;
        }

        uint256 matrixUpline = getAvailableUplineInMatrix(
            uplineId,
            1,
            true,
            random
        );
        user.prestigeMatrices[1].registered = true;
        user.prestigeMatrices[1].uplineId = matrixUpline;
        user.prestigeLevel = 1;

        if (users[matrixUpline].prestigeMatrices[1].left == 0) {
            users[matrixUpline].prestigeMatrices[1].left = userId;
        } else {
            users[matrixUpline].prestigeMatrices[1].right = userId;
        }

        uint256 earnerId = sendMatrixPayout(userId, 1);

        if (hasCompletedLevel(earnerId, 1)) {
            moveToNextLevel(earnerId, random);
        }

        if (msg.value > priceEth) {
            payable(msg.sender).transfer(msg.value - priceEth);
        }

        emit NewLevel(userId, 1);
    }

    function hasCompletedLevel(uint256 userId, uint256 level) internal view returns (bool) {
        return users[userId].prestigeLevelEarningsCount[level] == 4;
    }

    function moveToNextLevel(uint256 userID, uint256 random) internal {
        if (userID == 1) return;
        User storage user = users[userID];
        uint256 newLevel = user.prestigeLevel + 1;
        require(newLevel >= 1, "Invalid level");
        user.prestigeLevel = newLevel;

        uint256 matrixUpline = getAvailableUplineInMatrix(
            user.prestigeMatrices[newLevel - 1].uplineId,
            newLevel,
            true,
            random
        );

        user.prestigeMatrices[newLevel].registered = true;
        user.prestigeMatrices[newLevel].uplineId = matrixUpline;

        if (users[matrixUpline].prestigeMatrices[newLevel].left == 0) {
            users[matrixUpline].prestigeMatrices[newLevel].left = userID;
        } else {
            users[matrixUpline].prestigeMatrices[newLevel].right = userID;
        }

        uint256 earnerId = sendMatrixPayout(userID, newLevel);

        if (hasCompletedLevel(earnerId, newLevel)) {
            moveToNextLevel(earnerId, random);
        }

        emit NewLevel(userID, newLevel);
    }

    function sendMatrixPayout(uint256 userId, uint256 level) internal returns(uint256) {
        uint256 payout = prestigeLevelEarning[level];

        uint256 directUpline = users[userId].prestigeMatrices[level].uplineId;
        if (directUpline == 0) {
            return 0;
        }
        uint256 earnerId = users[directUpline].prestigeMatrices[level].uplineId;
        if (earnerId == 0) {
            return 0;
        }
        User storage earner = users[earnerId];
        if (earner.prestigeLevelEarningsCount[level] >= 3) {
            payable(miningWallet).transfer(getUSDCToBNBAmount(payout));
        } else {
            payable(earner.wallet).transfer(getUSDCToBNBAmount(payout));
        }
        earner.prestigeLevelEarningsCount[level] += 1;

        emit MatrixPayout(userId, level, earnerId, payout);

        return earnerId;
    }

    function addToAvalancheSlot(
        uint256 userId,
        uint256 level,
        uint256 uplineId,
        uint256 random,
        bool isManualPurchase
    ) internal {
        User storage user = users[userId];
        require(
            level == user.avalancheLevel + 1,
            "Account not qualified for this level"
        );

        user.avalancheLevel = level;

        uint256 matrixUpline = getNextAvailableAvalencheSlot(
            uplineId,
            level,
            true,
            random
        );


        user.avalancheMatrices[level].uplineId = matrixUpline;
        user.avalancheMatrices[level].registered = true;

        users[matrixUpline].avalancheMatrices[level].slots.push(userId);
        
        if (level == 1) {
            if (users[matrixUpline].avalancheMatrices[level].registered) {
                sendAvalanchePayout(userId, level, true);
            }
            if (user.avalancheMatrices[level].slots.length > 0) {
                for (
                    uint256 i = 0;
                    i < user.avalancheMatrices[level].slots.length;
                    i++
                ) {
                    sendAvalanchePayout(
                        user.avalancheMatrices[level].slots[i],
                        level,
                        true
                    );
                }
            }
        } else {
            if (isManualPurchase) {
                sendAvalanchePayoutForManualPurchase(userId, level);
            } else {
                sendAvalanchePayout(
                    userId,
                    level,
                    level < 20 ||
                        !users[matrixUpline]
                            .avalancheMatrices[level + 1]
                            .registered
                );
            }
        }

        if (users[matrixUpline].avalancheMatrices[level].slots.length == 4) {
            moveToNextAvalancheLevel(matrixUpline, random);
        }
    }

    function buyAvalancheSlot(
        uint256 userId,
        uint256 level,
        uint256 uplineId,
        uint256 random
    ) external payable {
        require(
            avalancheConfigs[level].price > 0,
            "Avalanche registration fee not set"
        );
        require(userId > 0 && userId <= classicIndex, "Invalid user ID");
        require(
            uplineId == 0 ||
                uplineId == users[userId].uplineId ||
                (users[uplineId].avalancheLevel > 0 &&
                    isADownline(uplineId, userId, 10)),
            "Cannot use this upline ID"
        );

        (uint256 pendingEarningsAmount, , ) = pendingEarnings(userId);
        uint256 price = getUSDCToBNBAmount(avalancheConfigs[level].price);
        require(
            msg.value >= price || pendingEarningsAmount >= price,
            "Invalid registration fee"
        );

        require(level > 0 && level <= 20, "Invalid level");

        User storage user = users[userId];
        require(user.avalancheLevel == level - 1, "Cannot buy this level");

        if (uplineId == 0) {
            uplineId = user.uplineId;
        }

        if (msg.value == 0) {
            harvestEarnings(userId);
            require(
                user.availableBalance >= avalancheConfigs[level].price,
                "Insufficient balance"
            );
            user.availableBalance -= avalancheConfigs[level].price;
        }

        addToAvalancheSlot(userId, level, uplineId, random, level > 1);

        if (msg.value > price) {
            payable(msg.sender).transfer(msg.value - price);
        }
    }

    function sendAvalanchePayout(
        uint256 userId,
        uint256 level,
        bool payG2
    ) public {
        require(
            users[userId].avalancheMatrices[level].registered,
            "User not registered in this level"
        );

        User storage user = users[userId];

        // TODO: if upline already paid, mark g2Paid as true and send payout to upline
        if (
            !user.avalancheMatrices[level].g1Paid &&
            !user.avalancheMatrices[level].g2Paid
        ) {
            payable(miningWallet).transfer(
                getUSDCToBNBAmount(avalancheConfigs[level].miningPayout)
            );
        }

        if (user.avalancheMatrices[level].uplineId == 0) {
            return;
        }
        User storage g1Upline = users[user.avalancheMatrices[level].uplineId];
        if (!user.avalancheMatrices[level].g1Paid) {
            uint256 l1Amount = avalancheConfigs[level].g1SlotPayout;
            if (!payG2 && !user.avalancheMatrices[level].g2Paid) {
                l1Amount += avalancheConfigs[level].g2SlotPayout;
                user.avalancheMatrices[level].g2Paid = true;
            }
            if (g1Upline.avalancheLevel >= level) {
                payable(g1Upline.wallet).transfer(getUSDCToBNBAmount(l1Amount));
            } else {
                g1Upline.pendingAvalancheEarnings[level] += l1Amount;
            }
            user.avalancheMatrices[level].g1Paid = true;
            emit AvalanchePayout(g1Upline.id, userId, level, l1Amount);
        }

        if (g1Upline.avalancheMatrices[level].uplineId == 0) {
            return;
        }
        User storage g2Upline = users[
            g1Upline.avalancheMatrices[level].uplineId
        ];
        if (!user.avalancheMatrices[level].g2Paid && payG2) {
            if (g2Upline.avalancheLevel >= level) {
                payable(g2Upline.wallet).transfer(
                    getUSDCToBNBAmount(avalancheConfigs[level].g2SlotPayout)
                );
            } else {
                g2Upline.pendingAvalancheEarnings[level] += avalancheConfigs[
                    level
                ].g2SlotPayout;
            }
            user.avalancheMatrices[level].g2Paid = true;
            emit AvalanchePayout(
                g2Upline.id,
                userId,
                level,
                avalancheConfigs[level].g2SlotPayout
            );
        }
    }

    function sendAvalanchePayoutForManualPurchase(
        uint256 userId,
        uint256 level
    ) internal {
        require(
            users[userId].avalancheMatrices[level].registered,
            "User not registered in this level"
        );

        require(
            level > 1,
            "Manual purchase is only available for level 2 and above"
        );

        User storage user = users[userId];

        // TODO: if upline already paid, mark g2Paid as true and send payout to upline
        if (
            !user.avalancheMatrices[level].g1Paid &&
            !user.avalancheMatrices[level].g2Paid
        ) {
            payable(miningWallet).transfer(
                getUSDCToBNBAmount(avalancheConfigs[level - 1].miningPayout * 4)
            );
        }

        if (user.avalancheMatrices[level - 1].uplineId == 0) {
            return;
        }

        uint256 leg0UplineEarnings = avalancheConfigs[level - 1].g2SlotPayout *
            4;
        payable(users[user.avalancheMatrices[level - 1].uplineId].wallet)
            .transfer(getUSDCToBNBAmount(leg0UplineEarnings));
    }

    function moveToNextAvalancheLevel(uint256 userID, uint256 random) internal {
        if (userID == 1) return;
        User storage user = users[userID];
        uint256 newLevel = user.avalancheLevel + 1;
        uint256 uplineId = user.avalancheMatrices[1].uplineId;

        if (
            !users[uplineId].avalancheMatrices[newLevel].registered &&
            uplineId != user.uplineId
        ) {
            uplineId = user.uplineId;
        }

        addToAvalancheSlot(userID, newLevel, uplineId, random, false);
    }
}

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.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 reininitialization) 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 Returns a pointer to the storage namespace.
     */
    // solhint-disable-next-line var-name-mixedcase
    function _getInitializableStorage() private pure returns (InitializableStorage storage $) {
        assembly {
            $.slot := INITIALIZABLE_STORAGE
        }
    }
}

// SPDX-License-Identifier: MIT
pragma solidity >=0.4.22 <0.9.0;

library console {
    address constant CONSOLE_ADDRESS =
        0x000000000000000000636F6e736F6c652e6c6f67;

    function _sendLogPayloadImplementation(bytes memory payload) internal view {
        address consoleAddress = CONSOLE_ADDRESS;
        /// @solidity memory-safe-assembly
        assembly {
            pop(
                staticcall(
                    gas(),
                    consoleAddress,
                    add(payload, 32),
                    mload(payload),
                    0,
                    0
                )
            )
        }
    }

    function _castToPure(
      function(bytes memory) internal view fnIn
    ) internal pure returns (function(bytes memory) pure fnOut) {
        assembly {
            fnOut := fnIn
        }
    }

    function _sendLogPayload(bytes memory payload) internal pure {
        _castToPure(_sendLogPayloadImplementation)(payload);
    }

    function log() internal pure {
        _sendLogPayload(abi.encodeWithSignature("log()"));
    }

    function logInt(int256 p0) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(int256)", p0));
    }

    function logUint(uint256 p0) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(uint256)", p0));
    }

    function logString(string memory p0) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(string)", p0));
    }

    function logBool(bool p0) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(bool)", p0));
    }

    function logAddress(address p0) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(address)", p0));
    }

    function logBytes(bytes memory p0) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(bytes)", p0));
    }

    function logBytes1(bytes1 p0) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(bytes1)", p0));
    }

    function logBytes2(bytes2 p0) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(bytes2)", p0));
    }

    function logBytes3(bytes3 p0) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(bytes3)", p0));
    }

    function logBytes4(bytes4 p0) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(bytes4)", p0));
    }

    function logBytes5(bytes5 p0) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(bytes5)", p0));
    }

    function logBytes6(bytes6 p0) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(bytes6)", p0));
    }

    function logBytes7(bytes7 p0) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(bytes7)", p0));
    }

    function logBytes8(bytes8 p0) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(bytes8)", p0));
    }

    function logBytes9(bytes9 p0) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(bytes9)", p0));
    }

    function logBytes10(bytes10 p0) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(bytes10)", p0));
    }

    function logBytes11(bytes11 p0) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(bytes11)", p0));
    }

    function logBytes12(bytes12 p0) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(bytes12)", p0));
    }

    function logBytes13(bytes13 p0) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(bytes13)", p0));
    }

    function logBytes14(bytes14 p0) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(bytes14)", p0));
    }

    function logBytes15(bytes15 p0) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(bytes15)", p0));
    }

    function logBytes16(bytes16 p0) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(bytes16)", p0));
    }

    function logBytes17(bytes17 p0) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(bytes17)", p0));
    }

    function logBytes18(bytes18 p0) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(bytes18)", p0));
    }

    function logBytes19(bytes19 p0) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(bytes19)", p0));
    }

    function logBytes20(bytes20 p0) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(bytes20)", p0));
    }

    function logBytes21(bytes21 p0) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(bytes21)", p0));
    }

    function logBytes22(bytes22 p0) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(bytes22)", p0));
    }

    function logBytes23(bytes23 p0) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(bytes23)", p0));
    }

    function logBytes24(bytes24 p0) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(bytes24)", p0));
    }

    function logBytes25(bytes25 p0) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(bytes25)", p0));
    }

    function logBytes26(bytes26 p0) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(bytes26)", p0));
    }

    function logBytes27(bytes27 p0) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(bytes27)", p0));
    }

    function logBytes28(bytes28 p0) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(bytes28)", p0));
    }

    function logBytes29(bytes29 p0) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(bytes29)", p0));
    }

    function logBytes30(bytes30 p0) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(bytes30)", p0));
    }

    function logBytes31(bytes31 p0) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(bytes31)", p0));
    }

    function logBytes32(bytes32 p0) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(bytes32)", p0));
    }

    function log(uint256 p0) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(uint256)", p0));
    }

    function log(int256 p0) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(int256)", p0));
    }

    function log(string memory p0) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(string)", p0));
    }

    function log(bool p0) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(bool)", p0));
    }

    function log(address p0) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(address)", p0));
    }

    function log(uint256 p0, uint256 p1) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256)", p0, p1));
    }

    function log(uint256 p0, string memory p1) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(uint256,string)", p0, p1));
    }

    function log(uint256 p0, bool p1) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(uint256,bool)", p0, p1));
    }

    function log(uint256 p0, address p1) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(uint256,address)", p0, p1));
    }

    function log(string memory p0, uint256 p1) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(string,uint256)", p0, p1));
    }

    function log(string memory p0, int256 p1) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(string,int256)", p0, p1));
    }

    function log(string memory p0, string memory p1) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(string,string)", p0, p1));
    }

    function log(string memory p0, bool p1) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(string,bool)", p0, p1));
    }

    function log(string memory p0, address p1) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(string,address)", p0, p1));
    }

    function log(bool p0, uint256 p1) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(bool,uint256)", p0, p1));
    }

    function log(bool p0, string memory p1) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(bool,string)", p0, p1));
    }

    function log(bool p0, bool p1) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(bool,bool)", p0, p1));
    }

    function log(bool p0, address p1) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(bool,address)", p0, p1));
    }

    function log(address p0, uint256 p1) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(address,uint256)", p0, p1));
    }

    function log(address p0, string memory p1) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(address,string)", p0, p1));
    }

    function log(address p0, bool p1) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(address,bool)", p0, p1));
    }

    function log(address p0, address p1) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(address,address)", p0, p1));
    }

    function log(uint256 p0, uint256 p1, uint256 p2) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,uint256)", p0, p1, p2));
    }

    function log(uint256 p0, uint256 p1, string memory p2) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,string)", p0, p1, p2));
    }

    function log(uint256 p0, uint256 p1, bool p2) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,bool)", p0, p1, p2));
    }

    function log(uint256 p0, uint256 p1, address p2) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,address)", p0, p1, p2));
    }

    function log(uint256 p0, string memory p1, uint256 p2) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(uint256,string,uint256)", p0, p1, p2));
    }

    function log(uint256 p0, string memory p1, string memory p2) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(uint256,string,string)", p0, p1, p2));
    }

    function log(uint256 p0, string memory p1, bool p2) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(uint256,string,bool)", p0, p1, p2));
    }

    function log(uint256 p0, string memory p1, address p2) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(uint256,string,address)", p0, p1, p2));
    }

    function log(uint256 p0, bool p1, uint256 p2) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,uint256)", p0, p1, p2));
    }

    function log(uint256 p0, bool p1, string memory p2) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,string)", p0, p1, p2));
    }

    function log(uint256 p0, bool p1, bool p2) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,bool)", p0, p1, p2));
    }

    function log(uint256 p0, bool p1, address p2) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,address)", p0, p1, p2));
    }

    function log(uint256 p0, address p1, uint256 p2) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(uint256,address,uint256)", p0, p1, p2));
    }

    function log(uint256 p0, address p1, string memory p2) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(uint256,address,string)", p0, p1, p2));
    }

    function log(uint256 p0, address p1, bool p2) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(uint256,address,bool)", p0, p1, p2));
    }

    function log(uint256 p0, address p1, address p2) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(uint256,address,address)", p0, p1, p2));
    }

    function log(string memory p0, uint256 p1, uint256 p2) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(string,uint256,uint256)", p0, p1, p2));
    }

    function log(string memory p0, uint256 p1, string memory p2) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(string,uint256,string)", p0, p1, p2));
    }

    function log(string memory p0, uint256 p1, bool p2) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(string,uint256,bool)", p0, p1, p2));
    }

    function log(string memory p0, uint256 p1, address p2) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(string,uint256,address)", p0, p1, p2));
    }

    function log(string memory p0, string memory p1, uint256 p2) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(string,string,uint256)", p0, p1, p2));
    }

    function log(string memory p0, string memory p1, string memory p2) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(string,string,string)", p0, p1, p2));
    }

    function log(string memory p0, string memory p1, bool p2) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(string,string,bool)", p0, p1, p2));
    }

    function log(string memory p0, string memory p1, address p2) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(string,string,address)", p0, p1, p2));
    }

    function log(string memory p0, bool p1, uint256 p2) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(string,bool,uint256)", p0, p1, p2));
    }

    function log(string memory p0, bool p1, string memory p2) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(string,bool,string)", p0, p1, p2));
    }

    function log(string memory p0, bool p1, bool p2) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(string,bool,bool)", p0, p1, p2));
    }

    function log(string memory p0, bool p1, address p2) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(string,bool,address)", p0, p1, p2));
    }

    function log(string memory p0, address p1, uint256 p2) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(string,address,uint256)", p0, p1, p2));
    }

    function log(string memory p0, address p1, string memory p2) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(string,address,string)", p0, p1, p2));
    }

    function log(string memory p0, address p1, bool p2) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(string,address,bool)", p0, p1, p2));
    }

    function log(string memory p0, address p1, address p2) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(string,address,address)", p0, p1, p2));
    }

    function log(bool p0, uint256 p1, uint256 p2) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,uint256)", p0, p1, p2));
    }

    function log(bool p0, uint256 p1, string memory p2) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,string)", p0, p1, p2));
    }

    function log(bool p0, uint256 p1, bool p2) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,bool)", p0, p1, p2));
    }

    function log(bool p0, uint256 p1, address p2) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,address)", p0, p1, p2));
    }

    function log(bool p0, string memory p1, uint256 p2) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(bool,string,uint256)", p0, p1, p2));
    }

    function log(bool p0, string memory p1, string memory p2) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(bool,string,string)", p0, p1, p2));
    }

    function log(bool p0, string memory p1, bool p2) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(bool,string,bool)", p0, p1, p2));
    }

    function log(bool p0, string memory p1, address p2) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(bool,string,address)", p0, p1, p2));
    }

    function log(bool p0, bool p1, uint256 p2) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint256)", p0, p1, p2));
    }

    function log(bool p0, bool p1, string memory p2) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(bool,bool,string)", p0, p1, p2));
    }

    function log(bool p0, bool p1, bool p2) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(bool,bool,bool)", p0, p1, p2));
    }

    function log(bool p0, bool p1, address p2) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(bool,bool,address)", p0, p1, p2));
    }

    function log(bool p0, address p1, uint256 p2) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(bool,address,uint256)", p0, p1, p2));
    }

    function log(bool p0, address p1, string memory p2) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(bool,address,string)", p0, p1, p2));
    }

    function log(bool p0, address p1, bool p2) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(bool,address,bool)", p0, p1, p2));
    }

    function log(bool p0, address p1, address p2) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(bool,address,address)", p0, p1, p2));
    }

    function log(address p0, uint256 p1, uint256 p2) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(address,uint256,uint256)", p0, p1, p2));
    }

    function log(address p0, uint256 p1, string memory p2) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(address,uint256,string)", p0, p1, p2));
    }

    function log(address p0, uint256 p1, bool p2) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(address,uint256,bool)", p0, p1, p2));
    }

    function log(address p0, uint256 p1, address p2) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(address,uint256,address)", p0, p1, p2));
    }

    function log(address p0, string memory p1, uint256 p2) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(address,string,uint256)", p0, p1, p2));
    }

    function log(address p0, string memory p1, string memory p2) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(address,string,string)", p0, p1, p2));
    }

    function log(address p0, string memory p1, bool p2) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(address,string,bool)", p0, p1, p2));
    }

    function log(address p0, string memory p1, address p2) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(address,string,address)", p0, p1, p2));
    }

    function log(address p0, bool p1, uint256 p2) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(address,bool,uint256)", p0, p1, p2));
    }

    function log(address p0, bool p1, string memory p2) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(address,bool,string)", p0, p1, p2));
    }

    function log(address p0, bool p1, bool p2) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(address,bool,bool)", p0, p1, p2));
    }

    function log(address p0, bool p1, address p2) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(address,bool,address)", p0, p1, p2));
    }

    function log(address p0, address p1, uint256 p2) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(address,address,uint256)", p0, p1, p2));
    }

    function log(address p0, address p1, string memory p2) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(address,address,string)", p0, p1, p2));
    }

    function log(address p0, address p1, bool p2) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(address,address,bool)", p0, p1, p2));
    }

    function log(address p0, address p1, address p2) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(address,address,address)", p0, p1, p2));
    }

    function log(uint256 p0, uint256 p1, uint256 p2, uint256 p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,uint256,uint256)", p0, p1, p2, p3));
    }

    function log(uint256 p0, uint256 p1, uint256 p2, string memory p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,uint256,string)", p0, p1, p2, p3));
    }

    function log(uint256 p0, uint256 p1, uint256 p2, bool p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,uint256,bool)", p0, p1, p2, p3));
    }

    function log(uint256 p0, uint256 p1, uint256 p2, address p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,uint256,address)", p0, p1, p2, p3));
    }

    function log(uint256 p0, uint256 p1, string memory p2, uint256 p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,string,uint256)", p0, p1, p2, p3));
    }

    function log(uint256 p0, uint256 p1, string memory p2, string memory p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,string,string)", p0, p1, p2, p3));
    }

    function log(uint256 p0, uint256 p1, string memory p2, bool p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,string,bool)", p0, p1, p2, p3));
    }

    function log(uint256 p0, uint256 p1, string memory p2, address p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,string,address)", p0, p1, p2, p3));
    }

    function log(uint256 p0, uint256 p1, bool p2, uint256 p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,bool,uint256)", p0, p1, p2, p3));
    }

    function log(uint256 p0, uint256 p1, bool p2, string memory p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,bool,string)", p0, p1, p2, p3));
    }

    function log(uint256 p0, uint256 p1, bool p2, bool p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,bool,bool)", p0, p1, p2, p3));
    }

    function log(uint256 p0, uint256 p1, bool p2, address p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,bool,address)", p0, p1, p2, p3));
    }

    function log(uint256 p0, uint256 p1, address p2, uint256 p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,address,uint256)", p0, p1, p2, p3));
    }

    function log(uint256 p0, uint256 p1, address p2, string memory p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,address,string)", p0, p1, p2, p3));
    }

    function log(uint256 p0, uint256 p1, address p2, bool p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,address,bool)", p0, p1, p2, p3));
    }

    function log(uint256 p0, uint256 p1, address p2, address p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,address,address)", p0, p1, p2, p3));
    }

    function log(uint256 p0, string memory p1, uint256 p2, uint256 p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(uint256,string,uint256,uint256)", p0, p1, p2, p3));
    }

    function log(uint256 p0, string memory p1, uint256 p2, string memory p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(uint256,string,uint256,string)", p0, p1, p2, p3));
    }

    function log(uint256 p0, string memory p1, uint256 p2, bool p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(uint256,string,uint256,bool)", p0, p1, p2, p3));
    }

    function log(uint256 p0, string memory p1, uint256 p2, address p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(uint256,string,uint256,address)", p0, p1, p2, p3));
    }

    function log(uint256 p0, string memory p1, string memory p2, uint256 p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(uint256,string,string,uint256)", p0, p1, p2, p3));
    }

    function log(uint256 p0, string memory p1, string memory p2, string memory p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(uint256,string,string,string)", p0, p1, p2, p3));
    }

    function log(uint256 p0, string memory p1, string memory p2, bool p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(uint256,string,string,bool)", p0, p1, p2, p3));
    }

    function log(uint256 p0, string memory p1, string memory p2, address p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(uint256,string,string,address)", p0, p1, p2, p3));
    }

    function log(uint256 p0, string memory p1, bool p2, uint256 p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(uint256,string,bool,uint256)", p0, p1, p2, p3));
    }

    function log(uint256 p0, string memory p1, bool p2, string memory p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(uint256,string,bool,string)", p0, p1, p2, p3));
    }

    function log(uint256 p0, string memory p1, bool p2, bool p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(uint256,string,bool,bool)", p0, p1, p2, p3));
    }

    function log(uint256 p0, string memory p1, bool p2, address p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(uint256,string,bool,address)", p0, p1, p2, p3));
    }

    function log(uint256 p0, string memory p1, address p2, uint256 p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(uint256,string,address,uint256)", p0, p1, p2, p3));
    }

    function log(uint256 p0, string memory p1, address p2, string memory p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(uint256,string,address,string)", p0, p1, p2, p3));
    }

    function log(uint256 p0, string memory p1, address p2, bool p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(uint256,string,address,bool)", p0, p1, p2, p3));
    }

    function log(uint256 p0, string memory p1, address p2, address p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(uint256,string,address,address)", p0, p1, p2, p3));
    }

    function log(uint256 p0, bool p1, uint256 p2, uint256 p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,uint256,uint256)", p0, p1, p2, p3));
    }

    function log(uint256 p0, bool p1, uint256 p2, string memory p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,uint256,string)", p0, p1, p2, p3));
    }

    function log(uint256 p0, bool p1, uint256 p2, bool p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,uint256,bool)", p0, p1, p2, p3));
    }

    function log(uint256 p0, bool p1, uint256 p2, address p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,uint256,address)", p0, p1, p2, p3));
    }

    function log(uint256 p0, bool p1, string memory p2, uint256 p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,string,uint256)", p0, p1, p2, p3));
    }

    function log(uint256 p0, bool p1, string memory p2, string memory p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,string,string)", p0, p1, p2, p3));
    }

    function log(uint256 p0, bool p1, string memory p2, bool p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,string,bool)", p0, p1, p2, p3));
    }

    function log(uint256 p0, bool p1, string memory p2, address p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,string,address)", p0, p1, p2, p3));
    }

    function log(uint256 p0, bool p1, bool p2, uint256 p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,bool,uint256)", p0, p1, p2, p3));
    }

    function log(uint256 p0, bool p1, bool p2, string memory p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,bool,string)", p0, p1, p2, p3));
    }

    function log(uint256 p0, bool p1, bool p2, bool p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,bool,bool)", p0, p1, p2, p3));
    }

    function log(uint256 p0, bool p1, bool p2, address p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,bool,address)", p0, p1, p2, p3));
    }

    function log(uint256 p0, bool p1, address p2, uint256 p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,address,uint256)", p0, p1, p2, p3));
    }

    function log(uint256 p0, bool p1, address p2, string memory p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,address,string)", p0, p1, p2, p3));
    }

    function log(uint256 p0, bool p1, address p2, bool p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,address,bool)", p0, p1, p2, p3));
    }

    function log(uint256 p0, bool p1, address p2, address p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,address,address)", p0, p1, p2, p3));
    }

    function log(uint256 p0, address p1, uint256 p2, uint256 p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(uint256,address,uint256,uint256)", p0, p1, p2, p3));
    }

    function log(uint256 p0, address p1, uint256 p2, string memory p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(uint256,address,uint256,string)", p0, p1, p2, p3));
    }

    function log(uint256 p0, address p1, uint256 p2, bool p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(uint256,address,uint256,bool)", p0, p1, p2, p3));
    }

    function log(uint256 p0, address p1, uint256 p2, address p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(uint256,address,uint256,address)", p0, p1, p2, p3));
    }

    function log(uint256 p0, address p1, string memory p2, uint256 p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(uint256,address,string,uint256)", p0, p1, p2, p3));
    }

    function log(uint256 p0, address p1, string memory p2, string memory p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(uint256,address,string,string)", p0, p1, p2, p3));
    }

    function log(uint256 p0, address p1, string memory p2, bool p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(uint256,address,string,bool)", p0, p1, p2, p3));
    }

    function log(uint256 p0, address p1, string memory p2, address p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(uint256,address,string,address)", p0, p1, p2, p3));
    }

    function log(uint256 p0, address p1, bool p2, uint256 p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(uint256,address,bool,uint256)", p0, p1, p2, p3));
    }

    function log(uint256 p0, address p1, bool p2, string memory p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(uint256,address,bool,string)", p0, p1, p2, p3));
    }

    function log(uint256 p0, address p1, bool p2, bool p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(uint256,address,bool,bool)", p0, p1, p2, p3));
    }

    function log(uint256 p0, address p1, bool p2, address p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(uint256,address,bool,address)", p0, p1, p2, p3));
    }

    function log(uint256 p0, address p1, address p2, uint256 p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(uint256,address,address,uint256)", p0, p1, p2, p3));
    }

    function log(uint256 p0, address p1, address p2, string memory p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(uint256,address,address,string)", p0, p1, p2, p3));
    }

    function log(uint256 p0, address p1, address p2, bool p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(uint256,address,address,bool)", p0, p1, p2, p3));
    }

    function log(uint256 p0, address p1, address p2, address p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(uint256,address,address,address)", p0, p1, p2, p3));
    }

    function log(string memory p0, uint256 p1, uint256 p2, uint256 p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(string,uint256,uint256,uint256)", p0, p1, p2, p3));
    }

    function log(string memory p0, uint256 p1, uint256 p2, string memory p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(string,uint256,uint256,string)", p0, p1, p2, p3));
    }

    function log(string memory p0, uint256 p1, uint256 p2, bool p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(string,uint256,uint256,bool)", p0, p1, p2, p3));
    }

    function log(string memory p0, uint256 p1, uint256 p2, address p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(string,uint256,uint256,address)", p0, p1, p2, p3));
    }

    function log(string memory p0, uint256 p1, string memory p2, uint256 p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(string,uint256,string,uint256)", p0, p1, p2, p3));
    }

    function log(string memory p0, uint256 p1, string memory p2, string memory p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(string,uint256,string,string)", p0, p1, p2, p3));
    }

    function log(string memory p0, uint256 p1, string memory p2, bool p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(string,uint256,string,bool)", p0, p1, p2, p3));
    }

    function log(string memory p0, uint256 p1, string memory p2, address p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(string,uint256,string,address)", p0, p1, p2, p3));
    }

    function log(string memory p0, uint256 p1, bool p2, uint256 p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(string,uint256,bool,uint256)", p0, p1, p2, p3));
    }

    function log(string memory p0, uint256 p1, bool p2, string memory p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(string,uint256,bool,string)", p0, p1, p2, p3));
    }

    function log(string memory p0, uint256 p1, bool p2, bool p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(string,uint256,bool,bool)", p0, p1, p2, p3));
    }

    function log(string memory p0, uint256 p1, bool p2, address p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(string,uint256,bool,address)", p0, p1, p2, p3));
    }

    function log(string memory p0, uint256 p1, address p2, uint256 p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(string,uint256,address,uint256)", p0, p1, p2, p3));
    }

    function log(string memory p0, uint256 p1, address p2, string memory p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(string,uint256,address,string)", p0, p1, p2, p3));
    }

    function log(string memory p0, uint256 p1, address p2, bool p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(string,uint256,address,bool)", p0, p1, p2, p3));
    }

    function log(string memory p0, uint256 p1, address p2, address p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(string,uint256,address,address)", p0, p1, p2, p3));
    }

    function log(string memory p0, string memory p1, uint256 p2, uint256 p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(string,string,uint256,uint256)", p0, p1, p2, p3));
    }

    function log(string memory p0, string memory p1, uint256 p2, string memory p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(string,string,uint256,string)", p0, p1, p2, p3));
    }

    function log(string memory p0, string memory p1, uint256 p2, bool p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(string,string,uint256,bool)", p0, p1, p2, p3));
    }

    function log(string memory p0, string memory p1, uint256 p2, address p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(string,string,uint256,address)", p0, p1, p2, p3));
    }

    function log(string memory p0, string memory p1, string memory p2, uint256 p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(string,string,string,uint256)", p0, p1, p2, p3));
    }

    function log(string memory p0, string memory p1, string memory p2, string memory p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(string,string,string,string)", p0, p1, p2, p3));
    }

    function log(string memory p0, string memory p1, string memory p2, bool p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(string,string,string,bool)", p0, p1, p2, p3));
    }

    function log(string memory p0, string memory p1, string memory p2, address p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(string,string,string,address)", p0, p1, p2, p3));
    }

    function log(string memory p0, string memory p1, bool p2, uint256 p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(string,string,bool,uint256)", p0, p1, p2, p3));
    }

    function log(string memory p0, string memory p1, bool p2, string memory p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(string,string,bool,string)", p0, p1, p2, p3));
    }

    function log(string memory p0, string memory p1, bool p2, bool p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(string,string,bool,bool)", p0, p1, p2, p3));
    }

    function log(string memory p0, string memory p1, bool p2, address p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(string,string,bool,address)", p0, p1, p2, p3));
    }

    function log(string memory p0, string memory p1, address p2, uint256 p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(string,string,address,uint256)", p0, p1, p2, p3));
    }

    function log(string memory p0, string memory p1, address p2, string memory p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(string,string,address,string)", p0, p1, p2, p3));
    }

    function log(string memory p0, string memory p1, address p2, bool p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(string,string,address,bool)", p0, p1, p2, p3));
    }

    function log(string memory p0, string memory p1, address p2, address p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(string,string,address,address)", p0, p1, p2, p3));
    }

    function log(string memory p0, bool p1, uint256 p2, uint256 p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(string,bool,uint256,uint256)", p0, p1, p2, p3));
    }

    function log(string memory p0, bool p1, uint256 p2, string memory p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(string,bool,uint256,string)", p0, p1, p2, p3));
    }

    function log(string memory p0, bool p1, uint256 p2, bool p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(string,bool,uint256,bool)", p0, p1, p2, p3));
    }

    function log(string memory p0, bool p1, uint256 p2, address p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(string,bool,uint256,address)", p0, p1, p2, p3));
    }

    function log(string memory p0, bool p1, string memory p2, uint256 p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(string,bool,string,uint256)", p0, p1, p2, p3));
    }

    function log(string memory p0, bool p1, string memory p2, string memory p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(string,bool,string,string)", p0, p1, p2, p3));
    }

    function log(string memory p0, bool p1, string memory p2, bool p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(string,bool,string,bool)", p0, p1, p2, p3));
    }

    function log(string memory p0, bool p1, string memory p2, address p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(string,bool,string,address)", p0, p1, p2, p3));
    }

    function log(string memory p0, bool p1, bool p2, uint256 p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(string,bool,bool,uint256)", p0, p1, p2, p3));
    }

    function log(string memory p0, bool p1, bool p2, string memory p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(string,bool,bool,string)", p0, p1, p2, p3));
    }

    function log(string memory p0, bool p1, bool p2, bool p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(string,bool,bool,bool)", p0, p1, p2, p3));
    }

    function log(string memory p0, bool p1, bool p2, address p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(string,bool,bool,address)", p0, p1, p2, p3));
    }

    function log(string memory p0, bool p1, address p2, uint256 p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(string,bool,address,uint256)", p0, p1, p2, p3));
    }

    function log(string memory p0, bool p1, address p2, string memory p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(string,bool,address,string)", p0, p1, p2, p3));
    }

    function log(string memory p0, bool p1, address p2, bool p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(string,bool,address,bool)", p0, p1, p2, p3));
    }

    function log(string memory p0, bool p1, address p2, address p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(string,bool,address,address)", p0, p1, p2, p3));
    }

    function log(string memory p0, address p1, uint256 p2, uint256 p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(string,address,uint256,uint256)", p0, p1, p2, p3));
    }

    function log(string memory p0, address p1, uint256 p2, string memory p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(string,address,uint256,string)", p0, p1, p2, p3));
    }

    function log(string memory p0, address p1, uint256 p2, bool p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(string,address,uint256,bool)", p0, p1, p2, p3));
    }

    function log(string memory p0, address p1, uint256 p2, address p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(string,address,uint256,address)", p0, p1, p2, p3));
    }

    function log(string memory p0, address p1, string memory p2, uint256 p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(string,address,string,uint256)", p0, p1, p2, p3));
    }

    function log(string memory p0, address p1, string memory p2, string memory p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(string,address,string,string)", p0, p1, p2, p3));
    }

    function log(string memory p0, address p1, string memory p2, bool p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(string,address,string,bool)", p0, p1, p2, p3));
    }

    function log(string memory p0, address p1, string memory p2, address p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(string,address,string,address)", p0, p1, p2, p3));
    }

    function log(string memory p0, address p1, bool p2, uint256 p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(string,address,bool,uint256)", p0, p1, p2, p3));
    }

    function log(string memory p0, address p1, bool p2, string memory p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(string,address,bool,string)", p0, p1, p2, p3));
    }

    function log(string memory p0, address p1, bool p2, bool p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(string,address,bool,bool)", p0, p1, p2, p3));
    }

    function log(string memory p0, address p1, bool p2, address p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(string,address,bool,address)", p0, p1, p2, p3));
    }

    function log(string memory p0, address p1, address p2, uint256 p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(string,address,address,uint256)", p0, p1, p2, p3));
    }

    function log(string memory p0, address p1, address p2, string memory p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(string,address,address,string)", p0, p1, p2, p3));
    }

    function log(string memory p0, address p1, address p2, bool p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(string,address,address,bool)", p0, p1, p2, p3));
    }

    function log(string memory p0, address p1, address p2, address p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(string,address,address,address)", p0, p1, p2, p3));
    }

    function log(bool p0, uint256 p1, uint256 p2, uint256 p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,uint256,uint256)", p0, p1, p2, p3));
    }

    function log(bool p0, uint256 p1, uint256 p2, string memory p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,uint256,string)", p0, p1, p2, p3));
    }

    function log(bool p0, uint256 p1, uint256 p2, bool p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,uint256,bool)", p0, p1, p2, p3));
    }

    function log(bool p0, uint256 p1, uint256 p2, address p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,uint256,address)", p0, p1, p2, p3));
    }

    function log(bool p0, uint256 p1, string memory p2, uint256 p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,string,uint256)", p0, p1, p2, p3));
    }

    function log(bool p0, uint256 p1, string memory p2, string memory p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,string,string)", p0, p1, p2, p3));
    }

    function log(bool p0, uint256 p1, string memory p2, bool p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,string,bool)", p0, p1, p2, p3));
    }

    function log(bool p0, uint256 p1, string memory p2, address p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,string,address)", p0, p1, p2, p3));
    }

    function log(bool p0, uint256 p1, bool p2, uint256 p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,bool,uint256)", p0, p1, p2, p3));
    }

    function log(bool p0, uint256 p1, bool p2, string memory p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,bool,string)", p0, p1, p2, p3));
    }

    function log(bool p0, uint256 p1, bool p2, bool p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,bool,bool)", p0, p1, p2, p3));
    }

    function log(bool p0, uint256 p1, bool p2, address p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,bool,address)", p0, p1, p2, p3));
    }

    function log(bool p0, uint256 p1, address p2, uint256 p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,address,uint256)", p0, p1, p2, p3));
    }

    function log(bool p0, uint256 p1, address p2, string memory p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,address,string)", p0, p1, p2, p3));
    }

    function log(bool p0, uint256 p1, address p2, bool p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,address,bool)", p0, p1, p2, p3));
    }

    function log(bool p0, uint256 p1, address p2, address p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,address,address)", p0, p1, p2, p3));
    }

    function log(bool p0, string memory p1, uint256 p2, uint256 p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(bool,string,uint256,uint256)", p0, p1, p2, p3));
    }

    function log(bool p0, string memory p1, uint256 p2, string memory p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(bool,string,uint256,string)", p0, p1, p2, p3));
    }

    function log(bool p0, string memory p1, uint256 p2, bool p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(bool,string,uint256,bool)", p0, p1, p2, p3));
    }

    function log(bool p0, string memory p1, uint256 p2, address p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(bool,string,uint256,address)", p0, p1, p2, p3));
    }

    function log(bool p0, string memory p1, string memory p2, uint256 p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(bool,string,string,uint256)", p0, p1, p2, p3));
    }

    function log(bool p0, string memory p1, string memory p2, string memory p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(bool,string,string,string)", p0, p1, p2, p3));
    }

    function log(bool p0, string memory p1, string memory p2, bool p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(bool,string,string,bool)", p0, p1, p2, p3));
    }

    function log(bool p0, string memory p1, string memory p2, address p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(bool,string,string,address)", p0, p1, p2, p3));
    }

    function log(bool p0, string memory p1, bool p2, uint256 p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(bool,string,bool,uint256)", p0, p1, p2, p3));
    }

    function log(bool p0, string memory p1, bool p2, string memory p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(bool,string,bool,string)", p0, p1, p2, p3));
    }

    function log(bool p0, string memory p1, bool p2, bool p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(bool,string,bool,bool)", p0, p1, p2, p3));
    }

    function log(bool p0, string memory p1, bool p2, address p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(bool,string,bool,address)", p0, p1, p2, p3));
    }

    function log(bool p0, string memory p1, address p2, uint256 p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(bool,string,address,uint256)", p0, p1, p2, p3));
    }

    function log(bool p0, string memory p1, address p2, string memory p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(bool,string,address,string)", p0, p1, p2, p3));
    }

    function log(bool p0, string memory p1, address p2, bool p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(bool,string,address,bool)", p0, p1, p2, p3));
    }

    function log(bool p0, string memory p1, address p2, address p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(bool,string,address,address)", p0, p1, p2, p3));
    }

    function log(bool p0, bool p1, uint256 p2, uint256 p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint256,uint256)", p0, p1, p2, p3));
    }

    function log(bool p0, bool p1, uint256 p2, string memory p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint256,string)", p0, p1, p2, p3));
    }

    function log(bool p0, bool p1, uint256 p2, bool p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint256,bool)", p0, p1, p2, p3));
    }

    function log(bool p0, bool p1, uint256 p2, address p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint256,address)", p0, p1, p2, p3));
    }

    function log(bool p0, bool p1, string memory p2, uint256 p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(bool,bool,string,uint256)", p0, p1, p2, p3));
    }

    function log(bool p0, bool p1, string memory p2, string memory p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(bool,bool,string,string)", p0, p1, p2, p3));
    }

    function log(bool p0, bool p1, string memory p2, bool p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(bool,bool,string,bool)", p0, p1, p2, p3));
    }

    function log(bool p0, bool p1, string memory p2, address p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(bool,bool,string,address)", p0, p1, p2, p3));
    }

    function log(bool p0, bool p1, bool p2, uint256 p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(bool,bool,bool,uint256)", p0, p1, p2, p3));
    }

    function log(bool p0, bool p1, bool p2, string memory p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(bool,bool,bool,string)", p0, p1, p2, p3));
    }

    function log(bool p0, bool p1, bool p2, bool p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(bool,bool,bool,bool)", p0, p1, p2, p3));
    }

    function log(bool p0, bool p1, bool p2, address p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(bool,bool,bool,address)", p0, p1, p2, p3));
    }

    function log(bool p0, bool p1, address p2, uint256 p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(bool,bool,address,uint256)", p0, p1, p2, p3));
    }

    function log(bool p0, bool p1, address p2, string memory p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(bool,bool,address,string)", p0, p1, p2, p3));
    }

    function log(bool p0, bool p1, address p2, bool p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(bool,bool,address,bool)", p0, p1, p2, p3));
    }

    function log(bool p0, bool p1, address p2, address p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(bool,bool,address,address)", p0, p1, p2, p3));
    }

    function log(bool p0, address p1, uint256 p2, uint256 p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(bool,address,uint256,uint256)", p0, p1, p2, p3));
    }

    function log(bool p0, address p1, uint256 p2, string memory p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(bool,address,uint256,string)", p0, p1, p2, p3));
    }

    function log(bool p0, address p1, uint256 p2, bool p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(bool,address,uint256,bool)", p0, p1, p2, p3));
    }

    function log(bool p0, address p1, uint256 p2, address p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(bool,address,uint256,address)", p0, p1, p2, p3));
    }

    function log(bool p0, address p1, string memory p2, uint256 p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(bool,address,string,uint256)", p0, p1, p2, p3));
    }

    function log(bool p0, address p1, string memory p2, string memory p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(bool,address,string,string)", p0, p1, p2, p3));
    }

    function log(bool p0, address p1, string memory p2, bool p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(bool,address,string,bool)", p0, p1, p2, p3));
    }

    function log(bool p0, address p1, string memory p2, address p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(bool,address,string,address)", p0, p1, p2, p3));
    }

    function log(bool p0, address p1, bool p2, uint256 p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(bool,address,bool,uint256)", p0, p1, p2, p3));
    }

    function log(bool p0, address p1, bool p2, string memory p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(bool,address,bool,string)", p0, p1, p2, p3));
    }

    function log(bool p0, address p1, bool p2, bool p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(bool,address,bool,bool)", p0, p1, p2, p3));
    }

    function log(bool p0, address p1, bool p2, address p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(bool,address,bool,address)", p0, p1, p2, p3));
    }

    function log(bool p0, address p1, address p2, uint256 p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(bool,address,address,uint256)", p0, p1, p2, p3));
    }

    function log(bool p0, address p1, address p2, string memory p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(bool,address,address,string)", p0, p1, p2, p3));
    }

    function log(bool p0, address p1, address p2, bool p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(bool,address,address,bool)", p0, p1, p2, p3));
    }

    function log(bool p0, address p1, address p2, address p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(bool,address,address,address)", p0, p1, p2, p3));
    }

    function log(address p0, uint256 p1, uint256 p2, uint256 p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(address,uint256,uint256,uint256)", p0, p1, p2, p3));
    }

    function log(address p0, uint256 p1, uint256 p2, string memory p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(address,uint256,uint256,string)", p0, p1, p2, p3));
    }

    function log(address p0, uint256 p1, uint256 p2, bool p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(address,uint256,uint256,bool)", p0, p1, p2, p3));
    }

    function log(address p0, uint256 p1, uint256 p2, address p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(address,uint256,uint256,address)", p0, p1, p2, p3));
    }

    function log(address p0, uint256 p1, string memory p2, uint256 p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(address,uint256,string,uint256)", p0, p1, p2, p3));
    }

    function log(address p0, uint256 p1, string memory p2, string memory p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(address,uint256,string,string)", p0, p1, p2, p3));
    }

    function log(address p0, uint256 p1, string memory p2, bool p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(address,uint256,string,bool)", p0, p1, p2, p3));
    }

    function log(address p0, uint256 p1, string memory p2, address p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(address,uint256,string,address)", p0, p1, p2, p3));
    }

    function log(address p0, uint256 p1, bool p2, uint256 p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(address,uint256,bool,uint256)", p0, p1, p2, p3));
    }

    function log(address p0, uint256 p1, bool p2, string memory p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(address,uint256,bool,string)", p0, p1, p2, p3));
    }

    function log(address p0, uint256 p1, bool p2, bool p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(address,uint256,bool,bool)", p0, p1, p2, p3));
    }

    function log(address p0, uint256 p1, bool p2, address p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(address,uint256,bool,address)", p0, p1, p2, p3));
    }

    function log(address p0, uint256 p1, address p2, uint256 p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(address,uint256,address,uint256)", p0, p1, p2, p3));
    }

    function log(address p0, uint256 p1, address p2, string memory p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(address,uint256,address,string)", p0, p1, p2, p3));
    }

    function log(address p0, uint256 p1, address p2, bool p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(address,uint256,address,bool)", p0, p1, p2, p3));
    }

    function log(address p0, uint256 p1, address p2, address p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(address,uint256,address,address)", p0, p1, p2, p3));
    }

    function log(address p0, string memory p1, uint256 p2, uint256 p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(address,string,uint256,uint256)", p0, p1, p2, p3));
    }

    function log(address p0, string memory p1, uint256 p2, string memory p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(address,string,uint256,string)", p0, p1, p2, p3));
    }

    function log(address p0, string memory p1, uint256 p2, bool p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(address,string,uint256,bool)", p0, p1, p2, p3));
    }

    function log(address p0, string memory p1, uint256 p2, address p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(address,string,uint256,address)", p0, p1, p2, p3));
    }

    function log(address p0, string memory p1, string memory p2, uint256 p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(address,string,string,uint256)", p0, p1, p2, p3));
    }

    function log(address p0, string memory p1, string memory p2, string memory p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(address,string,string,string)", p0, p1, p2, p3));
    }

    function log(address p0, string memory p1, string memory p2, bool p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(address,string,string,bool)", p0, p1, p2, p3));
    }

    function log(address p0, string memory p1, string memory p2, address p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(address,string,string,address)", p0, p1, p2, p3));
    }

    function log(address p0, string memory p1, bool p2, uint256 p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(address,string,bool,uint256)", p0, p1, p2, p3));
    }

    function log(address p0, string memory p1, bool p2, string memory p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(address,string,bool,string)", p0, p1, p2, p3));
    }

    function log(address p0, string memory p1, bool p2, bool p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(address,string,bool,bool)", p0, p1, p2, p3));
    }

    function log(address p0, string memory p1, bool p2, address p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(address,string,bool,address)", p0, p1, p2, p3));
    }

    function log(address p0, string memory p1, address p2, uint256 p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(address,string,address,uint256)", p0, p1, p2, p3));
    }

    function log(address p0, string memory p1, address p2, string memory p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(address,string,address,string)", p0, p1, p2, p3));
    }

    function log(address p0, string memory p1, address p2, bool p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(address,string,address,bool)", p0, p1, p2, p3));
    }

    function log(address p0, string memory p1, address p2, address p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(address,string,address,address)", p0, p1, p2, p3));
    }

    function log(address p0, bool p1, uint256 p2, uint256 p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(address,bool,uint256,uint256)", p0, p1, p2, p3));
    }

    function log(address p0, bool p1, uint256 p2, string memory p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(address,bool,uint256,string)", p0, p1, p2, p3));
    }

    function log(address p0, bool p1, uint256 p2, bool p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(address,bool,uint256,bool)", p0, p1, p2, p3));
    }

    function log(address p0, bool p1, uint256 p2, address p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(address,bool,uint256,address)", p0, p1, p2, p3));
    }

    function log(address p0, bool p1, string memory p2, uint256 p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(address,bool,string,uint256)", p0, p1, p2, p3));
    }

    function log(address p0, bool p1, string memory p2, string memory p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(address,bool,string,string)", p0, p1, p2, p3));
    }

    function log(address p0, bool p1, string memory p2, bool p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(address,bool,string,bool)", p0, p1, p2, p3));
    }

    function log(address p0, bool p1, string memory p2, address p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(address,bool,string,address)", p0, p1, p2, p3));
    }

    function log(address p0, bool p1, bool p2, uint256 p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(address,bool,bool,uint256)", p0, p1, p2, p3));
    }

    function log(address p0, bool p1, bool p2, string memory p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(address,bool,bool,string)", p0, p1, p2, p3));
    }

    function log(address p0, bool p1, bool p2, bool p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(address,bool,bool,bool)", p0, p1, p2, p3));
    }

    function log(address p0, bool p1, bool p2, address p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(address,bool,bool,address)", p0, p1, p2, p3));
    }

    function log(address p0, bool p1, address p2, uint256 p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(address,bool,address,uint256)", p0, p1, p2, p3));
    }

    function log(address p0, bool p1, address p2, string memory p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(address,bool,address,string)", p0, p1, p2, p3));
    }

    function log(address p0, bool p1, address p2, bool p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(address,bool,address,bool)", p0, p1, p2, p3));
    }

    function log(address p0, bool p1, address p2, address p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(address,bool,address,address)", p0, p1, p2, p3));
    }

    function log(address p0, address p1, uint256 p2, uint256 p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(address,address,uint256,uint256)", p0, p1, p2, p3));
    }

    function log(address p0, address p1, uint256 p2, string memory p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(address,address,uint256,string)", p0, p1, p2, p3));
    }

    function log(address p0, address p1, uint256 p2, bool p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(address,address,uint256,bool)", p0, p1, p2, p3));
    }

    function log(address p0, address p1, uint256 p2, address p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(address,address,uint256,address)", p0, p1, p2, p3));
    }

    function log(address p0, address p1, string memory p2, uint256 p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(address,address,string,uint256)", p0, p1, p2, p3));
    }

    function log(address p0, address p1, string memory p2, string memory p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(address,address,string,string)", p0, p1, p2, p3));
    }

    function log(address p0, address p1, string memory p2, bool p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(address,address,string,bool)", p0, p1, p2, p3));
    }

    function log(address p0, address p1, string memory p2, address p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(address,address,string,address)", p0, p1, p2, p3));
    }

    function log(address p0, address p1, bool p2, uint256 p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(address,address,bool,uint256)", p0, p1, p2, p3));
    }

    function log(address p0, address p1, bool p2, string memory p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(address,address,bool,string)", p0, p1, p2, p3));
    }

    function log(address p0, address p1, bool p2, bool p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(address,address,bool,bool)", p0, p1, p2, p3));
    }

    function log(address p0, address p1, bool p2, address p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(address,address,bool,address)", p0, p1, p2, p3));
    }

    function log(address p0, address p1, address p2, uint256 p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(address,address,address,uint256)", p0, p1, p2, p3));
    }

    function log(address p0, address p1, address p2, string memory p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(address,address,address,string)", p0, p1, p2, p3));
    }

    function log(address p0, address p1, address p2, bool p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(address,address,address,bool)", p0, p1, p2, p3));
    }

    function log(address p0, address p1, address p2, address p3) internal pure {
        _sendLogPayload(abi.encodeWithSignature("log(address,address,address,address)", p0, p1, p2, p3));
    }
}

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

interface IPancakeRouter {
    function WETH() external view returns (address);
    function getAmountsOut(uint256 amountIn, address[] memory path) external view returns (uint256[] memory amounts);
}

contract Quoter {
    IPancakeRouter public pancakeRouter;
    address public usdc;
    address public weth;
    constructor(address _pancakeRouter, address _usdc) {
        pancakeRouter = IPancakeRouter(_pancakeRouter);
        usdc = _usdc;
    }

    function getUSDCToBNBAmount(uint256 usdcAmount) public view returns (uint256) {
        address[] memory path = new address[](2);
        path[0] = usdc;
        path[1] = pancakeRouter.WETH();
        uint256[] memory amounts = pancakeRouter.getAmountsOut(usdcAmount, path);
        return amounts[1];
    }

    function getBNBToUSDCAmount(uint256 bnbAmount) public view returns (uint256) {
        address[] memory path = new address[](2);
        path[0] = pancakeRouter.WETH();
        path[1] = usdc;
        uint256[] memory amounts = pancakeRouter.getAmountsOut(bnbAmount, path);
        return amounts[1];
    }
}

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

contract Qualifier {
  address public owner;
  // userId => level => blocked
  mapping(uint256 => mapping(uint256 => bool)) public blockedUsers;

  mapping(address => bool) public adminUsers;

  modifier onlyAdmin() {
    require(adminUsers[msg.sender], "Not an admin");
    _;
  }

  modifier onlyOwner() {
    require(msg.sender == owner, "Not an owner");
    _;
  }

  constructor() {
    owner = msg.sender;
    adminUsers[msg.sender] = true;
  }



  function canUserWithdraw(uint256 userId, uint256 level) public view returns (bool)  {
    return blockedUsers[userId][level] == false;
  }

  function blockUser(uint256 userId, uint256 level) public onlyAdmin {
    blockedUsers[userId][level] = true;
  }

  function blockUserForAllLevels(uint256 userId) public onlyAdmin {
    for (uint256 i = 1; i <= 20; i++) {
      blockedUsers[userId][i] = true;
    }
  }

  function unblockUser(uint256 userId, uint256 level) public onlyAdmin {
    blockedUsers[userId][level] = false;
  }

  function unblockUserForAllLevels(uint256 userId) public onlyAdmin {
    for (uint256 i = 1; i <= 20; i++) {
      blockedUsers[userId][i] = false;
    }
  }

  function addAdmin(address admin) public onlyOwner {
    adminUsers[admin] = true;
  }

  function removeAdmin(address admin) public onlyOwner {
    adminUsers[admin] = false;
  }
}

Please enter a contract address above to load the contract details and source code.

Context size (optional):