Solidity Reference Passing – How to Pass By Reference in Solidity

assemblycontract-deploymentcontract-designcontract-developmentsolidity

I have a couple of questions.

First:

So, In a function, i created memory array. I want to pass this memory by reference to another function..

function test2() public returns(uint  a) {
        uint[2] memory gio;
        gio[0] = 100;
        gio[1] = 200;
        test3(gio);
        return gio[0];
    }
    
    
    function test3(uint[2] storage arr) private returns (uint) {
        arr[0] = 35;
    }

This doesn't work and says:

Invalid type for argument in function call. Invalid implicit
conversion from uint256[2] memory to uint256[2] storage pointer
requested. test3(gio); ^-^

Is it not possible ?

Second

internal and private functions are the only types of functions that can receive parameters as reference types, right ? since public and external functions being called could be dependent on another application, so another app can't pass parameters as references. Agreed ?

Third.

string test;
   
    function test2() public returns(uint  a) {
        test = " awesome ";
        test3(test);
        return 10;
    }
    
    
    function test3(string storage str) private  {
        str = " changed ";
    }

Why does calling test2 result in:

TypeError: Type literal_string " changed " is not implicitly
convertible to expected type string storage pointer. str = " changed
"; ^———^

Best Answer

When you declare a parameter as storage you are limiting the function to only accept parameters with that qualifier.

The qualifiers storage, memory and calldata specify where the data is located. You can convert implicitly storage to memory and calldata to memory, but the reverse is not possible.

string public stor = "banana";

function test(string calldata calld) external view {
    string memory memo = "pizza";

    foo(memo, stor);
    foo(calld, stor);  // Creates a copy of calld in memory and passes as parameter
    foo(stor, stor);   // Creates a copy of stor in memory and passes as parameter
    
    foo(memo, stor);
    // foo(memo, memo); // Cannot convert from memory to storage
    // foo(memo, calld); // Cannot convert from calldata to storage
}

function foo(string memory, string storage) internal view {
    
}

/* This fails because you can only use calldata on external functions
function bar(string calldata) internal view {
    
} */

Value types like bool, uintXXX, bytesYY, address, etc. are passed by value. Non-value tyeps like structs, arrays, string are passed by reference.

  • Functions that are public, internal and private can use types passed by reference but only if they are call from the same contract.

  • Functions public and external will receive a copy when called by a regular user of from another contract.

I don't know why, but at least since solc 0.3 it wasn't allowed.

Related Topic