📜  solidity 关键字 calldata (1)

📅  最后修改于: 2023-12-03 14:47:30.774000             🧑  作者: Mango

Solidity 关键字 calldata

在 Solidity 中,calldata 是一个类型,用于在合约函数之间传递数据。和 memorystorage 类型相比,calldata 对应的数据区域是只读的,并且存储在交易数据中。

语法

在函数定义中,可以使用 calldata 关键字来声明一个参数的类型。例如:

function foo(uint256 x, uint256[] calldata y) external pure returns (uint256) {
  // ...
}

这个函数接受两个参数:一个 uint256 类型的单值参数 x,和一个 uint256 类型的动态数组参数 y。注意这里声明 y 时使用了 calldata 关键字。

使用

对于 calldata 类型的参数,我们只能访问其中的数据,而不能改变它们。这是因为 calldata 区域位于事务数据中,一旦提交,就不能被修改。因此,合约函数可以读取 calldata 区域中的数据,处理它们并给出结果,但不能改变这些数据。

举个例子,考虑一个简单的 ERC20 合约中的转账函数:

function transfer(address to, uint256 amount) external returns (bool) {
   require(balanceOf[msg.sender] >= amount, "insufficient balance");

   balanceOf[msg.sender] -= amount;
   balanceOf[to] += amount;

   emit Transfer(msg.sender, to, amount);

   return true;
}

这个函数声明了两个参数 toamount,然后在执行转账时修改了相关账户的余额。然而,如果我们在声明参数时使用了 calldata 关键字:

function transfer(address to, uint256 amount) external returns (bool) {
   require(balanceOf[msg.sender] >= amount, "insufficient balance");

   balanceOf[msg.sender] -= amount;
   balanceOf[to] += amount;

   emit Transfer(msg.sender, to, amount);

   return true;
}

那么在函数内部,我们就只能读取 toamount,但不能修改它们;我们只能修改存储在合约中的账户余额。

总结

calldata 关键字是 Solidity 中用于声明只读数据区域的类型。我们可以在函数定义中使用 calldata 来声明函数参数,以指明参数位于交易数据中,不能被改变。在处理诸如 ERC20 转账等需要从交易数据中读取输入的情况下,calldata 将非常有用。