2

Following example code piece works on solidity v0.6.*:

// SPDX-License-Identifier: MIT

pragma solidity >=0.7.1;

contract Campaign {
    struct Status {
        uint32 cost;
        mapping(uint256 => address) jobs; // I will set this afterwards
    }
    
    struct Provider {
            mapping(string => Status[]) jobStatus;
    }
    
    mapping(address => Provider) providers;

    function submit(string memory key) public {
         Provider storage provider = providers[msg.sender];
         provider.jobStatus[key].push(Status({cost:100}));
    }
}

When I update solidity version to 0.7.1 I am getting following error: TypeError: Struct containing a (nested) mapping cannot be constructed..

When I uncomment following line mapping(uint256 => address) jobs; error is gone but is there any way to handle this error without uncommenting mapping(uint256 => address) jobs; section?

6
  • Side note: I'd declare those state variables in the exact reversed order, to explicitly emphasize the dependency chain, and perhaps even fix the compilation error (though based on the error-message, it hardly looks related). Commented Oct 4, 2020 at 14:05
  • What do you mean by reverse order, like Job , Status , and Provider?
    – alper
    Commented Oct 4, 2020 at 14:07
  • Relevant prior to your recent edit: you have 4 structures and state variables. The 1st uses the 2nd, the 2nd uses the 3rd, and the 3rd uses the 4th. Rearrange those Such that each dependency is declared before being used. Commented Oct 4, 2020 at 14:10
  • I have rearrange them but it didn't make any affect
    – alper
    Commented Oct 4, 2020 at 14:14
  • works on solidity v0.6.0 - by 'works', do you mean 'compiles'? Or have you actually tested it on an EVM (e.g., ganache)? I find it hard to believe that chriseth would unsupport a valid working functionality. Commented Oct 4, 2020 at 14:17

1 Answer 1

3

The problem is that since solc 0.7 it is no longer allowed to create structs in memory that contains mappings, see the release notes.

One workaround is to use .push() and get a reference to the new created element and use that reference to modify it.

function submit(string memory key) public {
     Provider storage provider = providers[msg.sender];
     Status storage st = provider.jobStatus[key].push();
     st.cost = 100;
}
3
  • In gas usage will this workaround might consume more gas if the jobStatus struct has lets say 10 variables ?
    – alper
    Commented Oct 4, 2020 at 17:23
  • @alper I'm don't know, you use less memory so gas usage should be lower, but you are write more code so gas will be higher.
    – Ismael
    Commented Oct 5, 2020 at 5:20
  • 1
    I experience there is additional 1.000 gas usage instead of pushing all in once in to the list []
    – alper
    Commented Oct 5, 2020 at 10:27

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.