ReferralSystem

Description:

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

Blockchain: Ethereum

Source Code: View Code On The Blockchain

Solidity Source Code:

{{
  "language": "Solidity",
  "sources": {
    "contracts/Refdrop.sol": {
      "content": "// SPDX-License-Identifier: MIT\r
pragma solidity ^0.8.0;\r
\r
/**\r
 * @title Interface for SubscriptionSystem\r
 * @dev External interface - implemented by SubscriptionSystem contract\r
 */\r
interface ISubscriptionSystem {\r
    function payReferralReward(address recipient, uint256 amount) external;\r
}\r
\r
/**\r
 * @title ReferralSystem\r
 * @dev Complete implementation of referral and reward system\r
 */\r
contract ReferralSystem {\r
    address payable public owner;\r
    bool public paused;\r
    \r
    // Access control mechanism\r
    mapping(address => bool) public authorizedCallers;\r
    \r
    // Address of SubscriptionSystem (for payment)\r
    address public subscriptionSystemAddress;\r
    \r
    struct ReferralConfig {\r
        uint8 levels;\r
        mapping(uint8 => uint8) discounts;\r
        mapping(uint8 => uint8) rewards;\r
    }\r
    \r
    struct ReferralMilestone {\r
        uint256 referralCount;\r
        bool isPlanSpecific;\r
        uint256 planId;\r
        bool isCorePlan;\r
        uint256 rewardAmount;\r
        bool isActive;\r
    }\r
    \r
    struct ReferralStats {\r
        address[] referredUsers;\r
        mapping(uint256 => uint256) planReferralCounts;\r
        mapping(address => uint8) referralLevel;\r
        uint256 totalEarned;\r
        uint256 totalWithdrawn;\r
        uint256[] achievedMilestones;\r
        uint256 rank;\r
    }\r
    \r
    ReferralConfig public referralConfig;\r
    \r
    mapping(address => address) public userReferrer;\r
    \r
    mapping(address => uint256) public referralRewards;\r
    \r
    mapping(address => ReferralStats) private referralStats;\r
    \r
    mapping(uint256 => ReferralMilestone) public referralMilestones;\r
    uint256 private nextMilestoneId = 1;\r
    \r
    mapping(address => mapping(uint256 => bool)) public claimedMilestones;\r
    \r
    // Arrays for enumeration (avoiding block scanning)\r
    uint256[] private allMilestoneIds;\r
    mapping(uint256 => bool) private milestoneExists;\r
    \r
    address[] private allReferrers;\r
    mapping(address => bool) private referrerExists;\r
    \r
    // Track pending rewards before withdrawal\r
    mapping(address => uint256) public pendingRewards;\r
    \r
    // Referral code system (generated from address, no transaction needed)\r
    mapping(address => string) public addressToReferralCode;\r
    mapping(string => address) public referralCodeToAddress;\r
    \r
    event ReferralPurchase(\r
        address indexed referrer, \r
        address indexed user, \r
        uint256 indexed planId,\r
        bool isCorePlan,\r
        uint256 purchaseId,\r
        uint256 referralLevel,\r
        uint256 rewardAmount\r
    );\r
    \r
    event ReferralRewardWithdrawn(\r
        address indexed referrer, \r
        uint256 amount\r
    );\r
    \r
    event MilestoneAchieved(\r
        address indexed user,\r
        uint256 indexed milestoneId,\r
        uint256 referralCount,\r
        uint256 rewardAmount\r
    );\r
    \r
    event MilestoneRewardClaimed(\r
        address indexed user,\r
        uint256 indexed milestoneId,\r
        uint256 rewardAmount\r
    );\r
    \r
    event EmergencyStatusChanged(bool paused);\r
    event WithdrawnByOwner(uint256 amount);\r
    \r
    event AuthorizedCallerSet(address indexed caller, bool status);\r
    event RankUpdated(address indexed user, uint256 oldRank, uint256 newRank);\r
    event ReferralCodeRegistered(address indexed user, string referralCode);\r
    event SubscriptionSystemAddressSet(address indexed newAddress);\r
    \r
    modifier onlyOwner() {\r
        require(msg.sender == owner, "Only owner can call this function");\r
        _;\r
    }\r
    \r
    modifier whenNotPaused() {\r
        require(!paused, "Contract is paused");\r
        _;\r
    }\r
    \r
    /**\r
     * @dev Constructor initializes the contract with default settings\r
     */\r
    constructor() {\r
        owner = payable(msg.sender);\r
        \r
        referralConfig.levels = 2;\r
        referralConfig.discounts[0] = 10;\r
        referralConfig.discounts[1] = 5;\r
        referralConfig.rewards[0] = 10;\r
        referralConfig.rewards[1] = 2;\r
    }\r
    \r
    /**\r
     * @dev Change contract ownership\r
     * @param newOwner Address of the new owner\r
     */\r
    function transferOwnership(address payable newOwner) external onlyOwner {\r
        require(newOwner != address(0), "New owner cannot be zero address");\r
        owner = newOwner;\r
    }\r
    \r
    /**\r
     * @dev Toggle emergency pause status\r
     * @param _paused New pause status\r
     */\r
    function setPaused(bool _paused) external onlyOwner {\r
        paused = _paused;\r
        emit EmergencyStatusChanged(_paused);\r
    }\r
    \r
    /**\r
     * @dev Withdraw contract balance (owner only)\r
     */\r
    function withdraw() external onlyOwner {\r
        uint256 balance = address(this).balance;\r
        require(balance > 0, "No balance to withdraw");\r
        \r
        (bool success, ) = owner.call{value: balance}("");\r
        require(success, "Withdrawal failed");\r
        \r
        emit WithdrawnByOwner(balance);\r
    }\r
    \r
    /**\r
     * @dev Set authorized caller status\r
     * @param caller Caller address\r
     * @param status Authorization status\r
     */\r
    function setAuthorizedCaller(address caller, bool status) external onlyOwner {\r
        require(caller != address(0), "Invalid address");\r
        authorizedCallers[caller] = status;\r
        emit AuthorizedCallerSet(caller, status);\r
    }\r
    \r
    /**\r
     * @dev Set SubscriptionSystem contract address\r
     * @param _subscriptionSystemAddress Address of the SubscriptionSystem contract\r
     */\r
    function setSubscriptionSystemAddress(address _subscriptionSystemAddress) external onlyOwner {\r
        require(_subscriptionSystemAddress != address(0), "Invalid address");\r
        subscriptionSystemAddress = _subscriptionSystemAddress;\r
        emit SubscriptionSystemAddressSet(_subscriptionSystemAddress);\r
    }\r
    \r
    /**\r
     * @dev Check if caller is authorized\r
     */\r
    modifier onlyAuthorized() {\r
        require(msg.sender == owner || authorizedCallers[msg.sender], "Unauthorized caller");\r
        _;\r
    }\r
    \r
    // ============= Referral Configuration Functions =============\r
    /**\r
     * @dev Configure the referral system levels and percentages\r
     * @param _levels Number of referral levels\r
     * @param _discounts Array of discount percentages for each level\r
     * @param _rewards Array of reward percentages for each level\r
     */\r
    function configureReferralSystem(\r
        uint8 _levels,\r
        uint8[] calldata _discounts,\r
        uint8[] calldata _rewards\r
    ) \r
        external \r
        onlyOwner \r
    {\r
        require(_levels > 0 && _levels <= 5, "Levels must be between 1 and 5");\r
        require(_discounts.length == _levels, "Discounts array length mismatch");\r
        require(_rewards.length == _levels, "Rewards array length mismatch");\r
        \r
        referralConfig.levels = _levels;\r
        \r
        for (uint8 i = 0; i < _levels; i++) {\r
            require(_discounts[i] <= 100, "Discount cannot exceed 100%");\r
            require(_rewards[i] <= 100, "Reward cannot exceed 100%");\r
            \r
            referralConfig.discounts[i] = _discounts[i];\r
            referralConfig.rewards[i] = _rewards[i];\r
        }\r
    }\r
    \r
    /**\r
     * @dev Create a new referral milestone\r
     * @param referralCount Number of referrals needed to achieve the milestone\r
     * @param rewardAmount Reward amount in wei\r
     * @param isPlanSpecific Whether this milestone is specific to a plan\r
     * @param planId Plan ID if plan-specific\r
     * @param isCorePlan Whether the plan is a core plan\r
     * @return milestoneId ID of the newly created milestone\r
     */\r
    function createReferralMilestone(\r
        uint256 referralCount,\r
        uint256 rewardAmount,\r
        bool isPlanSpecific,\r
        uint256 planId,\r
        bool isCorePlan\r
    ) \r
        external \r
        onlyOwner \r
        returns (uint256 milestoneId) \r
    {\r
        require(referralCount > 0, "Referral count must be greater than 0");\r
        require(rewardAmount > 0, "Reward amount must be greater than 0");\r
        \r
        milestoneId = nextMilestoneId++;\r
        \r
        referralMilestones[milestoneId] = ReferralMilestone({\r
            referralCount: referralCount,\r
            isPlanSpecific: isPlanSpecific,\r
            planId: planId,\r
            isCorePlan: isCorePlan,\r
            rewardAmount: rewardAmount,\r
            isActive: true\r
        });\r
        \r
        // Add to enumerable array\r
        if (!milestoneExists[milestoneId]) {\r
            allMilestoneIds.push(milestoneId);\r
            milestoneExists[milestoneId] = true;\r
        }\r
    }\r
    \r
    /**\r
     * @dev Toggle milestone activation status\r
     * @param milestoneId ID of the milestone\r
     * @param isActive New active status\r
     */\r
    function setMilestoneStatus(uint256 milestoneId, bool isActive)\r
        external\r
        onlyOwner\r
    {\r
        require(milestoneId > 0 && milestoneId < nextMilestoneId, "Invalid milestone ID");\r
        referralMilestones[milestoneId].isActive = isActive;\r
    }\r
    \r
    /**\r
     * @dev Update milestone referral count and reward amount\r
     * @param milestoneId ID of the milestone\r
     * @param referralCount New referral count\r
     * @param rewardAmount New reward amount\r
     */\r
    function updateMilestone(uint256 milestoneId, uint256 referralCount, uint256 rewardAmount)\r
        external\r
        onlyOwner\r
    {\r
        require(milestoneId > 0 && milestoneId < nextMilestoneId, "Invalid milestone ID");\r
        require(referralCount > 0, "Referral count must be greater than 0");\r
        require(rewardAmount > 0, "Reward amount must be greater than 0");\r
        \r
        ReferralMilestone storage milestone = referralMilestones[milestoneId];\r
        milestone.referralCount = referralCount;\r
        milestone.rewardAmount = rewardAmount;\r
    }\r
    \r
    /**\r
     * @dev Process referral reward for a purchase\r
     * @param referrer Referrer address\r
     * @param user User address\r
     * @param planId Plan ID\r
     * @param purchaseId Purchase ID\r
     * @param originalPrice Original price of the plan\r
     */\r
    function processReferralReward(\r
        address referrer,\r
        address user,\r
        uint256 planId,\r
        uint256 purchaseId,\r
        uint256 originalPrice\r
    ) \r
        external \r
        onlyAuthorized\r
    {\r
        // If the user doesn't yet have a recorded referrer, set it from the provided referrer\r
        if (userReferrer[user] == address(0) && user != referrer && referrer != address(0)) {\r
            userReferrer[user] = referrer;\r
        }\r
        address currentReferrer = referrer;\r
        bool isCorePlan = planId < 4; // Determine if it's a core plan based on ID\r
        \r
        uint8 level = 0;\r
        \r
        while (\r
            currentReferrer != address(0) && \r
            level < referralConfig.levels\r
        ) {\r
            uint8 rewardPercentage = referralConfig.rewards[level];\r
            \r
            uint256 rewardAmount = (originalPrice * rewardPercentage) / 100;\r
            \r
            ReferralStats storage stats = referralStats[currentReferrer];\r
            \r
            bool isNewReferral = true;\r
            for (uint256 i = 0; i < stats.referredUsers.length; i++) {\r
                if (stats.referredUsers[i] == user) {\r
                    isNewReferral = false;\r
                    break;\r
                }\r
            }\r
            \r
            if (isNewReferral) {\r
                stats.referredUsers.push(user);\r
                stats.referralLevel[user] = level;\r
            }\r
            \r
            stats.planReferralCounts[planId]++;\r
            \r
            stats.totalEarned += rewardAmount;\r
            \r
            referralRewards[currentReferrer] += rewardAmount;\r
            pendingRewards[currentReferrer] += rewardAmount;\r
            \r
            // Add to referrers array if first time\r
            if (!referrerExists[currentReferrer]) {\r
                allReferrers.push(currentReferrer);\r
                referrerExists[currentReferrer] = true;\r
            }\r
            \r
            _checkMilestones(currentReferrer, planId, isCorePlan);\r
            \r
            // Update referrer rank\r
            _updateReferrerRank(currentReferrer);\r
            \r
            emit ReferralPurchase(\r
                currentReferrer,\r
                user,\r
                planId,\r
                isCorePlan,\r
                purchaseId,\r
                level,\r
                rewardAmount\r
            );\r
            \r
            currentReferrer = userReferrer[currentReferrer];\r
            level++;\r
        }\r
    }\r
    \r
    // Deprecated: manual referrer setting removed. Referrer links are now established automatically when\r
    // a user makes a purchase using a referral code (the subscription contract passes the resolved referrer).\r
    \r
    /**\r
     * @dev Generate and register referral code for user (one transaction)\r
     * @param referralCode Unique referral code (generated off-chain from address)\r
     */\r
    function generateReferralCode(string calldata referralCode) external {\r
        require(bytes(referralCode).length >= 6 && bytes(referralCode).length <= 12, "Code must be 6-12 characters");\r
        require(bytes(addressToReferralCode[msg.sender]).length == 0, "Code already registered");\r
        require(referralCodeToAddress[referralCode] == address(0), "Code already taken");\r
        \r
        addressToReferralCode[msg.sender] = referralCode;\r
        referralCodeToAddress[referralCode] = msg.sender;\r
        \r
        emit ReferralCodeRegistered(msg.sender, referralCode);\r
    }\r
    \r
    /**\r
     * @dev Get referral code for an address\r
     * @param user User address\r
     * @return Referral code (empty if not registered)\r
     */\r
    function getReferralCode(address user) external view returns (string memory) {\r
        return addressToReferralCode[user];\r
    }\r
    \r
    /**\r
     * @dev Resolve referral code to address\r
     * @param referralCode Referral code\r
     * @return User address (zero address if not found)\r
     */\r
    function resolveReferralCode(string calldata referralCode) external view returns (address) {\r
        return referralCodeToAddress[referralCode];\r
    }\r
    \r
    /**\r
     * @dev Check if referral code is available\r
     * @param referralCode Referral code\r
     * @return Whether the code is available\r
     */\r
    function isReferralCodeAvailable(string calldata referralCode) external view returns (bool) {\r
        return referralCodeToAddress[referralCode] == address(0);\r
    }\r
    \r
    /**\r
     * @dev Check if referrer has achieved any milestones\r
     * @param referrer Referrer address\r
     * @param planId Plan ID of the purchase\r
     * @param isCorePlan Whether the plan is a core plan\r
     */\r
    function _checkMilestones(\r
        address referrer,\r
        uint256 planId,\r
        bool isCorePlan\r
    ) \r
        internal \r
    {\r
        ReferralStats storage stats = referralStats[referrer];\r
        \r
        for (uint256 i = 1; i < nextMilestoneId; i++) {\r
            ReferralMilestone storage milestone = referralMilestones[i];\r
            \r
            if (!milestone.isActive) continue;\r
            \r
            bool alreadyAchieved = false;\r
            for (uint256 j = 0; j < stats.achievedMilestones.length; j++) {\r
                if (stats.achievedMilestones[j] == i) {\r
                    alreadyAchieved = true;\r
                    break;\r
                }\r
            }\r
            \r
            if (alreadyAchieved) continue;\r
            \r
            if (milestone.isPlanSpecific) {\r
                if (milestone.isCorePlan != isCorePlan || milestone.planId != planId) {\r
                    continue;\r
                }\r
                \r
                if (stats.planReferralCounts[planId] >= milestone.referralCount) {\r
                    stats.achievedMilestones.push(i);\r
                    emit MilestoneAchieved(referrer, i, stats.planReferralCounts[planId], milestone.rewardAmount);\r
                }\r
            } else {\r
                uint256 totalReferrals = stats.referredUsers.length;\r
                if (totalReferrals >= milestone.referralCount) {\r
                    stats.achievedMilestones.push(i);\r
                    emit MilestoneAchieved(referrer, i, totalReferrals, milestone.rewardAmount);\r
                }\r
            }\r
        }\r
    }\r
    \r
    /**\r
     * @dev Get referral discount percentage\r
     * @return Discount percentage\r
     */\r
    function getReferralDiscount(address /* referrer */) external view returns (uint8) {\r
        return referralConfig.discounts[0];\r
    }\r
    \r
    /**\r
     * @dev Get referral reward percentage for a specific level\r
     * @param level The referral level (0-based index)\r
     * @return Reward percentage for the specified level\r
     */\r
    function getRewardPercentageForLevel(uint8 level) external view returns (uint8) {\r
        require(level < referralConfig.levels, "Invalid level");\r
        return referralConfig.rewards[level];\r
    }\r
    \r
    // ============= Referral Reward Functions =============\r
    /**\r
     * @dev Withdraw referral rewards (paid from SubscriptionSystem)\r
     */\r
    function withdrawReferralRewards() external whenNotPaused {\r
        uint256 amount = referralRewards[msg.sender];\r
        require(amount > 0, "No rewards to withdraw");\r
        require(subscriptionSystemAddress != address(0), "SubscriptionSystem not set");\r
        \r
        // Mark as withdrawn BEFORE transfer (prevent reentrancy)\r
        referralRewards[msg.sender] = 0;\r
        pendingRewards[msg.sender] = 0;\r
        \r
        referralStats[msg.sender].totalWithdrawn += amount;\r
        \r
        // Request payment from SubscriptionSystem\r
        ISubscriptionSystem(subscriptionSystemAddress).payReferralReward(msg.sender, amount);\r
        \r
        emit ReferralRewardWithdrawn(msg.sender, amount);\r
    }\r
    \r
    /**\r
     * @dev Claim milestone reward (paid from SubscriptionSystem)\r
     * @param milestoneId Milestone ID\r
     */\r
    function claimMilestoneReward(uint256 milestoneId) external whenNotPaused {\r
        require(milestoneId > 0 && milestoneId < nextMilestoneId, "Invalid milestone ID");\r
        require(!claimedMilestones[msg.sender][milestoneId], "Milestone already claimed");\r
        require(subscriptionSystemAddress != address(0), "SubscriptionSystem not set");\r
        \r
        ReferralMilestone storage milestone = referralMilestones[milestoneId];\r
        require(milestone.isActive, "Milestone is not active");\r
        \r
        ReferralStats storage stats = referralStats[msg.sender];\r
        \r
        bool hasAchieved = false;\r
        for (uint256 i = 0; i < stats.achievedMilestones.length; i++) {\r
            if (stats.achievedMilestones[i] == milestoneId) {\r
                hasAchieved = true;\r
                break;\r
            }\r
        }\r
        \r
        require(hasAchieved, "Milestone not achieved");\r
        \r
        // Mark as claimed BEFORE transfer (prevent reentrancy)\r
        claimedMilestones[msg.sender][milestoneId] = true;\r
        \r
        uint256 rewardAmount = milestone.rewardAmount;\r
        \r
        stats.totalWithdrawn += rewardAmount;\r
        \r
        // Request payment from SubscriptionSystem\r
        ISubscriptionSystem(subscriptionSystemAddress).payReferralReward(msg.sender, rewardAmount);\r
        \r
        emit MilestoneRewardClaimed(msg.sender, milestoneId, rewardAmount);\r
    }\r
    \r
    // ============= Query Functions =============\r
    /**\r
     * @dev Get referral statistics for a user\r
     * @param user User address\r
     * @return totalReferrals Total number of referrals\r
     * @return totalEarned Total amount earned\r
     * @return totalWithdrawn Total amount withdrawn\r
     * @return referralCount Array of referral counts by plan\r
     */\r
    function getReferralStats(address user) \r
        external \r
        view \r
        returns (\r
            uint256 totalReferrals,\r
            uint256 totalEarned,\r
            uint256 totalWithdrawn,\r
            uint256[] memory referralCount\r
        ) \r
    {\r
        ReferralStats storage stats = referralStats[user];\r
        \r
        totalReferrals = stats.referredUsers.length;\r
        totalEarned = stats.totalEarned;\r
        totalWithdrawn = stats.totalWithdrawn;\r
        \r
        // Use a dynamic array since we don't know plan IDs in this contract\r
        uint256[] memory planIds = new uint256[](100); // Example size, adjust as needed\r
        uint256 count = 0;\r
        \r
        for (uint256 i = 0; i < 4; i++) {\r
            if (stats.planReferralCounts[i] > 0) {\r
                planIds[count++] = i;\r
            }\r
        }\r
        \r
        for (uint256 i = 100; i < 1000; i++) { // Assuming max custom plan ID is 999\r
            if (stats.planReferralCounts[i] > 0) {\r
                planIds[count++] = i;\r
            }\r
        }\r
        \r
        referralCount = new uint256[](count);\r
        for (uint256 i = 0; i < count; i++) {\r
            referralCount[i] = stats.planReferralCounts[planIds[i]];\r
        }\r
    }\r
    \r
    /**\r
     * @dev Get referral rewards balance\r
     * @param referrer Referrer address\r
     * @return Pending rewards amount\r
     */\r
    function getReferralRewards(address referrer) external view returns (uint256) {\r
        return referralRewards[referrer];\r
    }\r
    \r
    /**\r
     * @dev Get user's achieved milestones\r
     * @param user User address\r
     * @return achievedMilestoneIds Array of achieved milestone IDs\r
     * @return claimedStatus Array of whether each milestone has been claimed\r
     */\r
    function getUserMilestones(address user)\r
        external\r
        view\r
        returns (\r
            uint256[] memory achievedMilestoneIds,\r
            bool[] memory claimedStatus\r
        )\r
    {\r
        ReferralStats storage stats = referralStats[user];\r
        uint256[] memory milestoneIds = stats.achievedMilestones;\r
        \r
        achievedMilestoneIds = milestoneIds;\r
        claimedStatus = new bool[](milestoneIds.length);\r
        \r
        for (uint256 i = 0; i < milestoneIds.length; i++) {\r
            claimedStatus[i] = claimedMilestones[user][milestoneIds[i]];\r
        }\r
    }\r
    \r
    /**\r
     * @dev Update referrer rank based on total referrals and earnings\r
     * @param referrer Referrer address\r
     */\r
    function _updateReferrerRank(address referrer) internal {\r
        ReferralStats storage stats = referralStats[referrer];\r
        \r
        uint256 oldRank = stats.rank;\r
        uint256 newRank = 0;\r
        \r
        // Ranking based on number of referrals and earned amount\r
        uint256 referralCount = stats.referredUsers.length;\r
        \r
        if (referralCount >= 100) {\r
            newRank = 5; // Diamond\r
        } else if (referralCount >= 1000) {\r
            newRank = 4; // Platinum\r
        } else if (referralCount >= 250) {\r
            newRank = 3; // Gold\r
        } else if (referralCount >= 50) {\r
            newRank = 2; // Silver\r
        } else if (referralCount >= 5) {\r
            newRank = 1; // Bronze\r
        }\r
        \r
        // If rank has changed, we update it\r
        if (newRank != oldRank) {\r
            stats.rank = newRank;\r
            emit RankUpdated(referrer, oldRank, newRank);\r
        }\r
    }\r
    \r
    /**\r
     * @dev Update all referrers ranks (for admin use)\r
     * @param referrers Array of referrer addresses\r
     */\r
    function updateReferrersRanks(address[] calldata referrers) external onlyOwner {\r
        for (uint256 i = 0; i < referrers.length; i++) {\r
            _updateReferrerRank(referrers[i]);\r
        }\r
    }\r
    \r
    /**\r
     * @dev Get referrer rank\r
     * @param referrer Referrer address\r
     * @return Referrer rank (0-5)\r
     */\r
    function getReferrerRank(address referrer) external view returns (uint256) {\r
        return referralStats[referrer].rank;\r
    }\r
    \r
    // ============= Enumeration Functions (No Block Scanning) =============\r
    /**\r
     * @dev Get all milestone IDs\r
     * @return Array of all milestone IDs\r
     */\r
    function getAllMilestoneIds() external view returns (uint256[] memory) {\r
        return allMilestoneIds;\r
    }\r
    \r
    /**\r
     * @dev Get total number of milestones\r
     * @return Total milestone count\r
     */\r
    function getMilestoneCount() external view returns (uint256) {\r
        return allMilestoneIds.length;\r
    }\r
    \r
    /**\r
     * @dev Get complete milestone details\r
     * @param milestoneId Milestone ID\r
     * @return referralCount Required referral count\r
     * @return isPlanSpecific Whether plan specific\r
     * @return planId Plan ID if plan specific\r
     * @return isCorePlan Whether core plan\r
     * @return rewardAmount Reward amount\r
     * @return isActive Whether active\r
     */\r
    function getMilestoneDetails(uint256 milestoneId)\r
        external\r
        view\r
        returns (\r
            uint256 referralCount,\r
            bool isPlanSpecific,\r
            uint256 planId,\r
            bool isCorePlan,\r
            uint256 rewardAmount,\r
            bool isActive\r
        )\r
    {\r
        require(milestoneId > 0 && milestoneId < nextMilestoneId, "Invalid milestone ID");\r
        ReferralMilestone storage milestone = referralMilestones[milestoneId];\r
        return (\r
            milestone.referralCount,\r
            milestone.isPlanSpecific,\r
            milestone.planId,\r
            milestone.isCorePlan,\r
            milestone.rewardAmount,\r
            milestone.isActive\r
        );\r
    }\r
    \r
    /**\r
     * @dev Get all referrers\r
     * @return Array of all referrer addresses\r
     */\r
    function getAllReferrers() external view returns (address[] memory) {\r
        return allReferrers;\r
    }\r
    \r
    /**\r
     * @dev Get total number of referrers\r
     * @return Total referrer count\r
     */\r
    function getReferrerCount() external view returns (uint256) {\r
        return allReferrers.length;\r
    }\r
    \r
    /**\r
     * @dev Get user's referred users list\r
     * @param user User address\r
     * @return Array of referred user addresses\r
     */\r
    function getReferredUsers(address user) external view returns (address[] memory) {\r
        return referralStats[user].referredUsers;\r
    }\r
    \r
    /**\r
     * @dev Get complete referral reward info\r
     * @param referrer Referrer address\r
     * @return totalEarned Total amount earned\r
     * @return totalWithdrawn Total amount withdrawn\r
     * @return pendingAmount Pending withdrawal amount\r
     * @return availableAmount Available to withdraw now\r
     */\r
    function getReferralRewardDetails(address referrer)\r
        external\r
        view\r
        returns (\r
            uint256 totalEarned,\r
            uint256 totalWithdrawn,\r
            uint256 pendingAmount,\r
            uint256 availableAmount\r
        )\r
    {\r
        ReferralStats storage stats = referralStats[referrer];\r
        totalEarned = stats.totalEarned;\r
        totalWithdrawn = stats.totalWithdrawn;\r
        pendingAmount = pendingRewards[referrer];\r
        availableAmount = referralRewards[referrer];\r
    }\r
    \r
    /**\r
     * @dev Get user's complete referral info\r
     * @param user User address\r
     * @return referredCount Total referred users count\r
     * @return totalEarned Total earned amount\r
     * @return totalWithdrawn Total withdrawn amount\r
     * @return availableRewards Available rewards to withdraw\r
     * @return rank User rank\r
     * @return achievedMilestoneCount Number of achieved milestones\r
     */\r
    function getUserReferralInfo(address user)\r
        external\r
        view\r
        returns (\r
            uint256 referredCount,\r
            uint256 totalEarned,\r
            uint256 totalWithdrawn,\r
            uint256 availableRewards,\r
            uint256 rank,\r
            uint256 achievedMilestoneCount\r
        )\r
    {\r
        ReferralStats storage stats = referralStats[user];\r
        return (\r
            stats.referredUsers.length,\r
            stats.totalEarned,\r
            stats.totalWithdrawn,\r
            referralRewards[user],\r
            stats.rank,\r
            stats.achievedMilestones.length\r
        );\r
    }\r
    \r
    /**\r
     * @dev Receive function to accept ETH payments\r
     */\r
    receive() external payable {}\r
}"
    }
  },
  "settings": {
    "optimizer": {
      "enabled": false,
      "runs": 200
    },
    "outputSelection": {
      "*": {
        "*": [
          "evm.bytecode",
          "evm.deployedBytecode",
          "devdoc",
          "userdoc",
          "metadata",
          "abi"
        ]
      }
    },
    "remappings": [],
    "evmVersion": "cancun"
  }
}}

Tags:
Multisig, Multi-Signature, Factory|addr:0x38f70984b8c42d0d1ff7945be69171d7cbe29470|verified:true|block:23678996|tx:0xf880e83a10ee2f075556f47f53d7f18c5742b89e8e7d8416d7e10ee3f027d4fc|first_check:1761727328

Submitted on: 2025-10-29 09:42:08

Comments

Log in to comment.

No comments yet.