一个模块化用于记录邀请关系的合约,可自由接入到其他合约

一个模块化设计,可用于记录邀请关系的合约

pragma solidity >=0.8.0;

interface IInvite {
    function addRecord(address) external returns(bool);
    function getParents(address) external view returns(address[2] memory);
    function getChilds(address) external view returns(address[] memory);
    function getInviteNum(address) external view returns(uint256[2] memory);
}
// SPDX-License-Identifier: MIT
pragma solidity >=0.8.0;

import './interfaces/IInvite.sol'; // 注意路径,我把所有的接口合约都放在了interfaces目录下

contract Invite is IInvite {
    address public factory; // 记录合约发布者地址
    mapping(address => address[]) public inviteRecords; // 邀请记录  邀请人地址 => 被邀请人地址数组
    mapping(address => address) public parents; // 记录上级  我的地址 => 我的上级地址
    mapping(address => uint256[2]) public inviteNumRecords; // 记录邀请数量  我的地址 => [邀请的一级用户数量,邀请的二级用户数量]
    address public firstAddress; // 合约发布时需要初始化第一个用户地址,否则无法往下绑定用户
    uint256 public totalPeople;

    constructor() {
        factory = msg.sender; // 记录合约发布人地址
        firstAddress = 0x9C28a16CC5d22E6D18B2201a3B51faf89ATg6BA; // 初始化第一个用户地址,发布前改成自己项目用的地址
    }

    // 绑定上级。在Dapp中的合适位置,让用户点击按钮或者自动弹出授权,要求绑定一个上级(绑定前要做是否已经绑定上级的验证)
    function addRecord(address parentAddress) external override returns(bool){
        require(parentAddress != address(0), 'Invite: 0001'); // 不允许上级地址为0地址
        address myAddress = msg.sender; // 重新赋个值,没什么实际意义,单纯为了看着舒服
        require(parentAddress != myAddress, 'Invite: 0002');// 不允许自己的上级是自己
        // 验证要绑定的上级是否有上级,只有有上级的用户,才能被绑定为上级(firstAddress除外)。如果没有此验证,那么就可以随意拿一个地址绑定成上级了
        require(parents[parentAddress] != address(0) || parentAddress == firstAddress, 'Invite: 0003');
        // 判断是否已经绑定过上级
        if(parents[myAddress] != address(0)){
            // 已有上级,返回一个true
            return true;
        }
        // 记录邀请关系,parentAddress邀请了myAddress,给parentAddress对应的数组增加一个记录
        inviteRecords[parentAddress].push(myAddress);
        // 记录我的上级
        parents[myAddress] = parentAddress;
        // 统计数量
        inviteNumRecords[parentAddress][0]++;// parentAddress的一级邀请数+1
        inviteNumRecords[parents[parentAddress]][1]++; // 我的上上级(也就是parentAddress的上级)的二级邀请数+1
        totalPeople++; // 总用户数+1
        return true;
    }

    // 获取指定用户的两个上级地址,其他合约可以调用此接口,进行分佣等操作
    function getParents(address myAddress) external view override returns(address[2] memory myParents){
        // 获取直接上级
        address firstParent = parents[myAddress];
        // 获取上上级
        address secondParent;
        // 先验证一下是否有直接上级
        if(firstParent != address(0)){
            secondParent = parents[firstParent];
        }
        // 以数组形式返回
        myParents = [firstParent, secondParent];
    }

    // 获取我的全部一级下级。如果想获取多层,遍历就可以(考虑过预排序遍历树快速获取全部下级,发现难度比较大,如果有更好的方法,欢迎指点)
    function getChilds(address myAddress) external view override returns(address[] memory childs){
        childs = inviteRecords[myAddress];
    }

    // 我的邀请数量。其他合约可以调用此接口,进行统计分佣等其他操作
    function getInviteNum(address myAddress) external view override returns(uint256[2] memory){
        // 返回我的直接邀请数量和二级邀请数量
        return inviteNumRecords[myAddress];
    }

    // 修改第一个用户地址,这个接口可有可无,不重要,看自己的需求
    function setFirstAddress(address _firstAddress) external virtual returns(bool){
        require(msg.sender == factory, 'Invite: 0009'); // 只有合约发布者能修改
        firstAddress = _firstAddress;
        return true;
    }
}
点赞 2
收藏 7
分享
本文参与登链社区写作激励计划 ,好文好收益,欢迎正在阅读的你也加入。

0 条评论

请先 登录 后评论
快乐的程序猿
快乐的程序猿
软件开发v colorful_cloud_sea