0

Is is possible to make getFirst10() to work? It seems impossible to cast the uint256[100] memory to uint256[10] memory.

contract Test {
  uint256[100] private foo;

  function get() external view returns (uint256[100] memory) {
    return foo;               // Works
  }
  function getFirst10() external view returns (uint256[10] memory) {
    return uint256[10](foo);  // Doesn't compile
  }
}

The closest I've gotten is is the try above, but it fails with the error: Error: Explicit type conversion not allowed from "uint256[100] storage ref" to "uint256[10] storage pointer"

What I'm trying to do is have a function that returns a sub-slice of a large uint256[] storage array.. is there any way to do that? Do I have to return calldata instead and copy each element?

Erik
  • 87
  • 3
  • why you want to this? uint256[100] memory to uint256[10] memory – Wang Liang Aug 24 '21 at 00:50
  • I'd like to return a slice of a uint256[] on storage. I only need a subset of the data. – Erik Aug 24 '21 at 01:00
  • https://ethereum.stackexchange.com/questions/78559/how-can-i-slice-bytes-strings-and-arrays-in-solidity – Wang Liang Aug 24 '21 at 01:03
  • Slice syntax doesn't work on storage arrays. I was wondering if there was some other casting syntax, but I think the solution it just to loop and copy elements into a new static memory array in the function. – Erik Aug 24 '21 at 01:15
  • https://gist.github.com/oscarguindzberg/fba0086c185022ef2def66841fc80c1f – Wang Liang Aug 24 '21 at 01:20
  • That seems very interesting, but I'm definitely not advanced enough to understand what is going on there. I'd be concerned about the portability/forward compatibility of things that have assembly{} and custom pointer encoding, but again I'm still new. Thanks for opening my eyes up to new solidity-fu, though! – Erik Aug 24 '21 at 01:27

1 Answers1

0

I think the proper solution is just to create a function-local memory array of the desired fixed size, and copy elements. After reading a bit more about "storage" vs "memory", I'm guessing the EVM does this exact thing for you in the "same size" case, but otherwise there doesn't seem to be any casting syntax to avoid writing the loop yourself. I don't think there are performance or gas cost implications, but could be wrong.

  function getFirst10() external view returns (uint256[10] memory) {
    uint256[10] chunk;
    for (uint32 j = 0; j < 10; j++) {
      chunk[j] = foo[j];
    }
    return chunk;
  }
Erik
  • 87
  • 3