Solidity, Storage, Truffle Contract, Struct – Invalid Type for Argument in Function Call: Invalid Implicit Conversion from Mapping

soliditystoragestructtruffle-contract

I have defined struct for saving data to ethereum blockchain. I am using uint to map the data stored with a unique ID. I am using truffle framework to write smart contracts with solidity version: 0.4.24

Here are Structs:

    struct Location {
            string longitude;
            string latitude;
            string locationName;
        }

        struct Farm {
            uint farmId;
            string farmName;
            Location location;
        }

    struct Grapes {
            uint grapesId;
            string notes;
            uint vintageYear;
            address farmOwner;
            GrapeState state;
            Farm farm;
        }

mapping (uint => Farm) farms;
mapping (uint => Location) farmLocation;
mapping (uint => Grapes) grapes;

I am getting an error while writing data to struct:

function harvestGrapes(string _notes, uint _vintageYear, uint farmId) public verifyCaller(deployer) {

        previousGrapesId = previousGrapesId + 1;

        grapes[previousGrapesId] = Grapes ({
            grapesId: previousGrapesId,
            notes: _notes,
            vintageYear: _vintageYear,
            farmOwner: msg.sender,
            GrapeState: GrapeState.Harvested,
            farm: farms[farmId].farmName
        });

        emit GrapesHarvested(previousGrapesId);
    }

Here is the error log for the function call.

Named argument does not match function declaration.
        grapes[previousGrapesId] = Grapes ({
                                   ^ (Relevant source part starts here and spans across multiple lines).
,/C/Blockchain/WineSupplyChain/contracts/winebase/SupplyChain.sol:141:19: TypeError: Invalid type for argument in function call. Invalid implicit conversion from string storage ref to struct SupplyChain.Farm memory requested.
            farm: farms[farmId].farmName
                  ^--------------------^

Best Answer

If I'm not mistaken, you'll find problems as you try to write a struct from memory to storage.

I don't see where grapes was defined but it looks like a mapping, so I'll assume it is.

Change this:

grapes[previousGrapesId] = Grapes ({
 grapesId: previousGrapesId,
 notes: _notes,
 vintageYear: _vintageYear,
 farmOwner: msg.sender,
 GrapeState: GrapeState.Harvested,
 farm: farms[farmId].farmName
});

to this style:

Grapes storage g = grapes[previousGrapesId];
g.notes = _notes;
g.vintageYear = _vintageYear;
g.farmOwner = msg.sender;
g.GrapeState = GrapeState.Harvested;

I think your enum has an issue. It should be:

g.state = GrapeState.Harvested;

and

g.farm = farms[farmId].farmName;

g is a storage pointer. https://blog.b9lab.com/storage-pointers-in-solidity-7dcfaa536089

It's redundant to store the grapesId in the struct in most cases. For example, if the structs are stored in a mapping, then one needs to know the id to fetch an instance. In that case, it doesn't help to return the id the caller already knows. These patterns might give you some ideas: Are there well-solved and simple storage patterns for Solidity?

Hope it helps.

Related Topic