2

Im trying to set a mapping to a struct that contains an array of structs inside. Like so:

struct ParentTokenDetails{
    TokenType _tokenType;
    address _tokenOwner;
    ChildTokenDetails[] children;
}

struct ChildTokenDetails{
    TokenType _tokenType;
    address _tokenOwner;
    bool _locked;
}

mapping(uint256 => ParentTokenDetails) public TokenEnums;

I have a function where I try to do this but so far no luck:

function test()
    public
    returns (uint256)
{
    uint256 newItemId = 1;
    ParentTokenDetails._tokenType = TokenType.NON_FUNGIBLE;
    ParentTokenDetails._tokenOwner = msg.sender;
    ParentTokenDetails.children = ChildTokenDetails([TokenType.NULL, msg.sender, false]);
    TokenEnums[newItemId] = ParentTokenDetails;

    return newItemId;
}

Which prompts the error:

TypeError: Type struct EndLabsEnum.ChildTokenDetails memory is not implicitly convertible to expected type struct EndLabsEnum.ChildTokenDetails storage ref[] storage ref.

Ideally I would be able to create a struct for a new Id with an empty struct array I can add information to later.

Any pointers would help!

Full contract:

//SPDX-License-Identifier:MIT
pragma solidity 0.8.13;

contract TestEnum {
    enum TokenType{ FUNGIBLE, NON_FUNGIBLE, NULL }
    address public owner;

    struct ParentTokenDetails{
        TokenType _tokenType;
        address _tokenOwner;
        ChildTokenDetails[] children;
    }
    struct ChildTokenDetails{
        TokenType _tokenType;
        address _tokenOwner;
        bool _locked;
    }
    mapping(uint256 => ParentTokenDetails) public TokenEnums;

    constructor(){
        owner = msg.sender;
    }

    // Ensure minting of assets with duplicated Ids fail
    function mintNonFungibleTokenEnum(uint256 tokenID)
        public
        returns (uint256)
    {
        uint256 newItemId = 1;
        ParentTokenDetails._tokenType = TokenType.NON_FUNGIBLE;
        ParentTokenDetails._tokenOwner = msg.sender;
        ParentTokenDetails.children = ChildTokenDetails([TokenType.NULL, msg.sender, false]);
        TokenEnums[newItemId] = ParentTokenDetails;

        return newItemId;
}
2
  • Can you share all your smart contract code? Apr 15, 2022 at 14:56
  • done, added the full contract, its still early stages. just trying to get the nonfungible enum implemented for now Apr 15, 2022 at 15:08

1 Answer 1

2

For work around this issue you can modify your ChildTokenDetails[] inside ParentTokenDetails using a mapping. In your case, I thougth that you can use the tokenId for key in this second mapping and ChildTokensDetails[] for values.

At this point, you must change your ParentTokenDetails struct in this way:

struct ParentTokenDetails{
   TokenType _tokenType;
   address _tokenOwner;
   mapping(uint => ChildTokenDetails[]) children;
}

And then, you must update your mintNonFungibleTokenEnum function in this way:

function mintNonFungibleTokenEnum(uint256 tokenID)
    public
    returns (uint256)
{
    uint256 newItemId = 1;
    ParentTokenDetails storage ptd = tokenEnums[tokenID];
    ptd._tokenType = TokenType.NON_FUNGIBLE;
    ptd._tokenOwner = msg.sender;
    ptd.children[tokenID].push(ChildTokenDetails(TokenType.NULL, msg.sender, false));
    ptd.children[tokenID].push(ChildTokenDetails(TokenType.FUNGIBLE, msg.sender, false));
    return newItemId;
}

In the following line, I put your smart contract modified:

//SPDX-License-Identifier:MIT
pragma solidity 0.8.13;

import "hardhat/console.sol";

contract TestEnum {
    enum TokenType { FUNGIBLE, NON_FUNGIBLE, NULL }
    address public owner;

    struct ParentTokenDetails{
        TokenType _tokenType;
        address _tokenOwner;
        mapping(uint => ChildTokenDetails[]) children;
    }

    struct ChildTokenDetails{
        TokenType _tokenType;
        address _tokenOwner;
        bool _locked;
    }

    mapping(uint256 => ParentTokenDetails) public tokenEnums;

    constructor(){
        owner = msg.sender;
    }
    
    function mintNonFungibleTokenEnum(uint256 tokenID)
        public
        returns (uint256)
    {
        uint256 newItemId = 1;
        ParentTokenDetails storage ptd = tokenEnums[tokenID];
        ptd._tokenType = TokenType.NON_FUNGIBLE;
        ptd._tokenOwner = msg.sender;
        ptd.children[tokenID].push(ChildTokenDetails(TokenType.NULL, msg.sender, false));
        ptd.children[tokenID].push(ChildTokenDetails(TokenType.FUNGIBLE, msg.sender, false));
        return newItemId;
    }

    // Getter Child tokens 
    function getChildTokens(uint tokenId) external view returns(ChildTokenDetails[] memory _tokens) {
        ChildTokenDetails[] storage ctdS = tokenEnums[tokenId].children[tokenId];
        return ctdS;
    }
} 

Your Answer

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

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