MAXFI系统开发源码和核心智能合约分享

第一章:合约系统架构总览​​

MAXFI的智能合约系统将采用模块化设计,各合约职责分离,通过接口相互调用,以提高安全性、可维护性和可升级性。整个系统架构如下所示:

image

 

  • ​​MaxFiMain合约​​:用户主要交互的合约。它负责将函数调用委托给相应的模块合约,并管理各模块间的地址引用。
  • ​​MAX代币合约 (MAXToken)​​:标准的ERC-20代币实现,负责MAX代币的转账、余额查询等基本功能。
  • ​​创世节点销售合约 (NodeSale)​​:处理创世节点的购买逻辑,包括限额检查、支付接收和节点资格分配。
  • ​​质押收益合约 (StakingPool)​​:核心业务逻辑合约,管理用户的双仓(质押仓、创世仓),计算并发放收益。
  • ​​推荐奖励合约 (ReferralSystem)​​:记录推荐关系,并在成功购买节点时分配推荐奖励。

第二章:合约详细实现与代码分析​​

以下将分节详细描述每个合约的关键代码结构。我们将使用Solidity语言(0.8.x及以上版本,强调安全性)进行编写。

​​2.1 MAX代币合约 (MAXToken.sol)​​

这是一个标准的ERC-20合约,但增加了铸造(Mint)功能和权限管理,用于项目初始发行。

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

import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import "@openzeppelin/contracts/access/Ownable.sol";

contract MAXToken is ERC20, Ownable {
    // 代币总供应量:3亿枚,但考虑到小数位(默认18位),需要乘以10^18
    uint256 public constant MAX_SUPPLY = 300000000 * 10**18;

    // 分配地址:在实际部署时需要设置
    address public treasuryWallet; // 国库地址
    address public incentivePoolWallet; // 激励池地址
    address public managementPoolWallet; // 管理池地址
    address public otherWallet; // 其他用途地址

    constructor(
        address _treasury,
        address _incentivePool,
        address _managementPool,
        address _other
    ) ERC20("MAXFI Token", "MAX") {
        require(_treasury != address(0) && _incentivePool != address(0), "Invalid address");
        treasuryWallet = _treasury;
        incentivePoolWallet = _incentivePool;
        managementPoolWallet = _managementPool;
        otherWallet = _other;

        // 根据图片中的分配方案一次性铸造全部代币
        _mint(treasuryWallet, 36950000 * 10**18);       // 国库
        _mint(incentivePoolWallet, 132360000 * 10**18); // 激励池
        _mint(managementPoolWallet, 71100000 * 10**18); // 管理池
        _mint(otherWallet, 59700000 * 10**18);          // 其他 (注意:97,700,000 - 37,950,000? 需明确分配)
        // 确保总量为3亿
        assert(totalSupply() == MAX_SUPPLY);
    }

    // 可增加交易税等功能,此处为简化版标准代币
}

2.2 创世节点销售合约 (NodeSale.sol)​​

此合约是用户购买创世节点的入口,包含核心的业务规则校验。

pragma solidity ^0.8.19;

import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "./MAXToken.sol";
import "./IStakingPool.sol";
import "./IReferralSystem.sol";

contract NodeSale is Ownable {
    IERC20 public usdtToken; // 用于支付的稳定币合约地址(例如USDT)
    IStakingPool public stakingPool;
    IReferralSystem public referralSystem;

    uint256 public constant NODE_PRICE = 100 * 10**6; // 100 USDT (假设USDT有6位小数)
    uint256 public constant MAX_NODES = 2000;
    uint256 public totalNodesSold;

    // 记录地址是否已购买节点
    mapping(address => bool) public isNodeHolder;
    // 记录已购买节点的地址列表
    address[] public nodeHolders;

    event NodePurchased(address indexed buyer, address indexed referrer, uint256 nodeId);

    constructor(address _usdtAddress, address _stakingPool, address _referralSystem) {
        usdtToken = IERC20(_usdtAddress);
        stakingPool = IStakingPool(_stakingPool);
        referralSystem = IReferralSystem(_referralSystem);
    }

    /**
     * @dev 用户购买创世节点的主要函数
     * @param _referrer 推荐人地址(如果无可为0x0)
     */
    function purchaseNode(address _referrer) external {
        require(totalNodesSold < MAX_NODES, "All genesis nodes sold out");
        require(!isNodeHolder[msg.sender], "Already purchased a node");
        require(msg.sender != _referrer, "Cannot refer yourself");

        // 检查用户是否已授权足够的USDT给本合约
        require(usdtToken.allowance(msg.sender, address(this)) >= NODE_PRICE, "Insufficient USDT allowance");
        // 将USDT从用户转账到本合约(实际项目中,通常转入一个特定的财政钱包)
        require(usdtToken.transferFrom(msg.sender, address(this), NODE_PRICE), "USDT transfer failed");

        // 更新状态
        totalNodesSold++;
        isNodeHolder[msg.sender] = true;
        nodeHolders.push(msg.sender);
        uint256 nodeId = totalNodesSold; // 节点ID从1开始

        // 调用质押合约,为用户创建双仓(100U质押仓 + 100U创世仓)
        stakingPool.createGenesisStake(msg.sender, NODE_PRICE); // 传递100 USDT的价值

        // 处理推荐关系与奖励分配
        if (_referrer != address(0) && isNodeHolder[_referrer]) {
            referralSystem.handleReferral(_referrer, msg.sender, NODE_PRICE);
        }

        emit NodePurchased(msg.sender, _referrer, nodeId);
    }

    // 所有者函数:用于提取合约中积累的USDT
    function withdrawUSDT(address _to) external onlyOwner {
        uint256 balance = usdtToken.balanceOf(address(this));
        require(balance > 0, "No USDT to withdraw");
        require(usdtToken.transfer(_to, balance));
    }
}

2.3 质押收益合约 (StakingPool.sol)​​

这是系统中最复杂的合约,负责管理仓位、计算收益和处理本金取回。

pragma solidity ^0.8.19;

import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/security/ReentrancyGuard.sol";
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";

contract StakingPool is Ownable, ReentrancyGuard {
    IERC20 public maxToken;

    // 基础收益率(每日0.6%,以分子形式表示,分母为10000,即60/10000=0.6%)
    uint256 public constant BASE_RATE = 60;
    uint256 public constant RATE_DENOMINATOR = 10000;
    uint256 public constant RATE_INCREASE_INTERVAL = 2 days; // 48小时
    uint256 public constant RATE_INCREASE_AMOUNT = 10; // 每48小时增加0.1%

    uint256 public systemLaunchTime;
    uint256 public currentGlobalRate = BASE_RATE;

    struct Stake {
        uint256 stakingAmount;    // 质押仓位金额(100 USDT等值的MAX)
        uint256 genesisAmount;    // 创世仓位金额(100 USDT等值的MAX)
        uint256 lastUpdateTime;   // 最后一次更新收益的时间戳
        bool isActive;            // 节点资格是否有效(取回本金后失效)
    }

    mapping(address => Stake) public stakes;

    event Staked(address indexed user, uint256 stakingAmount, uint256 genesisAmount);
    event RewardClaimed(address indexed user, uint256 reward);
    event Unstaked(address indexed user, uint256 amount);

    modifier onlyAfterLaunch {
        require(systemLaunchTime != 0 && block.timestamp >= systemLaunchTime, "System not launched");
        _;
    }

    constructor(address _maxTokenAddress) {
        maxToken = IERC20(_maxTokenAddress);
    }

    // 由NodeSale合约调用的函数,为用户初始化质押
    function createGenesisStake(address _user, uint256 _usdtAmount) external onlyOwner {
        require(_usdtAmount == 100 * 10**6, "Invalid stake amount"); // 必须为100USDT
        require(stakes[_user].stakingAmount == 0, "Stake already exists");

        // 假设1USDT = 1 MAX(初始定价),将USDT价值映射为MAX代币数量进行记录
        // 实际项目中,这里可能需要一个预言机来确定USDT/MAX的汇率,此处简化处理
        uint256 stakeAmountInMAX = _usdtAmount; // 简化:1:1锚定

        stakes[_user] = Stake({
            stakingAmount: stakeAmountInMAX,
            genesisAmount: stakeAmountInMAX, // 赠送等额的创世仓位
            lastUpdateTime: block.timestamp,
            isActive: true
        });

        // 更新全局收益率(基于系统运行时间)
        _updateGlobalRate();
        emit Staked(_user, stakeAmountInMAX, stakeAmountInMAX);
    }

    /**
     * @dev 计算用户应得的累计收益(包括质押仓和创世仓)
     */
    function calculateRewards(address _user) public view returns (uint256) {
        Stake memory userStake = stakes[_user];
        if (userStake.stakingAmount == 0 || !userStake.isActive) return 0;

        // 计算从上次更新到现在的时间段数
        uint256 timeElapsed = block.timestamp - userStake.lastUpdateTime;
        uint256 intervals = timeElapsed / RATE_INCREASE_INTERVAL;

        // 简化收益计算:使用平均收益率
        // 总仓位 = 质押仓 + 创世仓
        uint256 totalStakeAmount = userStake.stakingAmount + userStake.genesisAmount;
        // 平均日化收益率 = 当前全局收益率
        // 收益 = 总仓位 * 平均日化收益率 * 经过的天数
        // 注意:这是一个简化的线性模型,实际复利计算更复杂,需要在每个间隔内单独计算
        uint256 averageRate = currentGlobalRate;
        uint256 daysStaked = timeElapsed / 1 days;
        uint256 reward = (totalStakeAmount * averageRate * daysStaked) / RATE_DENOMINATOR;

        return reward;
    }

    /**
     * @dev 用户提取已产生的收益
     */
    function claimRewards() external nonReentrant onlyAfterLaunch {
        uint256 reward = calculateRewards(msg.sender);
        require(reward > 0, "No rewards to claim");

        // 更新用户的最后结算时间
        stakes[msg.sender].lastUpdateTime = block.timestamp;
        _updateGlobalRate();

        // 将收益代币转账给用户
        require(maxToken.transfer(msg.sender, reward), "Reward transfer failed");
        emit RewardClaimed(msg.sender, reward);
    }

    /**
     * @dev 用户取回质押本金(30天后),并丧失节点资格
     */
    function unstake() external nonReentrant onlyAfterLaunch {
        Stake storage userStake = stakes[msg.sender];
        require(userStake.isActive, "No active stake or already unstaked");
        require(block.timestamp >= systemLaunchTime + 30 days, "Cannot unstake before 30 days");

        // 结算所有未领取的收益
        uint256 reward = calculateRewards(msg.sender);
        if (reward > 0) {
            require(maxToken.transfer(msg.sender, reward), "Reward transfer failed");
        }

        uint256 amountToReturn = userStake.stakingAmount; // 只能取回质押的100U等值MAX
        // 销毁创世仓位(不退还)
        userStake.stakingAmount = 0;
        userStake.genesisAmount = 0;
        userStake.isActive = false; // 标记节点资格失效

        // 退还本金
        require(maxToken.transfer(msg.sender, amountToReturn), "Return of stake failed");
        emit Unstaked(msg.sender, amountToReturn);
    }

    /**
     * @dev 内部函数,更新全局收益率
     */
    function _updateGlobalRate() internal {
        if (systemLaunchTime == 0) {
            systemLaunchTime = block.timestamp; // 在第一次交互时启动系统
            return;
        }
        uint256 timeElapsed = block.timestamp - systemLaunchTime;
        uint256 intervals = timeElapsed / RATE_INCREASE_INTERVAL;
        currentGlobalRate = BASE_RATE + (intervals * RATE_INCREASE_AMOUNT);
    }

    // 所有者函数:设置启动时间、处理额外奖励(每日1MAX)等。
    function setLaunchTime(uint256 _launchTime) external onlyOwner {
        systemLaunchTime = _launchTime;
    }
}

2.4 推荐奖励合约 (ReferralSystem.sol)​​

此合约管理多级推荐关系和在购买节点时分配奖励。

pragma solidity ^0.8.19;

import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";

contract ReferralSystem is Ownable {
    IERC20 public usdtToken;
    IERC20 public maxToken;

    // 总奖励池(每个节点35 USDT)
    uint256 public constant REF_POOL_PER_NODE = 35 * 10**6;

    // 推荐奖励比例(1层20%,2层10%,3层5%)
    uint256[] public refRates = [2000, 1000, 500]; // 分母为10000,即20%=2000/10000
    uint256 public constant RATE_DENOMINATOR = 10000;

    // 直推额外MAX奖励
    uint256 public constant DIRECT_REF_MAX_REWARD = 2 * 10**18; // 2 MAX
    uint256 public constant DIRECT_REF_MAX_CAP = 600 * 10**18; // 600 MAX上限

    // 记录用户的推荐人
    mapping(address => address) public referrerOf;
    // 记录用户已获得的直推MAX奖励总额
    mapping(address => uint256) public directRefMaxEarned;

    event ReferralRecorded(address indexed referrer, address indexed referee, uint256 level, uint256 rewardUSDT, uint256 rewardMAX);

    constructor(address _usdtAddress, address _maxAddress) {
        usdtToken = IERC20(_usdtAddress);
        maxToken = IERC20(_maxAddress);
    }

    /**
     * @dev 由NodeSale合约调用,处理推荐奖励分配
     */
    function handleReferral(address _referrer, address _referee, uint256 _nodePrice) external onlyOwner {
        require(_referrer != address(0) && _referee != address(0), "Invalid address");
        referrerOf[_referee] = _referrer;

        address current = _referrer;
        uint256 totalUSDTDistributed = 0;

        // 遍历1-3层推荐人
        for (uint256 i = 0; i < refRates.length; i++) {
            if (current == address(0)) break; // 没有更上层的推荐人

            uint256 rewardUSDT = (REF_POOL_PER_NODE * refRates[i]) / RATE_DENOMINATOR;
            totalUSDTDistributed += rewardUSDT;

            // 分配USDT奖励(需要确保本合约有足够的USDT余额)
            if (rewardUSDT > 0 && usdtToken.balanceOf(address(this)) >= rewardUSDT) {
                require(usdtToken.transfer(current, rewardUSDT), "USDT referral transfer failed");
            }

            // 如果是第一层(直推),额外分配MAX奖励
            if (i == 0) {
                if (directRefMaxEarned[current] + DIRECT_REF_MAX_REWARD <= DIRECT_REF_MAX_CAP) {
                    if (maxToken.balanceOf(address(this)) >= DIRECT_REF_MAX_REWARD) {
                        require(maxToken.transfer(current, DIRECT_REF_MAX_REWARD), "MAX referral transfer failed");
                        directRefMaxEarned[current] += DIRECT_REF_MAX_REWARD;
                    }
                }
            }

            emit ReferralRecorded(current, _referee, i+1, rewardUSDT, i == 0 ? DIRECT_REF_MAX_REWARD : 0);

            // 移动到上一层推荐人
            current = referrerOf[current];
        }
    }
}

第三章:关键特性与安全考量​​

  • ​​使用OpenZeppelin库​​:合约继承自OwnableReentrancyGuard,并使用ERC20标准,这些都经过广泛测试,能有效防止常见漏洞。
  • ​​重入攻击防护​​:在关键函数(如claimRewardsunstake)中使用nonReentrant修饰符。
  • ​​整数溢出防护​​:Solidity 0.8.x内置了整数溢出检查。
  • ​​访问控制​​:关键的管理函数(如提取资金、设置启动时间)由onlyOwner修饰,确保只有部署者可以调用。
  • ​​简化与假设​​:上述代码为演示核心逻辑的简化版。实际生产环境需要考虑:
    • ​​汇率问题​​:USDT与MAX代币的汇率需要通过​​去中心化预言机(如Chainlink)​​ 动态获取。
    • ​​精确收益计算​​:当前的收益计算是简化模型。精确的复利计算需要记录每个利率变化周期的份额,或采用更复杂的算法。
    • ​​AI超燃协议​​:实现动态收益调整需要将链下AI计算的结果通过预言机输入到合约中,修改calculateRewards函数。
    • ​​Gas优化​​:对于循环和映射操作需进行优化,避免达到区块Gas上限。
    • ​​全面的单元测试和第三方审计​​:这是DeFi项目安全上线的必要条件。
posted on 2025-11-26 18:10  程序员李铁牛  阅读(12)  评论(0)    收藏  举报