You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在智能合约中利用Oracle返回的数组实现五级推荐奖励机制?

五级推荐奖励质押DApp的实现方案

整体逻辑概览

整个流程分为四个核心环节:

  • 用户前端提交推荐关系到后端数据库
  • 用户质押时,智能合约通过Oracle发起链外数据请求
  • 后端API处理请求,从数据库提取五级推荐链数据
  • Oracle将数据返回合约,合约按比例计算并发放推荐奖励

分步实现细节

1. 前端与数据库的推荐关系存储

  • 用户在质押页面填写推荐人地址(可选),点击质押后,前端组装指定格式的JSON数据发送到后端API:
{
"type": "register",
"address":"0x78910",
"referrer":"0x12345",
"coin":20
}
  • 后端接收数据后,在数据库中维护推荐链关系:建议创建referral_links表,字段包括user_address、referrer_address。也可以提前计算并存储每个用户的五级推荐人(递归遍历上级推荐链,直到L5或无上级),这样后续Oracle查询效率更高。

2. 智能合约侧的Oracle集成

以Chainlink Oracle为例(核心逻辑通用,适配其他Oracle只需调整接口):

(1)合约基础结构

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

import "@chainlink/contracts/src/v0.8/ChainlinkClient.sol";
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";

contract StakingReferral is ChainlinkClient {
    address public immutable rewardToken; // 奖励用的ERC20代币地址
    address private oracle;
    bytes32 private jobId;
    uint256 private constant LINK_FEE = 0.1 * 10 ** 18;

    // 奖励比例:放大1000倍避免小数(7% = 70)
    uint256[5] public referralRates = [70, 30, 20, 10, 5];

    // 记录用户质押金额(示例)
    mapping(address => uint256) public stakedAmounts;

    event ReferralRewardsPaid(address indexed staker, uint256 totalRewards);
    event OracleRequestInitiated(address indexed staker);

    constructor(address _rewardToken, address _oracle, bytes32 _jobId) {
        setPublicChainlinkToken();
        rewardToken = _rewardToken;
        oracle = _oracle;
        jobId = _jobId;
    }
}

(2)触发Oracle请求的质押函数

用户质押时,先处理基础质押逻辑,再发起Oracle请求获取推荐链:

function stake(uint256 amount) external {
    // 基础质押逻辑:锁定用户的ERC20代币
    IERC20(rewardToken).transferFrom(msg.sender, address(this), amount);
    stakedAmounts[msg.sender] += amount;

    // 构建Oracle请求,传递用户地址给后端API
    Chainlink.Request memory req = buildChainlinkRequest(
        jobId,
        address(this),
        this.fulfillReferralData.selector
    );
    req.add("get", string(abi.encodePacked("https://your-api-domain.com/referral-chain?addr=", msg.sender)));
    req.add("pathReferrers", "referrers"); // 指定JSON中推荐人数组的路径
    req.add("pathLevels", "levels"); // 指定JSON中层级数组的路径

    sendChainlinkRequestTo(oracle, req, LINK_FEE);
    emit OracleRequestInitiated(msg.sender);
}

(3)Oracle回调与奖励发放

Oracle返回数据后,合约计算并发放奖励:

function fulfillReferralData(
    bytes32 _requestId,
    address[] memory _referrers,
    uint256[] memory _levels
) public recordChainlinkFulfillment(_requestId) {
    require(_referrers.length == _levels.length && _referrers.length <=5, "Invalid referral data");

    uint256 stakeAmount = stakedAmounts[msg.sender];
    uint256 totalPaid = 0;

    for(uint i=0; i<_referrers.length; i++){
        uint256 rate = referralRates[_levels[i]-1];
        uint256 reward = (stakeAmount * rate) / 1000;
        
        // 直接发放奖励,或存入奖励池待提取
        IERC20(rewardToken).transfer(_referrers[i], reward);
        totalPaid += reward;
    }

    emit ReferralRewardsPaid(msg.sender, totalPaid);
}

3. 后端API与Oracle Job配置

(1)API接口实现(Node.js/Express示例)

提供接口查询用户的五级推荐链:

const express = require('express');
const app = express();
const { Pool } = require('pg'); // 以PostgreSQL为例

const pool = new Pool({ /* 数据库连接配置 */ });

app.get('/referral-chain', async (req, res) => {
    const userAddr = req.query.addr;
    const referralChain = [];
    let currentAddr = userAddr;
    let level = 1;

    while(level <=5){
        const result = await pool.query(
            'SELECT referrer_address FROM referral_links WHERE user_address = $1',
            [currentAddr]
        );
        if(result.rows.length ===0) break;
        
        const referrer = result.rows[0].referrer_address;
        referralChain.push({ addr: referrer, lvl: level });
        currentAddr = referrer;
        level++;
    }

    // 返回Oracle需要的格式
    res.json({
        referrers: referralChain.map(item => item.addr),
        levels: referralChain.map(item => item.lvl)
    });
});

app.listen(3000, () => console.log('API running on port 3000'));

(2)Oracle Job配置

在Oracle节点上创建HTTP GET类型的Job,配置:

  • 请求URL:你的API地址(带用户地址参数)
  • 解析规则:从返回的JSON中提取referrers和levels数组
  • 回调合约:你的质押合约地址及fulfillReferralData函数签名

4. 核心注意事项

  • 数据校验:前端提交推荐人时,要验证地址格式合法性,后端也要校验推荐人是否为已注册用户,避免无效推荐链。
  • Oracle安全:API接口需限制访问来源(比如Oracle节点IP白名单),防止恶意请求篡改推荐数据。
  • Gas优化:可以将推荐奖励存入用户的奖励池,待用户提取质押代币时统一发放,减少链上交易次数。
  • 精度处理:Solidity不支持小数,所有比例计算需放大倍数(如1000倍),计算完成后再还原。

内容的提问来源于stack exchange,提问作者Nirban Chakraborty

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.17 21:35:20