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

如何降低Polygon投票智能合约函数的Gas成本?

降低Polygon投票合约Gas成本的优化方案

1. 移除合约内字符串拼接,将格式化逻辑移至前端

Solidity中字符串拼接(尤其是循环内反复调用append)会频繁创建新内存对象,消耗大量Gas。当前合约中拼接artistas仅用于事件输出,完全可以把格式化为[ , 候选人1, 候选人2 ]的逻辑放到前端处理,合约只传递原始数组数据。

修改事件定义和投票函数:

// 原事件定义
// event Vote(string indexed name, string candidates);

// 修改后的事件定义,直接传递候选人数组
event Vote(string indexed name, string[] candidates);

function voteForCandidate(string[] calldata names, string[][] calldata vote ) public returns (bool){
    require(owner == msg.sender, "Only owner can call this function");
    uint voteLen = vote.length; // 缓存长度,避免重复读取calldata
    for(uint i = 0; i < voteLen; i++) {
        string[] calldata candidates = vote[i];
        uint candidateLen = candidates.length;
        for(uint y = 0; y < candidateLen; y++) {  
            votesReceived[candidates[y]] += 1;         
        }
        // 直接传递数组,无需拼接字符串
        emit Vote(names[i], candidates);
    }
    return true;
}

2. 合并批量事件触发(可选)

如果业务允许,可将100组投票的事件合并为一次触发,进一步减少事件发射的Gas开销。比如定义一个批量事件:

event BatchVote(string[] names, string[][] allCandidates);

// 在函数末尾触发一次批量事件,替代100次单个事件
emit BatchVote(names, vote);

前端监听该事件后,再拆分每组数据进行展示,这样能节省大量事件发射的固定Gas开销。

3. 优化存储操作

votesReceived[vote[i][y]] += 1是SSTORE操作(修改链上存储),Gas成本极高。如果同一候选人在单次交易中被多次投票,可以先在内存中累加票数,再一次性写入存储:

function voteForCandidate(string[] calldata names, string[][] calldata vote ) public returns (bool){
    require(owner == msg.sender, "Only owner can call this function");
    // 用内存映射临时存储单次交易内的票数累加
    mapping(string => uint) memory tempVotes;

    uint voteLen = vote.length;
    for(uint i = 0; i < voteLen; i++) {
        string[] calldata candidates = vote[i];
        uint candidateLen = candidates.length;
        for(uint y = 0; y < candidateLen; y++) {  
            tempVotes[candidates[y]] += 1;         
        }
        emit Vote(names[i], candidates);
    }

    // 批量写入链上存储
    // 注:Solidity 0.8.13+支持遍历内存映射,低版本需改用数组存储候选人列表
    for(string memory candidate in tempVotes) {
        votesReceived[candidate] += tempVotes[candidate];
    }
    return true;
}

4. 优化权限控制的Gas开销

将owner变量改为immutable类型(部署时赋值,后续不可修改),这样读取owner时直接从合约代码中获取,而非读取链上存储(SLOAD),能减少每次调用的Gas:

address public immutable owner;

constructor() {
    owner = msg.sender;
}

5. 动态设置Gas价格,避免固定高价

放弃固定500 GWEI的Gas价格,改用Polygon网络的动态Gas定价策略:

  • 使用EIP-1559交易类型,通过工具(如ethers.js)获取当前网络的maxFeePerGas和maxPriorityFeePerGas,设置略高于当前值的价格即可,无需固定高价。
  • 示例代码(ethers.js):
const feeData = await provider.getFeeData();
const tx = await contract.voteForCandidate(names, vote, {
    maxFeePerGas: feeData.maxFeePerGas?.add(ethers.utils.parseUnits("10", "gwei")),
    maxPriorityFeePerGas: feeData.maxPriorityFeePerGas?.add(ethers.utils.parseUnits("5", "gwei"))
});

这样在Gas价格低谷时能大幅降低交易成本,同时避免定价过低导致交易卡住。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.15 03:50:31