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

前端调用Solidity合约view函数触发Panic code 50(数组越界)问题

解决Solidity合约getFoodItemsByOwner()函数数组越界导致的Panic Code 50错误

问题现象

前端调用Solidity合约的view函数getFoodItemsByOwner()时触发调用回滚异常,报错为Panic code 50(对应0x32错误),属于数组越界访问问题。

控制台完整错误输出

index.js?dd68:224 Uncaught (in promise) Error: call revert exception; VM Exception while processing transaction: reverted with panic code 50 [ See: https://links.ethers.org/v5-errors-CALL_EXCEPTION ] (method="getFoodItemsByOwner()", data="0x4e487b710000000000000000000000000000000000000000000000000000000000000032", errorArgs=[{"type":"BigNumber","hex":"0x32"}], errorName="Panic", errorSignature="Panic(uint256)", reason=null, code=CALL_EXCEPTION, version=abi/5.7.0)

原合约代码

address public owner;

struct FoodItem {
    address owner;
    string url;
    string name;
    string originCountry;
}

FoodItem[] public foodItems;

function addFoodItem(
    string memory url,
    string memory name,
    string memory originCountry
) public {
    foodItems.push(FoodItem(msg.sender, name, url, originCountry));
}

function getFoodItemsByOwner() public view returns (FoodItem[] memory) {
    uint256 itemCount = 0;

    for (uint256 i = 0; i < foodItems.length; i++) {
        if (foodItems[i].owner == msg.sender) {
            itemCount += 1;
        }
    }

    FoodItem[] memory myfoods = new FoodItem[](itemCount);
    for (uint256 i = 0; i < foodItems.length; i++) {
        if (foodItems[i].owner == msg.sender) {
            myfoods[i] = foodItems[i];
        }
    }

    return myfoods;
}

前端调用代码

const getDishesByUser = async () => {
    const { ethereum } = window;
    if(ethereum) {
        const provider = new ethers.providers.Web3Provider(ethereum);    
        const signer = provider.getSigner();
        const contract = new ethers.Contract(abiFoodAddress, Food.abi, signer);
        const data = await contract.getFoodItemsByOwner();
       console.log(data);
        setDishesByuser(data)
        //router.push('/');
    }
};

useEffect(() => {
    getDishesByUser();
}, []);

问题根源

合约中getFoodItemsByOwner函数的第二个循环存在致命问题:遍历foodItems的索引i被直接用来给myfoods数组赋值。myfoods的长度是itemCount(当前用户拥有的食品项数量),而foodItems的总长度通常大于itemCount。当循环到i >= itemCount时,访问myfoods[i]就会触发数组越界,导致Panic code 50错误。

修复后的合约代码

address public owner;

struct FoodItem {
    address owner;
    string url;
    string name;
    string originCountry;
}

FoodItem[] public foodItems;

function addFoodItem(
    string memory url,
    string memory name,
    string memory originCountry
) public {
    foodItems.push(FoodItem(msg.sender, name, url, originCountry));
}

function getFoodItemsByOwner() public view returns (FoodItem[] memory) {
    uint256 itemCount = 0;

    // 先统计当前用户拥有的食品项数量
    for (uint256 i = 0; i < foodItems.length; i++) {
        if (foodItems[i].owner == msg.sender) {
            itemCount += 1;
        }
    }

    FoodItem[] memory myfoods = new FoodItem[](itemCount);
    uint256 index = 0; // 新增独立索引计数器,追踪myfoods的赋值位置
    for (uint256 i = 0; i < foodItems.length; i++) {
        if (foodItems[i].owner == msg.sender) {
            myfoods[index++] = foodItems[i]; // 使用独立索引赋值,避免越界
        }
    }

    return myfoods;
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.10 16:31:18