16

Is it possible to have a struct inside a struct? I am not sure about the data type internals, but I was basically trying to do something like (pseudo-code):

library IpfsUtils {

  struct IpfsHash {
    bytes32 hash;
    uint8 hashFunction;
    uint8 hashSize;
  }

  function insert(bytes _hash) {}
  function combine() {}
}

contract Members {

  struct Member {
     IpfsUtils.IpfsHash profile;
     uint id;
  }
  mapping (address => Member) public members;

  function addMember(uint id, bytes profileHash) {
    Member m = members[msg.sender];
    m.id = id;
    m.profile.insert(profileHash);
  } 
}

I'm trying to store an IPFS hash with fixed length data types and I thought about extracting the storage of the ipfs hash function, size and the actual bytes32 hash into its own struct.

Can someone point me somewhere to learn more about the internals?

EDIT: nested structs are possible. BUT the the mapping (here members) can not be public causing the following error: TypeError: Internal type is not allowed for public state variable

2
  • How can I pass nested struct in Remix IDE? Commented Oct 3, 2018 at 13:49
  • If you have a new question, please ask it by clicking the Ask Question button. Include a link to this question if it helps provide context. - From Review Commented Oct 3, 2018 at 15:40

1 Answer 1

19

You can store a struct in a struct.

pragma solidity ^0.4.11;

contract Nest {

  struct IpfsHash {
    bytes32 hash;
    uint hashSize;
  }

  struct Member {
    IpfsHash ipfsHash;
  }

  mapping(uint => Member) members;

  function addMember(uint id, bytes32 hash, uint size) public returns(bool success) {
    members[id].ipfsHash.hash = hash;
    members[id].ipfsHash.hashSize = size;
    return true;
  }

  function getMember(uint id) public constant returns(bytes32 hash, uint hashSize) {
    return(members[id].ipfsHash.hash, members[id].ipfsHash.hashSize);
  }
}

This nesting is a little on the pointless side if there is only one IPFS per Member as I assume is the case. I didn't want to fix too much and drift away from the original question.

Yes, you can nest structs inside structs. Mappings and arrays, too, or even mappings of structs or arrays of structs.

Possibly helpful: struct declarations are only declaring a type not instances of the type.

In terms of coordinating all this to make something useful, have a look at the patterns over here: Are there well-solved and simple storage patterns for Solidity?

If you are looking for a one-to-many (many IPFS per Member), this pattern might be helpful: https://medium.com/@robhitchens/enforcing-referential-integrity-in-ethereum-smart-contracts-a9ab1427ff42

Hope it helps.

2
  • that's awesome, thanks. One problem I have is with the mapping: why can that not be public - that a getter function is basically auto-generated? with a public members mapping I get the an TypeError error: "TypeError: Internal type is not allowed for public state variable"
    – bumi
    Commented Jul 23, 2017 at 21:11
  • Right. I believe that error is about the compiler not understanding exactly how to construct the getter. It rhymes with this head-scratcher: ethereum.stackexchange.com/questions/15060/…. Possibly someone else will chime in with a detailed explanation for this exact case. My workaround was to just build the getter. Commented Jul 23, 2017 at 23:57

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.