1

In my contract there is a maaping of uint to an array of struct.

struct FactoryDetail{
 State itemState;            
 address factory;
 address warehouse;
 uint timeStamp1;
 uint timeStamp2;

}

mapping(uint=> FactoryDetail[]) public IdToFactory;

And a function to update the value of a factoryDetail based on uint key and index in the FactoryDetail array.

function factoryReceiveRawMaterials(uint256 _supplyChainId, address _warehouse) public{
    FactoryDetail[] memory fd =IdToFactory[_supplyChainId];
    for(uint i=0; i<fd.length; i++){
        if(fd[i].factory==msg.sender && fd[i].itemState== State.factoryBuyRawMaterial ){
            fd[i].warehouse =_warehouse;
            fd[i].itemState =State.factoryReceiveRawMaterials;
            fd[i].timeStamp1 =block.timestamp;
            temp=true;
            return;
        }
    }
}

But this is not working , when I am querying the value of IdToFactory, I'm seeing the old values.

2 Answers 2

2

The reason is because you are using memory when you asign the value of your mapping to fd here:

FactoryDetail[] memory fd =IdToFactory[_supplyChainId];

that means that a copy of your value is created in memory and when you modify fd what is modified is that copy

If you need to modify the actual value you should use: storage

FactoryDetail[] storage fd =IdToFactory[_supplyChainId];

take a look at this video to learn more

you can read more about storage and memory here

0

You are making a memory copy of the storage array, which is fine, you just need to remember to update the storage array with the changes.

Making a copy of a storage array to then loop through it reading/updating values is a good idea because reading and writing from and to storage is really expensive in terms of gas. So, make a memory copy if you know you are going to read/write a lot to the array, but then remember to set the updated array to storage.

Add this line at the end of your factoryReceiveRawMaterials function:

IdToFactory[_supplyChainId] = fd;

Like:

function factoryReceiveRawMaterials(uint256 _supplyChainId, address _warehouse) public{
    FactoryDetail[] memory fd =IdToFactory[_supplyChainId];
    for(uint i=0; i<fd.length; i++){
        if(fd[i].factory==msg.sender && fd[i].itemState== State.factoryBuyRawMaterial ){
            fd[i].warehouse =_warehouse;
            fd[i].itemState =State.factoryReceiveRawMaterials;
            fd[i].timeStamp1 =block.timestamp;
            temp=true;
            return;
        }
    }
   IdToFactory[_supplyChainId] = fd;
}

This will update the storage array with the newly updated array.

You could also declare the fd variable as storage, but it would be probably more expensive to read/write to it multiple times. You can implement both and check the gas consumption for each approach.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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