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

Lottery合约getPlayers无限Gas问题及新增部署钱包存代币功能咨询

Solidity Lottery合约Gas报错解决方案及功能实现

一、Gas报错原因及修复方案

你遇到的报错内容如下:

"Gas costs: Gas requirement of function Lottery.getPlayers is infinite: If the gas requirement of a function is higher than the block gas limit, it cannot be executed. Please avoid loops in your functions or actions that modify large areas of storage (this includes clearing or copying arrays in storage)"

报错根因

  • getPlayers()函数会直接返回整个players存储数组,当参与玩家数量足够多时,将完整存储数组复制到内存返回的操作会消耗超过区块Gas上限的资源,因此编译器会提前抛出Gas需求无限的告警。
  • 除此之外,pickWinner()函数中直接清空players数组的操作players = new address[](0),在数组长度过大时也会触发相同的Gas超限风险。

修复方案

  • 新增getPlayersCount()函数获取玩家总数,前端可直接调用合约自动生成的players(uint index)方法分页查询单个玩家地址,避免全量读取数组的高Gas消耗:
function getPlayersCount() public view returns(uint) {
    return players.length;
}
  • 若业务必须保留全量返回玩家的功能,可在enter()函数中新增最大参与人数限制,从根源避免数组过大:
// 最大参与人数可根据业务需求调整
require(players.length < 1000, "已达到最大参与人数上限");

注:原合约enter()函数存在提示与校验规则不匹配的问题,代码校验阈值为大于0.01ETH,错误提示写的是大于0.1ETH,可根据实际需求调整

二、新增管理员存入额外代币功能

仅需新增一个带restricted权限修饰符的payable函数即可实现仅部署钱包(manager)向合约存入资金:

function depositExtraFunds() public payable restricted {
    // payable修饰符会自动接收调用时转入的ETH,无需额外逻辑
}

三、修复后完整合约代码

pragma solidity ^0.6.0;
contract Lottery {
    address public manager;
    address[] public  players;
    uint public constant MAX_PLAYERS = 1000;

    constructor() public {
        manager = msg.sender;
    }

    modifier restricted() {
        require(msg.sender == manager,"仅管理员可操作");
        _;
    }

    function balanceInPool()public view returns(uint){
        return address(this).balance;
    }

    function enter() public payable {
        require(msg.value > .01 ether,"存入金额需大于0.01ETH");
        require(players.length < MAX_PLAYERS, "已达到最大参与人数上限");
        players.push(msg.sender);
   }

    function random() private view returns (uint) {
        return uint(keccak256(abi.encodePacked(block.difficulty,now,players)));
    }

    function pickWinner() public restricted {
        uint index = random() % players.length;
        address payable winner = payable(players[index]);
        players = new address[](0);
        winner.transfer(address(this).balance);
     }

    function getPlayers()public view returns(address[] memory){
        return players;
    }

    function getPlayersCount() public view returns(uint) {
        return players.length;
    }

    function depositExtraFunds() public payable restricted {
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.03 12:27:05