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

Solidity从数据库取实时数据及Oraclize实现白名单验证问询

问题2:实现isWhitelisted[msg.sender]映射,仅当用户钱包在SQL数据库中时返回true?

结合你提到的 Oraclize(Chainlink),这里有两种常见的实现思路,你可以根据需求选择:

思路1:预批量同步白名单

如果你的数据库中的白名单地址不会频繁变动,可以定期触发预言机批量查询数据库中的所有白名单地址,然后把这些地址批量标记到链上的isWhitelisted映射中。

这种方式的优点是用户后续验证时无需等待,直接查询链上映射即可;缺点是无法实时同步数据库的更新,需要手动或定时触发同步。

思路2:实时验证用户地址

如果需要实时验证用户地址是否在数据库中(比如数据库中的白名单随时可能更新),可以在用户需要验证白名单时,触发预言机请求,实时查询数据库并更新链上的映射状态。

具体实现步骤:

  1. 配置预言机和API:首先你需要搭建一个简单的 HTTP API,这个API接收预言机传来的用户地址参数,执行SQL查询(比如SELECT EXISTS(SELECT 1 FROM whitelist WHERE wallet_address = '用户地址')),然后返回true或false。
  2. 合约集成预言机:参考问题1中的合约框架,编写一个函数让用户调用,发起针对自己地址的验证请求。
  3. 回调更新映射:预言机获取API返回的结果后,回调合约的函数,更新isWhitelisted[msg.sender]的值。
  4. 白名单验证逻辑:在需要白名单权限的函数中,直接检查isWhitelisted[msg.sender]是否为true。

示例代码片段:

import "@chainlink/contracts/src/v0.8/ChainlinkClient.sol";

contract WhitelistChecker is ChainlinkClient {
    using Chainlink for Chainlink.Request;

    address private oracle;
    bytes32 private jobId;
    uint256 private fee;

    // 白名单映射
    mapping(address => bool) public isWhitelisted;

    constructor() {
        setPublicChainlinkToken();
        oracle = 0xYourOracleAddress;
        jobId = "0xYourJobId"; // 对应HTTP GET请求的Job
        fee = 0.1 * 10 ** 18;
    }

    // 用户调用此函数,验证自己是否在白名单中
    function checkMyWhitelistStatus() public returns (bytes32 requestId) {
        Chainlink.Request memory req = buildChainlinkRequest(jobId, address(this), this.fulfillWhitelistCheck.selector);
        
        // 传递用户地址到API,比如API地址是https://yourapi.com/check-whitelist?address=xxx
        req.add("get", string(abi.encodePacked("https://yourapi.com/check-whitelist?address=", toString(msg.sender))));
        req.add("path", "result"); // 假设API返回的JSON结构是{"result": true/false}
        
        return sendChainlinkRequestTo(oracle, req, fee);
    }

    // 预言机回调函数,更新白名单状态
    function fulfillWhitelistCheck(bytes32 _requestId, bool _isWhitelisted) public recordChainlinkFulfillment(_requestId) {
        // 这里可以添加额外的验证,确保请求是针对msg.sender的(防止恶意回调)
        // 比如可以存储requestId和对应的地址,这里简化处理
        isWhitelisted[msg.sender] = _isWhitelisted;
    }

    // 需要白名单权限的示例函数
    function mintToken() public {
        require(isWhitelisted[msg.sender], "You are not whitelisted");
        // 执行铸造逻辑...
    }

    function toString(address account) public pure returns (string memory) {
        return Strings.toHexString(uint256(uint160(account)), 20);
    }
}

注意事项

  • 费用问题:使用预言机需要支付服务费(Chainlink 用 LINK 代币),所以合约中需要预先存入足够的 LINK。
  • 安全性:回调函数必须验证预言机的签名(Chainlink 的recordChainlinkFulfillment修饰符已经帮你做了这部分),同时最好关联请求ID和发起请求的地址,防止恶意第三方触发回调。
  • 延迟问题:实时验证会有一定的延迟,因为需要等待预言机节点处理请求、查询数据库并回调结果,所以如果你的业务对实时性要求极高,可能需要考虑预同步的方式。

内容的提问来源于stack exchange,提问作者Smiles Lt

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.21 04:17:23