Solidity----view、storage的gas花费

本文探讨了在以太坊DApp中优化gas消耗的方法,包括合理使用view函数以减少玩家成本,以及避免不必要的存储写入来降低费用。view函数在外部调用时无需消耗gas,但若由非同一合约内的函数调用则会产生成本。存储操作尤其是写入操作极其昂贵,应尽可能避免。

1、“view” 函数不花 “gas”

当玩家从外部调用一个view函数,是不需要支付一分 gas 的。

这是因为 view 函数不会真正改变区块链上的任何数据 - 它们只是读取。因此用 view 标记一个函数,意味着告诉 web3.js,运行这个函数只需要查询你的本地以太坊节点,而不需要在区块链上创建一个事务(事务需要运行在每个节点上,因此花费 gas)。

所以,在只读的函数上标记上表示“只读”的“external view 声明,就能为你的玩家减少在 DApp 中 gas 用量。

注意:如果一个 view 函数在另一个函数的内部被调用,而调用函数与 view 函数的不属于同一个合约,也会产生调用成本。这是因为如果主调函数在以太坊创建了一个事务,它仍然需要逐个节点去验证。所以标记为 view 的函数只有在外部调用时才是免费的。

2、storage是非常昂贵的

”写入“操作尤其贵。

这是因为,无论是写入还是更改一段数据, 这都将永久性地写入区块链。需要在全球数千个节点的硬盘上存入这些数据,随着区块链的增长,拷贝份数更多,存储量也就越大。这是需要成本的!

为了降低成本,不到万不得已,避免将数据写入存储。这也会导致效率低下的编程逻辑 - 比如每次调用一个函数,都需要在 memory(内存) 中重建一个数组,而不是简单地将上次计算的数组给存储下来以便快速查找。

 

参考:CryptoZombies

<think>我们正在讨论Solidity中的存储概念。用户询问的是storagestorage slot之间的区别。 根据Solidity文档和知识: - storage:在Solidity中,storage指的是区块链上永久存储数据的区域。它是合约的状态变量存储的地方,其数据在交易之间和调用之间持久存在。storage是持久的,并且读写操作消耗的gas较多。 - storage slot:storage slot是storage中存储数据的位置。每个storage slot大小为256位(32字节)。状态变量根据其类型和声明顺序被分配到具体的storage slot。例如,连续声明的uint256变量会占用连续的slot。 因此,区别在于: - storage是一种存储位置(与memory、calldata等相对),用于永久存储数据。 - storage slot则是storage区域中的具体存储单元(每个单元32字节),状态变量被存储在特定的slot中。 另外,复杂类型(如动态数组、映射)的存储布局有特定规则: - 映射:通过keccak哈希计算来确定值的存储位置。 - 动态数组:在声明的slot位置存储数组长度,而数组元素则从keccak哈希计算得到的slot开始连续存储。 我们还需要注意: - 多个变量可能共享同一个storage slot,如果它们的大小小于32字节(例如,多个连续的小整数类型变量可以打包在一个slot中)。 因此,总结回答: storage是存储区域,而storage slot是此区域中具体的位置索引(每个索引对应32字节)。 根据要求,我们需要生成相关问题。 注意:引用站内资料[^1](虽然具体内容未给出,但根据用户提供的引用片段,我们知道它涉及存储布局,所以我们可以在回答中引用这个资料)。 </think> ### Soliditystoragestorage slot 的区别 #### 1. **storage(存储区域)** - **定义**:`storage` 是 Solidity 中**永久存储在区块链上的数据区域**,所有合约状态变量(非 `constant`/`immutable`)默认存储在 `storage` 中[^1]。 - **特性**: - 数据**持久化**:写入链上后永久存在,消耗高额 gas- **全局可见**:公开可读(除非标记 `private`),合约内外均可访问。 - **引用语义**:变量传递时传递指针(地址引用),而非值拷贝。 ```solidity contract Example { uint256 public data; // 存储在 storage } ``` #### 2. **storage slot(存储槽)** - **定义**:`storage slot` 是 `storage` 区域的**最小存储单元**,每个 slot 固定为 **32 字节(256 位)**。 - **核心机制**: - **线性分配**:状态变量按声明顺序分配 slot(从 slot 0 开始)。 ```solidity contract SlotDemo { uint256 a; // slot 0 (32字节) uint128 b; // slot 1 的前16字节 uint128 c; // slot 1 的后16字节(打包存储) } ``` - **复杂类型规则**: - **映射**:`mapping(key => value)` 的存储位置通过 `keccak256(key . slot)` 哈希计算得出。 - **动态数组**:声明的 slot 存储数组长度,元素位置按 `keccak256(slot) + index` 计算。 - **Slot 共享**:小于 32 字节的变量(如 `uint8`、`bool`)可共享同一 slot。 ### 关键区别总结 | **特性** | **storage** | **storage slot** | |-------------------|--------------------------------------|--------------------------------| | **性质** | 数据存储区域(逻辑概念) | 存储区域的物理单元(32字节) | | **作用** | 定义变量的存储位置 | 确定变量在 storage 中的物理地址 | | **操作对象** | 状态变量(如 `uint x`) | 变量的具体存储位置(如 slot 0)| | **Gas 成本** | 读写操作昂贵 | Slot 计算本身无 gas 成本 | ### 示例说明 ```solidity contract StorageDemo { uint256 public val1 = 100; // slot 0 mapping(address => uint) public balances; // slot 1(存储映射元数据) function getBalance(address addr) public view returns (uint) { // 计算 balance[addr] 的实际 slot: // slot = keccak256(abi.encode(addr, 1)) return balances[addr]; } } ``` 此例中: - `val1` 存储在 **storage slot 0**。 - `balances` 的存储位置基于 slot 1 和密钥哈希计算得出。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值