前端调用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
相关产品推荐
相关产品推荐

