15

This code works:

contract C {
  function Get() constant returns(bytes8[]) {
    bytes8[] stuff;
    return stuff;
  }
  function Copy() {
    bytes8[] memory stuff = Get();
  }
}

But when I try to call Get() in another way...

contract A {
  A other;
  function Get() constant returns(bytes8[]) {
    bytes8[] stuff;
    return stuff;
  }
  function Copy() {
    bytes8[] stuff = other.Get();
  }
}

I get this error:

DynamicType.sol:8:5: Error: Type inaccessible dynamic type is not implicitly convertible to expected type bytes8[] memory.
    bytes8[] memory stuff = other.Get();
    ^---------------------------------^

I come from the Javascript world where we don't have to worry about storage vs memory types. I have read the section in the Solidity docs on Data Location but it would be helpful to get an explanation particular to this example so that I can better connect the concepts.

dragosb
  • 2,370
  • 13
  • 23
Raine Revere
  • 3,600
  • 2
  • 23
  • 34

1 Answers1

7

To answer the main question that the OP is asking: the problem is that the EVM is unable to read variably-sized data from external function calls.

If you replace, in Get(), bytes8[] with uint you will see the error disappear.

Here (https://gist.github.com/raineorshine/ab40fa8c967e96dc94a1d34e2a79179b) is an example which shows, if you copy paste it in the solidity browser, that the error is not related to storage or memory issues.

dragosb
  • 2,370
  • 13
  • 23
  • Hi! Thank you for your explanation. The main message I'm getting is that you cannot dynamically allocate variables in storage. It does not answer my question specifically, but it is useful information nonetheless. (The error I get occurs when there is a reference to another instance, not the current instance. Naturally, removing the other instance as you did changes the problem. "The error you receive is because you don't initialize other" -> this is simply not true; the error occurs at compile-time, and occurs whether it is initialized or not.) – Raine Revere Jul 30 '16 at 19:20
  • how do you initialize it ? because if you try A other = new A() you get an error because you cannot create a contract of the same type inside a contract. – dragosb Jul 30 '16 at 19:26
  • You can pass in the address from the outside before calling Copy(): https://gist.github.com/raineorshine/35305e0a35e7e1184a6d4d54cbc853d4 – Raine Revere Jul 30 '16 at 19:28
  • The question is more about what specifically is causing the error rather than whether the pattern makes sense architecturally for a specific problem. – Raine Revere Jul 30 '16 at 19:29
  • I did some tests and I think the problem is that the EVM is unable to read variably-sized data from external function calls. If you replace, in Get(), bytes8[] with uint you will see the error disappear. – dragosb Jul 30 '16 at 19:41
  • Apparently this is confirmed here: https://github.com/ethereum/solidity/issues/164 – dragosb Jul 30 '16 at 19:45
  • Thank you, that is indeed the problem. It was obscured by memory/storage, which wasn't the problem. – Raine Revere Aug 05 '16 at 15:58
  • I would be happy to accept your answer if you remove your original attempt before UPDATE (it ends up being distracting since it has to do with an unrelated issue) and include the code from this gist which demonstrates that the problem is not related to memory vs storage: https://gist.github.com/raineorshine/ab40fa8c967e96dc94a1d34e2a79179b. Just wanted to give you the opportunity to have the accepted answer, though if you're not interested in making those changes I understand and will add an answer. Thanks! – Raine Revere Aug 05 '16 at 16:01
  • I agree that is distracting from your question. I will update the answer. – dragosb Aug 05 '16 at 16:46