为什么自动生成的getter函数会产生气体成本



我认为在以太坊上读取数据应该是免费的,但在合同文档(链接如下(中指出,对于公共数组,自动生成的getter函数一次只返回一个元素,以避免高昂的天然气成本。

getter函数不是只读的吗?如果是这样的话,为什么会产生巨大的天然气成本?

请参阅中的Getter函数部分https://docs.soliditylang.org/en/v0.5.3/contracts.html

与智能合约交互主要有两种方式。

  • 只读call不含气体
  • 事务(可以生成状态更改-存储更改、事件日志等(需要煤气费

从链下客户端应用程序的角度来看,您可以使用Truffle call((函数、Web3 call((功能、JSON-RPC eth_call方法和其他几种方法调用调用。

从Solidity合同的角度来看,不进行状态更改的只读函数应标记为视图(读取区块链数据,例如getters(或纯函数(不要读取区块链的数据,例如数学助手(。


如果您有一个数组类型的public状态变量,那么您只能通过生成的getter函数检索数组的单个元素。这种机制的存在是为了避免在返回整个阵列时的高气体成本。可以使用参数指定要返回的单个元素,例如data(0)。如果你想在一次调用中返回整个数组,那么你需要编写一个函数

来源:从您的问题链接的文档

getter函数不是只读的吗?如果是这样的话,为什么会产生巨大的天然气成本

它是只读的。但这并不意味着只能使用只读调用来访问它。

当您向Contract A发送一个需要从Contract B读取数据的事务时,它会生成一个内部事务。示例:

合同A部署在0x123

pragma solidity ^0.8;
interface B {
// this is the generated getter function that the docs mention
function data(uint256 index) external returns (address);
}
contract A {
// executing this function requires a transaction
function getContractBFirstItem() external returns (address) {
B memory b = B(address(0x456));
// this creates an internal transaction (not a read-only call)
address firstItem = b.data(0);
return firstItem;
}
}

合同B部署在0x456

pragma solidity ^0.8;
contract B {
// the getter function is generated from this public property
address[] public data;

constructor() {
// so that fhe first item exists and we can test it
data.push(address(0x789));
}
}

只读函数在事务处理过程中执行时,即封装在可能改变状态的函数中时,可能会产生天然气成本。

这是因为,由于此事务需要验证,它将由网络节点执行。这代表了冗余工作,最终导致相同的结果(给定相同的初始状态和相同的事务顺序(。

为了避免这种情况,标准的gas费用适用于在状态更改事务期间调用的只读函数。

来源-https://blog.b9lab.com/calls-vs-transactions-in-ethereum-smart-contracts-62d6b17d0bc2

最新更新