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

Solidity白名单:For/If循环无报错但未推入地址至数组

白名单合约数组添加失败问题排查与修复

问题描述

尝试实现一个自白名单合约,通过for和if循环检查msg.sender是否已存在于addressWhitelist数组中。调用whitelist()函数时无报错,但调用check()函数或直接读取数组时,地址并未被添加到数组内。

原合约代码:

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

contract SelfWhitelist {

    address[] public addressWhitelist;

    function whitelist() public returns(string memory) {
        for(uint i = 0; i < addressWhitelist.length; i++) {
            if(addressWhitelist[i] != msg.sender) {
                addressWhitelist.push(msg.sender);
                return "Whitelisted!";
            }
        }
        return "Already whitelisted!";
    }

    function check() public view returns (bool){
        for(uint i = 0; i < addressWhitelist.length; i++){
            if(addressWhitelist[i] == msg.sender)
                return true;
        }
        return false;
    }

}

错误原因分析

原whitelist()函数的逻辑完全错误:

  • 当addressWhitelist数组为空时,for循环不会执行,直接返回"Already whitelisted!",导致地址根本不会被添加。
  • 当数组不为空时,只要遍历到第一个不等于msg.sender的元素,就立刻将地址push进数组并返回,这会导致重复添加地址;如果数组第一个元素等于msg.sender,循环会继续,但后续只要遇到不等于的元素,依然会重复添加,完全没有实现“检查地址是否存在,不存在才添加”的核心逻辑。

修正后的代码

正确的逻辑是先遍历整个数组,确认地址不存在后再执行添加操作:

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

contract SelfWhitelist {

    address[] public addressWhitelist;

    function whitelist() public returns(string memory) {
        // 先遍历数组检查地址是否已存在
        for(uint i = 0; i < addressWhitelist.length; i++) {
            if(addressWhitelist[i] == msg.sender) {
                return "Already whitelisted!";
            }
        }
        // 确认不存在后添加地址
        addressWhitelist.push(msg.sender);
        return "Whitelisted!";
    }

    function check() public view returns (bool){
        for(uint i = 0; i < addressWhitelist.length; i++){
            if(addressWhitelist[i] == msg.sender)
                return true;
        }
        return false;
    }

}

额外优化建议

如果白名单数量较大,数组遍历的gas成本会很高,建议同时使用mapping(address => bool)来记录白名单状态,这样检查地址是否存在的操作可以在O(1)时间内完成,大幅降低gas消耗:

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

contract SelfWhitelist {

    address[] public addressWhitelist;
    mapping(address => bool) public isWhitelisted;

    function whitelist() public returns(string memory) {
        if(isWhitelisted[msg.sender]) {
            return "Already whitelisted!";
        }
        addressWhitelist.push(msg.sender);
        isWhitelisted[msg.sender] = true;
        return "Whitelisted!";
    }

    function check() public view returns (bool){
        return isWhitelisted[msg.sender];
    }

}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 01:40:32