0
pragma solidity >=0.5.0 <0.7.0;
contract Example{
    uint256[3] x;
    function setArr(uint256[3] memory y) public returns(uint256[3] memory){
        x=y;
       return getArr(x);
    }
    function getArr(uint256[3] storage z) internal pure returns(uint256[3] memory)
    {  return z;
    }
}
0

Short answer:

There is no syntax that will do that, by design.

Long answer:

The "why" of it relates to the EVM having different constraints than a CPU.

uint256[3] storage z is a storage pointer. That means it is represented by a single 32-byte pointer to a logical slot and the rest of the storage layout is implicit. It also means the function is inaccessible from outside the contract. Nothing outside can be trusted to refer directly to storage locations.

uint256[3] memory is a memory variable. These are transient and they don't persist after the function runs. This hints at the underlying fact that they live somewhere else. They're in the memory space, not the storage space.

So ... to get from storage to memory means copying data. It's not done automatically for (at least) two reasons.

  1. Too much voodoo would discourage the design of efficient contracts. An idiomoatic approach here, or a loop if there are significantly more than three makes clear to the developer that work is happening. Reading, copying & writing.

You could:

function getArr(uint256[3] storage z) internal pure returns(uint256[3] memory x) {  
  x[0]=z[0];
  x[1]=z[1];
  x[2]=z[2];
}

That makes it clear.

for(uint i=0; i<3; i++) { ... would also do it, but more expensively owing to the need to update and check i's state and jump around. That leads to the second reason which is, IMO, more fundamental.

  1. A process like that has O(n) complexity, meaning the compute cost is directly proportional to the length of the array. Unbounded loops are a gotcha that can make a contract seem to work and then fail at scale. Iteration and recursion are powerful tools when compute power is essentially unlimited but they are deadly in a setting with hard caps on the computing resources available. That causes one to rethink what the contract should be doing. https://blog.b9lab.com/getting-loopy-with-solidity-1d51794622ad

    That issue would not go away if the compiler had high-level grammar to help translate intentions into OPCODE. Everything in the EVN has a fixed cost for a fixed unit of work and this principle is also apparent in the high-level languages. In other words, if there was an explicit or implicit "copy array" function, it would be very dangerous.

Hope it helps.

| improve this answer | |
  • The answer is not correct. The code does compile and it works as expected. The problem is that setArr is function called within a transaction so the returned value is not easily accessible off-chain (you have to execute a traceTransaction). – Ismael Jul 29 at 18:02
  • please can you expand on this as i have just started learning about blockchain? Thanks – user61878 Jul 29 at 18:36
  • Ismael has a good point. There is another problem if you are expecting to access return values while setting with a transaction. This is also important: blog.b9lab.com/… – Rob Hitchens Jul 30 at 2:17

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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