Solidity合约rent函数无法实现Leaser向Owner转ETH的问题排查
问题定位与修复方案
核心转账失败原因
- 未校验交易附带的ETH金额
getRent函数声明为payable,但仅通过msg.sender.balance > _leaserAmount校验租户账户余额,未检查本次交易实际发送的ETH(msg.value)是否等于租金_leaserAmount。若租户未在调用时附带对应ETH,合约余额不足,执行_owner.transfer(_leaserAmount)会直接失败。 checkRentAmount函数调用参数错误
在getRent中调用checkRentAmount(_owner,property.MonthPrice)时,第二个参数误传为房产价格,而该函数要求传入房产在PropertyMap中的索引。这会导致函数读取错误的房产数据,大概率触发"Invalid Price"回滚;若测试场景中刚好价格等于索引,会隐藏逻辑异常。- 转账方式的局限性
使用transfer会强制限制2300 gas,若房主是合约地址且其receive/fallback函数消耗gas超过该值,转账会失败。
修复后的关键代码片段
修正getRent函数
function getRent ( address payable _leaser, address payable _owner, uint256 _HouseShopNumber, string memory _ProportName, uint256 _RentEnd, uint256 _leaserAmount) external payable { require(!locked, "Reentrant call detected!"); require(_owner != _leaser,"you cant rent yourself"); require(msg.sender == _leaser,"you are not leaser"); require(!checkRent(_owner,_HouseShopNumber),"already rented"); Property storage property = PropertyMap[_owner][_HouseShopNumber]; // 修正参数:传入房产索引而非价格 require(checkRentAmount(_owner, _HouseShopNumber) == _leaserAmount,"Invalid Price" ); // 校验本次交易发送的ETH与租金匹配 require(msg.value == _leaserAmount,"Sent ETH does not match rent amount"); contracts memory _contracts; _contracts.leaser = _leaser; _contracts.owner = _owner; _contracts.ProportName =_ProportName; _contracts.RentStart = block.timestamp; _contracts.RentEnd = _RentEnd + block.timestamp; _contracts.RentPrice = _leaserAmount; contractsMap[_owner].push(_contracts); locked = true; // 使用call替代transfer,处理返回值确保转账成功 (bool success,) = _owner.call{value: _leaserAmount}(""); require(success, "Transfer to owner failed"); locked = false; property.active = true; emit getRent1(_leaser, _HouseShopNumber, _ProportName, _RentEnd); }
修正setHouseShop中的空语句
将无意义的property.active;改为显式赋值(bool默认值虽为false,显式赋值更清晰):
Property memory property; property.owner = _owner; property.AssetName = _AssetName; property.MonthPrice = _amount; property.active = false; // 修正空语句
额外注意事项
- 调用
getRent时,必须在交易中附带与_leaserAmount相等的ETH,否则会触发"Sent ETH does not match rent amount"回滚。 - 若房主为合约地址,需确保其
receive或fallback函数的gas消耗在区块gas限制范围内。
内容的提问来源于stack exchange,提问作者Mentalist
相关产品推荐
相关产品推荐

