0

In solidity version 0.5.8, it is giving me the error that I have an uninitialized storage pointer. How do I fix this error, and if your answer is by making it a memory variable instead of storage variable, then how do i append a value instead of pushing?

my code is:

function enRouteList(uint rideNumber) public view returns(address[] memory) {
Ride storage curRide = rides[rideNumber];
address[] storage addressesEnRoute;
for(uint i = 0; i < curRide.passengerAccts.length; i++) {
  if (keccak256(bytes(curRide.passengers[curRide.passengerAccts[i]].state)) == keccak256("enRoute")) {
    addressesEnRoute.push(curRide.passengerAccts[i]);
  }
}

Thank you

2

You should, in fact, use an in-memory array. Unfortunately, those cannot be dynamically sized, which means you somehow need to know the size of the array before you start filling it. There are two typical patterns I see for doing this:

Count the element first

Here, there are two loops. The first time around, you're just counting the number of elements that will be in the returned array. Once that's done, you can create an in-memory array because you know the correct size. In the second loop, you fill the array.

(There are a number of ways to potentially make this more efficient, but the general pattern is "Count, then declare an array, and then fill it.")

    function enRouteList(uint rideNumber) public view returns (address[] memory) {
        Ride storage curRide = rides[rideNumber];
        uint256 count = 0;
        for (uint256 i = 0; i < curRide.passengerAccts.length; i++) {
            if (keccak256(bytes(curRide.passengers[curRide.passengerAccts[i]].state)) == keccak256("enRoute")) {
                count += 1;
            }
        }
        address[] memory addressesEnRoute = new address[](count);
        uint256 index = 0;
        for (uint256 i = 0; i < curRide.passengerAccts.length; i++) {
            if (keccak256(bytes(curRide.passengers[curRide.passengerAccts[i]].state)) == keccak256("enRoute")) {
                addressesEnRoute[index] = curRide.passengerAccts[i];
                index += 1;
            }
        }
    }

Return an oversized array

You know the upper bound on the size of the array before you loop through the potential elements, so you can declare an oversized array. This means you also need to indicate to the caller how many array elements are actually valid. Below, I'm doing that with a second return value, but that might be unnecessary if the zero value is invalid. (The caller can just read all the elements until they reach the first zero.)

Again, this can be done a few different ways, but the general pattern is "Declare an oversized array, fill it, and indicate its valid length."

    function enRouteList(uint rideNumber) public view returns (address[] memory, uint256) {
        Ride storage curRide = rides[rideNumber];

        address[] memory addressesEnRoute = new address[](curRide.passengerAccts.length);

        uint256 count = 0;
        for (uint256 i = 0; i < curRide.passengerAccts.length; i++) {
            if (keccak256(bytes(curRide.passengers[curRide.passengerAccts[i]].state)) == keccak256("enRoute")) {
                addressesEnRoute[count] = curRide.passengerAccts[i];
                count += 1;
            }
        }

        return (addressesEnRoute, count);
    }
1

You should declare the array globally instead of inside the function.

Have a look at this for some important information about this warning. Worth the time. https://blog.b9lab.com/storage-pointers-in-solidity-7dcfaa536089

Hope it helps.

  • If you did that, the function couldn't be a view function anymore, right? I suppose external callers could force a call instead of a transaction, and smart contracts could declare it a view function in an interface to get Solidity to use a STATICCALL. I think just putting the values in memory is simpler, though. – smarx Sep 5 at 3:03
  • That is indeed the next problem. TBO, I would resist the use of a loop in case it's a long list, like a train or a cruise ship. Nested dynamic sets and client-side iteration seems more scalable. – Rob Hitchens - B9lab Sep 5 at 5:42
  • I agree with that last point. – smarx Sep 5 at 5:47

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.