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

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