2

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 "; ^---------^

1 Answer 1

7

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.

3
  • the answer for the second question. you say: Functions that are public, internal and private can use types passed by reference but only if they are call from the same contract. Still, if you have storage keyword on parameter for the public function, compiler screams and doesn't let you do it. Oct 3, 2020 at 23:50
  • also, compiler screams for this: function test(string calldata calld) external view { , calldata location is not allowed here Oct 3, 2020 at 23:52
  • @NikaKurashvili Solc errors out when using storage as qualifier in public function as you said, but it does work with memory qualifier. I'm testing with solc 0.6.6 and 0.7.2 and both accept function test(string calldata calld) external view without a warning.
    – Ismael
    Oct 3, 2020 at 23:56

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.