【问题标题】:If statement in for loop not filtering out items in solidityfor循环中的if语句没有过滤掉solidity中的项目
【发布时间】:2018-12-13 01:48:46
【问题描述】:
// @param physicalAddress - the actual address of the home a host wants to list (not the ethereum address)
// @return _id - list of ids for homes
function listHomesByAddress(string _physicalAddress) public returns(uint [] _id ) {
    uint [] results;
    for(uint i = 0 ; i<homes.length; i++) {
        if(keccak256(homes[i].physicalAddress) == keccak256(_physicalAddress) && homes[i].available == true) {
            results.push(homes[i].id);
        }
    }
    return results;    
}

结果应该是与输入的物理地址匹配的 id 列表,但它不会过滤,而是返回所有可用的房屋。 当我改为使用 String utils 时,没有任何变化。

这是整个代码:

pragma solidity ^0.4.0;

import "browser/StringUtils.sol";

// @title HomeListing

contract HomeListing {

    struct Home {
        uint id;
        string physicalAddress;
        bool available;
    }

    Home[] public homes;
    mapping (address => Home) hostToHome;
    event HomeEvent(uint _id);
    event Test(uint length);

    constructor() {

    }

    // @param physicalAddress - the actual address of the home a host wants to list (not the ethereum address)
    function addHome(string _physicalAddress) public {
        uint _id = uint(keccak256(_physicalAddress, msg.sender));
        homes.push(Home(_id, _physicalAddress, true));
    }

    // @param physicalAddress - the actual address of the home a host wants to list (not the ethereum address)
    // @return _id - list of ids for homes
    function listHomesByAddress(string _physicalAddress) public returns(uint [] _id ) {
        uint [] results;
        for(uint i = 0 ; i<homes.length; i++) {
            string location = homes[i].physicalAddress;
            if(StringUtils.equal(location,_physicalAddress )) {
                results.push(homes[i].id);
            }
        }
        return results;
    }
}

【问题讨论】:

    标签: solidity smartcontracts remix


    【解决方案1】:

    给你带来麻烦的部分是uint[] results;。默认情况下,声明为局部变量的数组引用 storage 内存。来自Solidity docs 的“内存关键字是什么”部分:

    存储位置有默认值,具体取决于它涉及的变量类型:

    • 状态变量始终在存储中
    • 函数参数默认在内存中
    • 结构体、数组或映射类型的局部变量默认引用存储
    • 值类型的局部变量(即既不是数组,也不是结构,也不是映射)存储在堆栈中

    结果是你引用了合约的第一个存储槽,恰好是Home[] public homes。这就是你要恢复整个数组的原因。

    要解决此问题,您需要使用memory 数组。但是,您还有一个额外的问题,即您不能在 Solidity 中使用动态内存数组。一种解决方法是确定结果大小限制并静态声明您的数组。

    示例(限于 10 个结果):

    function listHomesByAddress(string _physicalAddress) public view returns(uint[10]) {
        uint [10] memory results;
        uint j = 0;
        for(uint i = 0 ; i<homes.length && j < 10; i++) {
            if(keccak256(homes[i].physicalAddress) == keccak256(_physicalAddress) && homes[i].available == true) {
                results[j++] = homes[i].id;
            }
        }
        return results;
    
    } 
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-07-25
      • 1970-01-01
      • 2016-06-16
      • 2019-06-09
      • 1970-01-01
      相关资源
      最近更新 更多