📅  最后修改于: 2023-12-03 14:47:30.774000             🧑  作者: Mango
在 Solidity 中,calldata
是一个类型,用于在合约函数之间传递数据。和 memory
和 storage
类型相比,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;
}
这个函数声明了两个参数 to
和 amount
,然后在执行转账时修改了相关账户的余额。然而,如果我们在声明参数时使用了 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;
}
那么在函数内部,我们就只能读取 to
和 amount
,但不能修改它们;我们只能修改存储在合约中的账户余额。
calldata
关键字是 Solidity 中用于声明只读数据区域的类型。我们可以在函数定义中使用 calldata
来声明函数参数,以指明参数位于交易数据中,不能被改变。在处理诸如 ERC20 转账等需要从交易数据中读取输入的情况下,calldata
将非常有用。