@@ -15,6 +15,397 @@ web2游戏大厂工作两年
1515## Notes
1616
1717<!-- Content_START -->
18+ # 2025-08-19
19+
20+ ## solidity中的Gas优化方案
21+
22+ ### 1. ** 变量声明优化**
23+
24+ #### 变量打包(Packing)
25+ ``` solidity
26+ // ❌ 浪费Gas:每个变量占用32字节
27+ contract Bad {
28+ uint256 a; // 32 bytes
29+ uint256 b; // 32 bytes
30+ uint256 c; // 32 bytes
31+ }
32+
33+ // ✅ 节省Gas:打包到同一槽位
34+ contract Good {
35+ uint128 a; // 16 bytes
36+ uint128 b; // 16 bytes
37+ uint256 c; // 32 bytes
38+ }
39+ ```
40+ ** Gas节省** :每个槽位节省约20,000 gas(存储操作)
41+
42+ #### 变量类型选择
43+ ``` solidity
44+ // ❌ 浪费Gas
45+ uint256 small = 1; // 32字节,浪费31字节
46+
47+ // ✅ 节省Gas
48+ uint8 small = 1; // 1字节,节省31字节
49+ ```
50+ ** Gas节省** :每个变量节省约5,000-15,000 gas
51+
52+ ### 2. ** 循环优化**
53+
54+ #### 循环边界优化
55+ ``` solidity
56+ // ❌ 浪费Gas:每次循环都读取数组长度
57+ for (uint i = 0; i < array.length; i++) {
58+ // 操作
59+ }
60+
61+ // ✅ 节省Gas:缓存数组长度
62+ uint length = array.length;
63+ for (uint i = 0; i < length; i++) {
64+ // 操作
65+ }
66+ ```
67+ ** Gas节省** :每次循环节省约100 gas
68+
69+ #### 循环展开
70+ ``` solidity
71+ // ❌ 标准循环
72+ for (uint i = 0; i < 4; i++) {
73+ array[i] = i;
74+ }
75+
76+ // ✅ 循环展开(适用于小循环)
77+ array[0] = 0;
78+ array[1] = 1;
79+ array[2] = 2;
80+ array[3] = 3;
81+ ```
82+ ** Gas节省** :小循环可节省约500-1,000 gas
83+
84+ ### 3. ** 函数优化**
85+
86+ #### 函数可见性
87+ ``` solidity
88+ // ❌ 浪费Gas:public函数自动生成getter
89+ uint256 public data;
90+
91+ // ✅ 节省Gas:明确指定可见性
92+ uint256 private data;
93+ ```
94+ ** Gas节省** :每个public变量节省约2,000 gas
95+
96+ #### 函数参数优化
97+ ``` solidity
98+ // ❌ 浪费Gas:使用storage引用
99+ function badFunction(uint[] storage arr) internal {
100+ uint[] storage temp = arr;
101+ }
102+
103+ // ✅ 节省Gas:使用calldata
104+ function goodFunction(uint[] calldata arr) external pure {
105+ // 直接使用arr,无需复制
106+ }
107+ ```
108+ ** Gas节省** :使用calldata可节省约5,000-20,000 gas
109+
110+ ### 4. ** 存储操作优化**
111+
112+ #### 批量操作
113+ ``` solidity
114+ // ❌ 浪费Gas:多次存储操作
115+ function badBatch() external {
116+ data[0] = 1; // 20,000 gas
117+ data[1] = 2; // 20,000 gas
118+ data[2] = 3; // 20,000 gas
119+ }
120+
121+ // ✅ 节省Gas:使用结构体批量存储
122+ struct BatchData {
123+ uint256 a;
124+ uint256 b;
125+ uint256 c;
126+ }
127+ function goodBatch() external {
128+ BatchData memory batch = BatchData(1, 2, 3);
129+ // 一次性存储,节省gas
130+ }
131+ ```
132+ ** Gas节省** :批量操作可节省约10,000-30,000 gas
133+
134+ #### 存储位置选择
135+ ``` solidity
136+ // ❌ 浪费Gas:频繁修改storage
137+ uint256[] public storageArray;
138+
139+ // ✅ 节省Gas:使用memory处理后再存储
140+ function processArray() external {
141+ uint256[] memory tempArray = new uint256[](100);
142+ // 在memory中处理
143+ // 最后一次性存储到storage
144+ }
145+ ```
146+ ** Gas节省** :memory操作比storage便宜约15,000-25,000 gas
147+
148+ ### 5. ** 事件优化**
149+
150+ #### 事件参数优化
151+ ``` solidity
152+ // ❌ 浪费Gas:过多indexed参数
153+ event BadEvent(
154+ address indexed from,
155+ address indexed to,
156+ uint256 indexed value, // 第三个indexed参数
157+ string message
158+ );
159+
160+ // ✅ 节省Gas:合理使用indexed
161+ event GoodEvent(
162+ address indexed from,
163+ address indexed to,
164+ uint256 value, // 非indexed,节省gas
165+ string message
166+ );
167+ ```
168+ ** Gas节省** :减少indexed参数可节省约375 gas
169+
170+ ### 6. ** Gas成本对比表**
171+
172+ | 操作类型 | Gas成本 | 优化建议 |
173+ | ---------| ---------| ----------|
174+ | ** 存储写入** | 20,000 gas | 批量操作,减少存储次数 |
175+ | ** 存储读取** | 2,100 gas | 缓存变量,避免重复读取 |
176+ | ** 内存分配** | 3 gas/字节 | 使用calldata,减少内存复制 |
177+ | ** 函数调用** | 2,100 gas | 内联小函数,减少调用开销 |
178+ | ** 循环迭代** | 100-500 gas/次 | 循环展开,缓存边界值 |
179+ | ** 事件日志** | 375 gas + 数据gas | 减少indexed参数,优化数据结构 |
180+
181+ ### 7. ** 实际优化示例**
182+
183+ ``` solidity
184+ // ❌ 未优化的合约
185+ contract Unoptimized {
186+ uint256 public value1;
187+ uint256 public value2;
188+ uint256 public value3;
189+
190+ function setValues(uint256 a, uint256 b, uint256 c) external {
191+ value1 = a;
192+ value2 = b;
193+ value3 = c;
194+ }
195+
196+ function processArray(uint256[] storage arr) external {
197+ for (uint i = 0; i < arr.length; i++) {
198+ arr[i] = arr[i] * 2;
199+ }
200+ }
201+ }
202+
203+ // ✅ 优化后的合约
204+ contract Optimized {
205+ // 变量打包
206+ uint128 public value1;
207+ uint128 public value2;
208+ uint256 public value3;
209+
210+ // 批量设置,减少存储操作
211+ function setValues(uint128 a, uint128 b, uint256 c) external {
212+ value1 = a;
213+ value2 = b;
214+ value3 = c;
215+ }
216+
217+ // 缓存数组长度,使用memory处理
218+ function processArray(uint256[] calldata arr) external pure returns (uint256[] memory) {
219+ uint256[] memory result = new uint256[](arr.length);
220+ uint256 length = arr.length;
221+
222+ for (uint i = 0; i < length; i++) {
223+ result[i] = arr[i] * 2;
224+ }
225+ return result;
226+ }
227+ }
228+ ```
229+
230+ ** 总Gas节省** :优化后的合约可节省约40,000-80,000 gas(取决于操作复杂度)
231+
232+ ### 8. ** 最佳实践总结**
233+
234+ 1 . ** 变量声明** :合理打包,选择合适类型
235+ 2 . ** 循环优化** :缓存边界值,考虑循环展开
236+ 3 . ** 函数设计** :减少storage操作,使用calldata
237+ 4 . ** 存储策略** :批量操作,减少存储次数
238+ 5 . ** 事件优化** :合理使用indexed参数
239+ 6 . ** 代码审查** :定期检查gas使用情况
240+
241+ 通过这些优化,可以将合约的gas消耗降低20-40%,显著提升用户体验和成本效益。
242+
243+ ---
244+
245+ ## Gas费用与ETH换算关系
246+
247+ ### 1. ** 基本换算公式**
248+
249+ ```
250+ 交易费用 = Gas使用量 × Gas价格
251+ ```
252+
253+ 其中:
254+ - ** Gas使用量** :合约执行所需的计算资源(固定值)
255+ - ** Gas价格** :用户愿意为每个Gas单位支付的ETH数量(可调整)
256+
257+ ### 2. ** Gas价格单位换算**
258+
259+ #### Wei(最小单位)
260+ ``` solidity
261+ 1 ETH = 10^18 Wei
262+ 1 Gwei = 10^9 Wei
263+ 1 ETH = 10^9 Gwei
264+ ```
265+
266+ #### 常用Gas价格范围
267+ | 网络拥堵程度 | Gas价格范围 | 说明 |
268+ | -------------| -------------| ------|
269+ | ** 低拥堵** | 5-20 Gwei | 交易确认时间:1-2分钟 |
270+ | ** 中等拥堵** | 20-50 Gwei | 交易确认时间:2-5分钟 |
271+ | ** 高拥堵** | 50-100+ Gwei | 交易确认时间:5-15分钟 |
272+ | ** 极端拥堵** | 100-500+ Gwei | 交易确认时间:15分钟以上 |
273+
274+ ### 3. ** 实际费用计算示例**
275+
276+ #### 简单转账交易
277+ ``` solidity
278+ // 标准ETH转账:21,000 gas
279+ Gas使用量 = 21,000 gas
280+ Gas价格 = 20 Gwei = 20 × 10^-9 ETH
281+
282+ 交易费用 = 21,000 × (20 × 10^-9) = 0.00042 ETH
283+ // 约等于 $0.84(假设ETH = $2,000)
284+ ```
285+
286+ #### 智能合约交互
287+ ``` solidity
288+ // 存储写入操作:20,000 gas
289+ Gas使用量 = 20,000 gas
290+ Gas价格 = 30 Gwei = 30 × 10^-9 ETH
291+
292+ 交易费用 = 20,000 × (30 × 10^-9) = 0.0006 ETH
293+ // 约等于 $1.20(假设ETH = $2,000)
294+ ```
295+
296+ #### 复杂合约操作
297+ ``` solidity
298+ // 批量操作:100,000 gas
299+ Gas使用量 = 100,000 gas
300+ Gas价格 = 25 Gwei = 25 × 10^-9 ETH
301+
302+ 交易费用 = 100,000 × (25 × 10^-9) = 0.0025 ETH
303+ // 约等于 $5.00(假设ETH = $2,000)
304+ ```
305+
306+ ### 4. ** Gas价格动态调整机制**
307+
308+ #### EIP-1559费用模型
309+ ``` solidity
310+ // 新费用结构
311+ 总费用 = 基础费用 + 优先费用
312+
313+ 其中:
314+ - 基础费用:被销毁,动态调整
315+ - 优先费用:给矿工的小费
316+ ```
317+
318+ #### 基础费用计算
319+ ``` solidity
320+ // 基础费用根据区块使用率动态调整
321+ if (区块使用率 > 50%) {
322+ 基础费用 += 12.5%
323+ } else if (区块使用率 < 50%) {
324+ 基础费用 -= 12.5%
325+ }
326+ ```
327+
328+ ### 5. ** 不同网络Gas价格对比**
329+
330+ | 网络 | 平均Gas价格 | 特点 |
331+ | ------| -------------| ------|
332+ | ** 以太坊主网** | 15-50 Gwei | 安全性最高,费用较高 |
333+ | ** Polygon** | 0.1-1 Gwei | 费用极低,确认快速 |
334+ | ** BSC** | 3-10 Gwei | 费用适中,兼容性好 |
335+ | ** Arbitrum** | 0.1-0.5 Gwei | 费用低,L2解决方案 |
336+
337+ ### 6. ** Gas费用优化策略**
338+
339+ #### 时间选择
340+ ``` solidity
341+ // 选择低峰期执行交易
342+ // 美国东部时间:凌晨2-6点
343+ // 欧洲时间:凌晨3-7点
344+ // 亚洲时间:下午2-6点
345+ ```
346+
347+ #### 价格设置策略
348+ ``` solidity
349+ // 1. 设置Gas价格上限
350+ maxFeePerGas: 50 Gwei
351+ maxPriorityFeePerGas: 2 Gwei
352+
353+ // 2. 使用动态Gas价格
354+ // 根据网络拥堵程度自动调整
355+ ```
356+
357+ ### 7. ** 实际开发中的费用估算**
358+
359+ #### 使用Hardhat估算
360+ ``` javascript
361+ // 估算Gas使用量
362+ const gasEstimate = await contract .estimateGas .functionName (params);
363+ console .log (` 预估Gas: ${ gasEstimate .toString ()} ` );
364+
365+ // 估算费用
366+ const gasPrice = await ethers .provider .getGasPrice ();
367+ const fee = gasEstimate .mul (gasPrice);
368+ console .log (` 预估费用: ${ ethers .utils .formatEther (fee)} ETH` );
369+ ```
370+
371+ #### 使用Web3.js估算
372+ ``` javascript
373+ // 估算Gas
374+ const gasEstimate = await contract .methods .functionName (params).estimateGas ();
375+ console .log (` 预估Gas: ${ gasEstimate} ` );
376+
377+ // 获取当前Gas价格
378+ const gasPrice = await web3 .eth .getGasPrice ();
379+ const fee = gasEstimate * gasPrice;
380+ console .log (` 预估费用: ${ web3 .utils .fromWei (fee, ' ether' )} ETH` );
381+ ```
382+
383+ ### 8. ** 费用监控工具**
384+
385+ #### 实时监控网站
386+ - ** Etherscan Gas Tracker** :实时Gas价格
387+ - ** GasNow** :Gas价格预测
388+ - ** ETH Gas Station** :详细费用分析
389+
390+ #### 开发工具集成
391+ ``` javascript
392+ // 在DApp中集成Gas价格显示
393+ async function getGasPrice () {
394+ const gasPrice = await provider .getGasPrice ();
395+ const gwei = ethers .utils .formatUnits (gasPrice, ' gwei' );
396+ return ` ${ gwei} Gwei` ;
397+ }
398+ ```
399+
400+ ### 9. ** 总结**
401+
402+ 1 . ** Gas费用 = Gas使用量 × Gas价格**
403+ 2 . ** 1 ETH = 10^9 Gwei = 10^18 Wei**
404+ 3 . ** 标准转账:21,000 gas × 20 Gwei = 0.00042 ETH**
405+ 4 . ** 合约交互:20,000-100,000+ gas,费用因操作复杂度而异**
406+ 5 . ** 选择合适时机和Gas价格可显著降低交易成本**
407+ 6 . ** 使用工具监控和估算Gas费用,优化用户体验**
408+
18409# 2025-08-18
19410
20411整理开发快捷键
0 commit comments