3

I know how to instantiate a memory array. Looks like this:

address[] memory users = new address[](1);
users[0] = address(0x0);

But I cannot create a calldata array in this same fashion. Any pointers?

9
  • Calldata is used to reference the area with the message received by the contract. It is not possible to change its content or add more data. Why would you need to create more calldata?
    – Ismael
    Commented May 20, 2021 at 0:48
  • I don't want to change its content. I need to call an internal function which takes in calldata, and as part of that I need to create a calldata array in a different on-chain function. I just want to instantiate a calldata array and never change it - in Solidity. Do you know how to do this? Commented May 20, 2021 at 1:05
  • You can only get them inside the external function that was called, e.g. function foo(bytes calldata a) external { /* use a here */ }. In some cases using memory instead of calldata will work. You can't create a calldata variable.
    – Ismael
    Commented May 20, 2021 at 1:28
  • So there's no way to instantiate a calldata array from within Solidity? It has to be created from web3py or web3js? Commented May 20, 2021 at 19:25
  • You cannot "create" calldata but you can assign and pass around existing variables: uint256[] calldata data = existing_data; some_function(data);.
    – Ismael
    Commented May 21, 2021 at 5:06

1 Answer 1

3

An easy solution for inheriting from IFlashLoanReceiver is to create an internal function that is callable from the executeOperation.

// SPDX-License-Identifier: ISC

pragma solidity 0.6.12;

// Interface cannot be modified
interface IFlashLoadReceiver {
    function executeOperation(
        address[] calldata assets,
        uint256[] calldata amounts,
        uint256[] calldata premiums,
        address initiator,
        bytes calldata params
    ) external returns (bool);
}

contract Demo is IFlashLoadReceiver {
    // Override inherited function
    function executeOperation(
        address[] calldata assets,
        uint256[] calldata amounts,
        uint256[] calldata premiums,
        address initiator,
        bytes calldata params
    ) override external returns (bool) {
        // Call real implementation
        // Compiler takes care of calldata to memory convertion
        return doExecuteOperation(assets, amounts, premiums, initiator, params);
    }

    // Real implementation callable by other internal functions
    function doExecuteOperation(
        address[] memory assets,
        uint256[] memory amounts,
        uint256[] memory premiums,
        address initiator,
        bytes memory params
    ) internal returns (bool) {
        // Do something with parameters
        return false;
    }

}

Another solution is to be aware that calldata and memory are not part of the function signature. So from the outside function foo(bytes calldata x) external has the same signature as function foo(bytes memory x) public so you can make the function public instead of external and replace calldata by memory where appropriate and it should work (tm).

contract Demo {
    function executeOperation(
        address[] memory assets,
        uint256[] memory amounts,
        uint256[] memory premiums,
        address initiator,
        bytes memory params
    ) public returns (bool) {
        // do something
        return false;
    }
}
0

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.