Business LogicReferrals System

Referrals System

Overview

Wafra implements a sophisticated on-chain referral system that incentivizes user growth through automated fee sharing. The system operates entirely on-chain through smart contracts, providing transparent and trustless reward distribution based on proportional holdings and yield generation.

On-Chain Referral Architecture

Smart Contract Implementation

Core Contract Structure:

abstract contract FundReferrals is FundERC20 {
    // Referral data structure with timestamp tracking
    struct ReferralData {
        address referrer;
        uint256 createdAt;
    }
 
    // Mappings for referral relationships
    mapping(address => ReferralData) private referralData;
    using EnumerableMap for EnumerableMap.AddressToAddressMap;
    EnumerableMap.AddressToAddressMap private referrals;
 
    // Rate configuration
    uint256 public referralRate; // 25% of fees (250000 / 1e6)
    uint256 public referredRate; // 5% discount (50000 / 1e6)
}

Referral Registration Process

On-Chain Registration:

function addReferral(address referrer) public {
    require(referrer != msg.sender, "Cannot refer yourself");
    require(referrer != address(0), "Invalid referrer address");
    require(!referrals.contains(msg.sender), "Referral already exists");
 
    uint256 timestamp = block.timestamp;
 
    // Store in both mappings for efficiency
    referrals.set(msg.sender, referrer);
    referralData[msg.sender] = ReferralData(referrer, timestamp);
 
    emit ReferralAdded(referrer, msg.sender, timestamp);
}

Registration Requirements:

  • Self-Referral Prevention: Users cannot refer themselves
  • Unique Relationships: Each user can only have one referrer
  • Immutable Links: Referral relationships cannot be changed once established
  • Timestamp Tracking: Creation time recorded for potential time-based rules

Referral Data Management

Data Retrieval Functions:

function getReferralInfo(address referred)
    external
    view
    returns (address referrer, uint256 createdAt, bool exists)
{
    if (!referrals.contains(referred)) {
        return (address(0), 0, false);
    }
 
    ReferralData memory data = referralData[referred];
    return (data.referrer, data.createdAt, true);
}
 
function getReferrals() public view returns (Referral[] memory) {
    address[] memory allReferrals = referrals.keys();
    uint256 length = allReferrals.length;
 
    Referral[] memory _referrals = new Referral[](length);
    for (uint256 i = 0; i < length; i++) {
        address referred = allReferrals[i];
        _referrals[i] = Referral(
            referred,
            referrals.get(referred),
            referralData[referred].createdAt
        );
    }
    return _referrals;
}

Fee Distribution Mechanism

Automated Distribution System

Distribution Process:

function distribute(uint256 fees) internal {
    if (!_validateDistribution(fees)) return;
 
    uint256 balance = balanceOf(address(this));
    uint256 actualFees = fees > balance ? balance : fees;
 
    // Process all referral relationships
    uint256 distributedFees = _processReferralDistributions(actualFees);
 
    // Send remaining fees to treasury
    _sendRemainingToTreasury(actualFees, distributedFees);
 
    emit Distribution(distributedFees);
}

Proportional Reward Calculation

User Share Calculation:

function _distributeForReferralPair(
    address referred,
    address referrer,
    uint256 createdAt,
    uint256 balance,
    uint256 supply,
    uint256 fees
) private returns (uint256) {
    // Calculate user's proportional share of total fees
    uint256 userShare = (balance * fees) / supply;
    if (userShare == 0) return 0;
 
    uint256 totalDistributed = 0;
 
    // Calculate and distribute referrer rewards (25% of user's share)
    uint256 referralShare = (userShare * referralRate) / 1e6;
    if (referralShare > 0) {
        _transferScaled(address(this), referrer, referralShare);
        emit ReferralRewardSent(referrer, referred, referralShare);
        totalDistributed += referralShare;
    }
 
    // Calculate and distribute referred user discount (5% of user's share)
    uint256 referredShare = (userShare * referredRate) / 1e6;
    if (referredShare > 0) {
        _transferScaled(address(this), referred, referredShare);
        emit ReferredRewardSent(referred, referredShare);
        totalDistributed += referredShare;
    }
 
    return totalDistributed;
}

Rate Configuration System

Current Reward Structure:

// Rate configuration (parts per million)
uint256 public referralRate = 250000;  // 25% of collected fees to referrer
uint256 public referredRate = 50000;   // 5% discount to referred user
 
// Based on 2% APY management fee:
// Referrer receives: ~0.5% APY on referred user's balance
// Referred user receives: ~0.1% APY discount on their fees

Rate Management Functions:

function setReferralRate(uint256 _newRate) external onlyOwner {
    require(_newRate <= 500000, "Rate cannot exceed 50%"); // 50% max
    uint256 oldRate = referralRate;
    referralRate = _newRate;
    emit ReferralRateUpdated(oldRate, _newRate);
}
 
function setReferredRate(uint256 _newRate) external onlyOwner {
    require(_newRate <= 100000, "Rate cannot exceed 10%"); // 10% max
    uint256 oldRate = referredRate;
    referredRate = _newRate;
    emit ReferredRateUpdated(oldRate, _newRate);
}

Off-Chain Referral Management

Database Integration

Referral Tracking Schema:

model Referral {
  id            Int      @id @default(autoincrement())
  referredPhone String   // Phone number of referred user
  userId        String   // ID of referrer
  user          User     @relation(fields: [userId], references: [id])
  accepted      Boolean  @default(false) // Whether on-chain registration occurred
  createdAt     DateTime @default(now())
  updatedAt     DateTime @updatedAt
 
  @@unique([userId, referredPhone])
  @@index([userId])
  @@index([referredPhone])
}

Waitlist Referral System

Pre-Launch Referrals:

model Waitlist {
  id           Int      @id @default(autoincrement())
  email        String   @unique
  createdAt    DateTime @default(now())
  referralCode String?  // Optional referral code
 
  @@index([referralCode])
}
 
model WaitlistReferral {
  id           Int      @id @default(autoincrement())
  name         String
  referralCode String   @unique
  createdAt    DateTime @default(now())
 
  @@index([referralCode])
}

API Integration

tRPC Endpoints:

export const referralRouter = router({
  // Get user's referral status
  getReferralStatus: protectedProcedure.query(async ({ ctx }) => {
    const user = ctx.session.user;
    return await getReferralInfo(user.walletAddress);
  }),
 
  // Submit referral relationship
  submitReferral: protectedProcedure
    .input(
      z.object({
        referredPhone: z.string(),
      })
    )
    .mutation(async ({ input, ctx }) => {
      return await createReferralRelationship(ctx.session.user, input);
    }),
 
  // Accept referral (triggers on-chain registration)
  acceptReferral: protectedProcedure
    .input(
      z.object({
        referrerAddress: z.string(),
      })
    )
    .mutation(async ({ input, ctx }) => {
      return await acceptReferralOnChain(ctx.session.user, input);
    }),
});

Transaction Integration

Client-Side Referral Registration

Transaction Builder Implementation:

export class SetReferralTransactionBuilder extends TransactionBuilder<SetReferralParams> {
  getTransactionType(): string {
    return "setReferral";
  }
 
  validateParams(params: SetReferralParams): boolean {
    return (
      ethers.isAddress(params.referrerAddress) &&
      params.referrerAddress !== ethers.ZeroAddress
    );
  }
 
  async buildTransaction(
    params: SetReferralParams,
    context: ExecutionContext
  ): Promise<TransactionData> {
    return {
      to: context.fundAddress,
      value: "0",
      data: encodeFunctionData({
        abi: fundAbi,
        functionName: "addReferral",
        args: [params.referrerAddress as `0x${string}`],
      }),
      operation: 0, // Call operation
    };
  }
}

Mobile App Integration

Referral Hook:

export function useReferrals() {
  const { user } = useAuth();
  const trpc = api.useContext();
 
  const submitReferral = useMutation({
    mutationFn: async (data: ReferralSubmissionData) => {
      return await trpc.referral.submitReferral.mutate(data);
    },
    onSuccess: () => {
      // Trigger on-chain registration transaction
      triggerReferralTransaction();
    },
  });
 
  const acceptReferral = useMutation({
    mutationFn: async (data: ReferralAcceptanceData) => {
      const { prepareSetReferralTransaction } = await import(
        "@wafra/transactions"
      );
 
      // Prepare and execute on-chain transaction
      const result = await prepareSetReferralTransaction(
        { referrerAddress: data.referrerAddress },
        await getTransactionContext()
      );
 
      return await executeTransaction(result);
    },
    onSuccess: () => {
      // Update local state and refresh data
      trpc.referral.getReferralStatus.invalidate();
    },
  });
 
  return { submitReferral, acceptReferral };
}

Reward Economics

Yield-Based Rewards

Current Reward Structure:

interface ReferralRewards {
  // Management fee: 2% APY on total fund value
  managementFee: {
    annualRate: "2%";
    weeklyRate: "0.0377%";
  };
 
  // Referrer rewards: 25% of referred user's fees
  referrerReward: {
    percentageOfFees: "25%";
    effectiveAPY: "~0.5%"; // On referred user's balance
  };
 
  // Referred user discount: 5% reduction in fees
  referredDiscount: {
    percentageOfFees: "5%";
    effectiveAPY: "~0.1%"; // Discount on their fees
  };
 
  // Treasury allocation: Remaining 70% of fees
  treasuryAllocation: {
    percentageOfFees: "70%";
    purpose: "Protocol development and operations";
  };
}

Proportional Distribution Model

Balance-Weighted Rewards:

// Example calculation for $10,000 referred user balance
// Weekly management fee: $10,000 * 0.0377% = $3.77
 
// Referrer reward: $3.77 * 25% = $0.94 (weekly)
// Annual referrer reward: $0.94 * 52 = ~$49 (0.49% APY on referred balance)
 
// Referred user discount: $3.77 * 5% = $0.19 (weekly)
// Annual user discount: $0.19 * 52 = ~$10 (0.1% APY discount)
 
// Treasury allocation: $3.77 * 70% = $2.64 (weekly)

Scalability Benefits

Network Effects:

  • Exponential Growth: Each referred user can refer others
  • Compound Rewards: Referrers benefit from their network’s growth
  • Self-Sustaining: Reduced marketing costs through organic growth
  • Quality Incentive: Rewards aligned with user retention and deposits

Security & Safety Features

Smart Contract Security

Protection Mechanisms:

// Prevent manipulation attempts
error SelfReferral();
error ZeroAddressReferrer();
error ReferralAlreadyExists();
error InsufficientFundTokenBalance(uint256 available, uint256 required);
 
// Validation functions
function _validateDistribution(uint256 fees) private view returns (bool) {
    uint256 supply = totalSupply();
    if (supply == 0) return false;
 
    uint256 balance = balanceOf(address(this));
    uint256 adjustedFees = (fees / PRECISION) * PRECISION;
    if (balance < adjustedFees) {
        revert InsufficientFundTokenBalance(balance, fees);
    }
 
    return true;
}

Rate Limits & Constraints

Configurable Safety Limits:

// Maximum referral rates to prevent excessive rewards
uint256 public constant MAX_REFERRAL_RATE = 500000; // 50% maximum
uint256 public constant MAX_REFERRED_RATE = 100000; // 10% maximum
 
function setReferralRate(uint256 _newRate) external onlyOwner {
    require(_newRate <= MAX_REFERRAL_RATE, "Rate exceeds maximum");
    referralRate = _newRate;
}

Audit Trail & Transparency

Event Logging:

event ReferralAdded(address indexed referrer, address indexed referred, uint256 timestamp);
event ReferralRewardSent(address indexed referrer, address indexed referred, uint256 amount);
event ReferredRewardSent(address indexed referred, uint256 amount);
event Distribution(uint256 distributedFees);
event ReferralRateUpdated(uint256 oldRate, uint256 newRate);

Analytics & Monitoring

Performance Metrics

Key Performance Indicators:

interface ReferralAnalytics {
  totalReferrals: number;
  activeReferrers: number;
  averageReferralsPerUser: number;
  totalRewardsDistributed: bigint;
  monthlyGrowthRate: number;
 
  topReferrers: {
    address: string;
    referralCount: number;
    totalRewards: bigint;
  }[];
 
  rewardDistribution: {
    referrerRewards: bigint;
    userDiscounts: bigint;
    treasuryAllocation: bigint;
  };
}

Real-Time Tracking

Dashboard Metrics:

export class ReferralAnalyticsService {
  async getReferralMetrics(): Promise<ReferralMetrics> {
    // Get on-chain referral data
    const onChainReferrals = await fundContract.read.getReferrals();
 
    // Calculate reward distributions
    const rewardData = await this.calculateRewardDistributions();
 
    // Track growth metrics
    const growthMetrics = await this.calculateGrowthMetrics();
 
    return {
      totalReferrals: onChainReferrals.length,
      activeReferrers: this.countActiveReferrers(onChainReferrals),
      rewardsSummary: rewardData,
      growthTrends: growthMetrics,
    };
  }
 
  private async calculateRewardDistributions(): Promise<RewardSummary> {
    // Query Distribution events from smart contract
    const events = await this.getDistributionEvents();
 
    return events.reduce(
      (acc, event) => {
        acc.totalDistributed += event.amount;
        acc.referrerRewards += event.referrerRewards;
        acc.userDiscounts += event.userDiscounts;
        return acc;
      },
      {
        totalDistributed: 0n,
        referrerRewards: 0n,
        userDiscounts: 0n,
      }
    );
  }
}

Future Enhancements

Advanced Features

Planned Improvements:

  • Tiered Rewards: Higher rates for high-volume referrers
  • Time-Based Bonuses: Additional rewards for long-term referrals
  • Group Referrals: Special programs for communities and organizations
  • Cross-Chain Referrals: Support for multi-chain referral relationships

Governance Integration

Decentralized Management:

  • Community Voting: Rate adjustments through governance proposals
  • Dynamic Rates: Algorithm-based rate optimization
  • Referral Contests: Community-driven growth campaigns
  • Reward Pools: Special allocation for referral incentives

This referral system provides a robust foundation for organic growth while maintaining transparency, security, and fair reward distribution through automated smart contract execution.