0

In my contact I want to have one place where I find an existing object(struct) and then use it in multiple places to read and modify it - but seems like it's not possible?

contract A
{
    struct Prop
    {
    }

    struct App
    {
        Prop[] props;
    }

    App[] apps;

    function AddProp(string memory name) public
    {
        App memory a = FindApp(name);

        if(bytes(a.name).length > 0)
            a.props.push(Prop()); // TypeError: Data location must be "memory" for return parameter in function, but "storage" was given.

        else
            revert('Application not found');        
    }

    function FindApp(string memory name) public returns (App memory) // can't return 'storage'
    {
        for(uint256 i = 0; i < apps.length; i++)
        {
            if(apps[i].name == name)
            {
                return apps[i];
            }
        }

        return App();
    }

}

1

I had to change quite a few things to get this code to compile, but the important piece you were missing is that public functions can't return storage references (because an external caller couldn't do anything with that), but internal (or private) functions can:

pragma solidity 0.5.11;

contract A
{
    struct Prop
    {
        uint256 foo; // empty structs are not allowed
    }

    struct App
    {
        string name; // added this because it was used elsewhere
        Prop[] props;
    }

    App[] apps;

    function AddProp(string memory name) public
    {
        App storage a = FindApp(name); // storage

        if(bytes(a.name).length > 0)
            a.props.push(Prop(0));
        else
            revert('Application not found');        
    }

    function FindApp(string memory name) internal view returns (App storage) // storage
    {
        bytes32 hash = keccak256(abi.encodePacked(name));
        for(uint256 i = 0; i < apps.length; i++)
        {
            // string equality is not defined, have to compare hashes
            if (keccak256(abi.encodePacked(apps[i].name)) == hash)
            {
                return apps[i];
            }
        }

        revert("Not found."); // Wasn't sure what to do here... you can't just return a new App because you need to return something from storage
    }
}
|improve this answer|||||

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.