Solidity代码报错:ParserError: 预期';'却获保留关键字'in'
Solidity函数错误修复:ParserError: expected ';' but got reserved keyword 'in'
错误原因
Solidity不支持直接用for...in语法遍历mapping的键,你代码里的for (address user in orderBook[token])属于无效写法,这就是触发该语法错误的核心原因。mapping是哈希表结构,无法直接枚举所有存储的键,必须额外维护一个可遍历的列表来记录参与的用户地址。
修复方案
1. 补充状态变量
新增一个mapping来维护每个代币对应的下单用户列表:
// 原有状态变量 mapping(address => bool) public tokens; mapping(address => mapping(address => uint256)) public orderBook; // token => user => 订单数量 mapping(address => mapping(address => uint256)) public orderPrices; // token => user => 单位价格 // 新增:记录每个代币的下单用户地址列表 mapping(address => address[]) public tokenUsers;
2. 修改getPrice函数
遍历维护的用户列表计算总价和总量,同时添加必要的错误检查:
// 根据订单簿可用订单计算上市代币当前价格 function getPrice(address token) public view returns (uint256) { require(tokens[token], "Token is not listed"); uint256 totalAmount = 0; uint256 totalPrice = 0; // 获取当前代币的所有下单用户列表 address[] memory users = tokenUsers[token]; for (uint256 i = 0; i < users.length; i++) { address user = users[i]; uint256 amount = orderBook[token][user]; // 跳过已取消或已完成的空订单 if (amount == 0) continue; totalAmount = totalAmount.add(amount); totalPrice = totalPrice.add(orderPrices[token][user].mul(amount)); } // 避免无订单时出现除以0的运行时错误 require(totalAmount > 0, "No active orders for token"); return totalPrice.div(totalAmount); }
3. 配套逻辑补充
当用户创建新订单时,需要将用户地址添加到对应代币的tokenUsers数组中(可根据业务需求添加重复检查逻辑):
function createOrder(address token, uint256 amount, uint256 price) public { require(tokens[token], "Token is not listed"); require(amount > 0, "Amount must be greater than 0"); // 记录订单信息 orderBook[token][msg.sender] = amount; orderPrices[token][msg.sender] = price; // 将用户添加到代币的用户列表 tokenUsers[token].push(msg.sender); }
关键注意事项
- 若用户取消订单,需要同步将
orderBook中对应用户的amount设为0,或者从tokenUsers数组中移除该用户地址,避免无效遍历。 - 若使用Solidity 0.8.0及以上版本,可直接用
+、*、/替代add()、mul()、div(),编译器会自动加入溢出检查。
内容的提问来源于stack exchange,提问作者zach yello
相关产品推荐
相关产品推荐

