1

As far as I am aware contract to contract calls store input arguments in memory. Or put more precisely they store them in memory and they can be accessed with CALLDATALOAD within the the new call frame. I am wondering however what is the point of specifying the input argument in a function as calldata, if you know that it will only be called from a contract (hence no gas savings of using the real calldata space which is only used EOA-> Contract calls).

It seems to me that it will be treated as memory either way?

1 Answer 1

2

I am wondering however what is the point of specifying the input argument in a function as calldata, if you know that it will only be called from a contract (hence no gas savings of using the real calldata space which is only used EOA-> Contract calls).

That is not true, calldata is present for both EOA to CA and CA to CA. In the EVM implementation, this is the input.

Typically, executing a transaction runs the interpreter the same way the call opcode implementation does.

Doing a call , delegatecall , staticcall from one contract to another will put the data passed along the call in calldata.

You can also see gas consumption gains even if the initial transaction is the same :

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;

contract Caller {

    Callee immutable public callee;

    constructor(Callee _callee) {
        callee = _callee;
    }

    function testCallerCalldata(bytes calldata data) external {
        callee.testCalleeCalldata(data);
    }

    function testCallerMemory(bytes calldata data) external {
        callee.testCalleeMemory(data);
    }
}

contract Callee {

    function testCalleeCalldata(bytes calldata data) external {

    }

    function testCalleeMemory(bytes memory data) external {

    }

}

Calling testCallerCalldata costs less than testCallerMemory because the Callee contract won't have to copy any calldata to memory.

8
  • Thanks for your answer! If contract to contract calls function arguments go into calldata and not memory why does one not save on zero bytes within the arguments? Because when EOA calls a contract and the calldata passed along the zero bytes in that calldata cost less then none zero bytes
    – FreddyC
    Jan 9, 2023 at 7:33
  • also do you see any reason why OZ implementation of ERC721 would specify immutable input params as memory here? github.com/OpenZeppelin/openzeppelin-contracts/blob/…
    – FreddyC
    Jan 9, 2023 at 7:46
  • 1
    For the OZ implementation, I think it's because they are using the safeTransferFrom with empty data ( github.com/OpenZeppelin/openzeppelin-contracts/blob/… ) to be able to reuse the code with data, you cannot do that with calldata location as it would be uninitialized and therefore forbidden.
    – hroussille
    Jan 9, 2023 at 8:12
  • I'm not sure to understand your first comment though ?
    – hroussille
    Jan 9, 2023 at 8:12
  • 1
    Ah no you cannot use calldata in a constructor parameters, you can try it yourself it won't compile.
    – hroussille
    Jan 9, 2023 at 8: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.