【问题标题】:Solidity smart contract: Data location must be "memory" or "calldata" for return parameter in function, but none was givenSolidity 智能合约:函数中返回参数的数据位置必须是“memory”或“calldata”,但没有给出
【发布时间】:2021-07-28 11:34:01
【问题描述】:

我正在深入探索以太坊和智能合约的开发。在一个简单的 todo 应用程序智能合约中,我收到以下错误:

我的代码:

pragma solidity ^0.4.4;

contract ToDo {
  struct Task{
    uint id;
    uint date;
    string content;
    string author;
    bool completed;
  }

  Task[] tasks;

  function createTask(string memory _content, string memory _author) public {
    tasks.push(Task(tasks.length, block.timestamp, _content, _author, false));
  }

  function getTask(uint id) public view 
    returns(
      uint,
      uint,
      string memory,
      string memory,
      bool
   ) {
     return(
       id,
       tasks[id].date,
       tasks[id].content,
       tasks[id].author,
       tasks[id].completed
     );
   }

   function getAllTasks() external view returns(Task[]){
     return tasks;
   }
}

错误行是 20 和 21 在尝试返回字符串的 getTask() 函数中。

【问题讨论】:

    标签: blockchain ethereum solidity smartcontracts


    【解决方案1】:

    回答原问题

    Solidity中的字符串在内部是作为字符数组处理的,对于数组等动态值,需要指定返回值的数据位置(见下图)。

    这是因为 Solidity 作为一门语言是基于 C++ 和 JS 的。

    此外,(“官方”)Solidity 编译器和相关实用程序是用 C++ 编写的,您没有 C 或 C++ 中的字符串。只是字符数组,所以这可能就是为什么将solidity中的字符串作为字符数组处理的原因。

      ...
    
      // You should consider using "blockchain.timestamp" instead of "now".
      function createTask(string memory _content, string memory _author) public {
        tasks.push(Task(tasks.length, now, _content, _author, false));
      }
    
      function getTask(uint id) public view 
        returns(
          uint,
          uint,
          string memory,
          string memory,
          bool
       ) {
         return(
           id,
           tasks[id].date,
           tasks[id].content,
           tasks[id].author,
           tasks[id].completed  // Also, removed the comma here because it would drop an empty tuple error.
         );
       }
       
       ...
    

    回答新问题

    TypeError: This type is only supported in the new experimental ABI encoder.

    确保在您的代码顶部添加pragma experimental ABIEncoderV2;,因为solidity versions under 0.8.0 don't support dynamic arrays with a depth level deeper than 1 by default, and you'll need to enable the experimental ABI for it to work,例如,数组数组,或者在您的情况下,是结构数组。

    【讨论】:

    • 好的,但是仍然出现类似“函数中返回参数的数据位置必须是“内存”或“调用数据”的错误,但没有给出。”
    • @Neelgorasiya 你能张贴你的错误和代码的截图吗?我已经使用remix.ethereum.org 尝试了上述解决方案,它可以正常编译和部署。
    • 这是您现在遇到的另一个错误,似乎 0.8.0 以下的solidity版本不使用ABI编码器的V2(它支持任意级别的嵌套数组,在此例如结构数组,它内部被处理为数组的数组)。所以有两种解决方案,你可以添加“pragma experimental ABIEncoderV2;”在您当前的代码之上,或使用solidity 0.8.X 版本,另外,请注意在您的松露配置中指定您的solidity 编译器版本,因为默认情况下它将使用松露的版本:i.prntscr.com/w50AcCbxTeeKADGLpDlvOQ.png
    • 不客气,但请考虑关闭问题(验证答案或其他)。
    猜你喜欢
    • 2020-02-04
    • 2019-04-26
    • 2019-04-26
    • 2018-11-16
    • 2022-09-29
    • 2021-09-02
    • 1970-01-01
    • 1970-01-01
    • 2022-08-20
    相关资源
    最近更新 更多