Contract Source Code (Solidity Standard Json-Input format)
File 1 of 1 : Referrals.sol
// SPDX-License-Identifier: MIT
pragma solidity 0.8.10;
/// @title Referral System
/// @notice Manages a 10-level referral structure for an investment plan
/// @dev Only the designated `investmentPlan` contract can register new members
contract Referrals {
/// @notice Address of the investment plan contract allowed to call `addMember`
address investmentPlan;
/// @notice Structure to store team member count per level
struct Team{
uint256 member;
}
/// @notice Mapping of each user to their direct sponsor
mapping(address => address) public mapSponsor;
/// @notice Mapping of each address to their team info (up to 10 levels deep)
mapping(address => Team[10]) public mapTeam;
/// @notice Mapping to track team members by level (e.g. level 0 = direct referrals)
mapping(address => mapping(uint256 => address[])) public mapTeamAddress;
/// @notice Emitted when a new referral is registered
/// @param investor The newly added member
/// @param sponsor The sponsor/referrer of the investor
event TeamMember(address investor, address sponsor);
/// @notice Sets the investment plan contract
/// @param plan The address allowed to call `addMember`
constructor(address plan) {
investmentPlan = address(plan);
}
/// @notice Adds a new referral relationship
/// @dev Only callable by `investmentPlan`
/// @param investor The new user being added
/// @param sponsor The address referring the new user
function addMember(address investor, address sponsor) external {
require(address(msg.sender) == address(investmentPlan), "Incorrect request");
require(address(investor) != address(0) && address(sponsor) != address(0), "Zero address");
require(address(investor) != address(sponsor), "Referrer different required");
require(mapSponsor[address(investor)] == address(0), "Member already added in list");
mapSponsor[address(investor)] = address(sponsor);
enterTeam(address(investor));
emit TeamMember(investor, sponsor);
}
/// @notice Internal function to update team stats up the 10-level referral tree
/// @param investor The address whose sponsor tree is updated
function enterTeam(address investor) internal {
address nextSponsor = mapSponsor[address(investor)];
for(uint256 i= 0; i < 10; i++) {
if(address(nextSponsor) != address(0)) {
mapTeamAddress[address(nextSponsor)][i].push(address(investor));
mapTeam[address(nextSponsor)][i].member += 1;
} else {
break;
}
nextSponsor = address(mapSponsor[address(nextSponsor)]);
}
}
/// @notice Returns the number of referrals at a given level for a sponsor
/// @param sponsor The address whose referral tree is queried
/// @param level The depth level (0 to 9)
/// @return The number of members at the specified level
function getTeam(address sponsor, uint256 level) external view returns(uint256){
return mapTeam[address(sponsor)][level].member;
}
/// @notice Gets the sponsor of a given team member
/// @param teamMember The address of the team member
/// @return The sponsor address of the given member
function getSponsor(address teamMember) external view returns (address) {
return mapSponsor[address(teamMember)];
}
}