Skip to content

Latest commit

 

History

History
519 lines (339 loc) · 13.2 KB

README.md

File metadata and controls

519 lines (339 loc) · 13.2 KB

WTF Gas Optimization

Solidity gas optimization techniques, verified with Foundry.

总结 Solidity 智能合约省 gas 技巧,并使用 Foundry 验证。

Lead by @0xKaso

Outline

1. use constant and immutable

2. use calldata over memory

3. use Bitmap

4. use unchecked

5. use uint256 over uint8

6. use custom error over require/assert

7. use local variable over storage

8. use clone over new/create2 to deploy contracts

9. packing storage slots

10. use ++i as better increment

11. use uint in reentrancy guard

12. use < over <=

13. optimized selector/method id

14. selector/method-id order matters

15. use shorter string in require()

16. use short circuit in logic operation || or &&

17. delete variables to get gas refund

18. do not initialize state variables with default values

19. swap 2 variables in 1 line with destructuring assignment

20. set constructor to payable to save gas

21. use bytes32 for short string

22. use fixed-size array over dynamic array

23. use event to store data when possible

24. use mapping over array when possible

1. use constant and immutable

Code | 文章

Testing

forge test --contracts 01_Constant/Constant.t.sol --gas-report

Gas report

Function Name Gas Cost
varConstant 161 ✅
varImmutable 161 ✅
variable 2261

2. use calldata over memory

Code | 文章

Testing

forge test --contracts 02_CalldataAndMemory/CalldataAndMemory.T.sol --gas-report

Gas report

Function Name Gas Cost
writeByCalldata 67905 ✅
writeByMemory 68456

3. use Bitmap

Code | 文章

Testing

forge test --contracts 03_Bitmap/Bitmap.T.sol --gas-report

Gas report

Function Name Gas Cost
setDataWithBitmap 22366 ✅
setDataWithBoolArray 35729

4. use unchecked

Code | 文章

Testing

forge test --contracts 04_unchecked/Unchecked.T.sol --gas-report

Gas report

Function Name Gas Cost
forNormal 1910309
forUnckecked 570287 ✅

5. use uint256 over uint8

Code | 文章

Testing

forge test --contracts 05_Uint/Uint.T.sol --gas-report

Gas report

Function Name Gas Cost
read Uint8 2301
read Uint32 2301
read Uint256 2261 ✅
set Uint8 22234
set Uint128 22234
set Uint256 22238
UseUint8 53,427
UseUint32 53,895
UseUint256 42,950 ✅

6. use custom error over require/assert

Code | 文章

Testing

forge test --contracts 06_Error/Error.T.sol --gas-report

Gas report

Error Name Gas Cost
Assert 180
Require 268
Revert 164 ✅

7. use local variable over storage

Code | 文章

Testing

forge test --contracts 07_LocalData/LocalData.T.sol --gas-report

Gas report

Data Type Gas Cost
localData 1902339 ✅
storageData 4022155

8. use clone over new/create2 to deploy contract

Code | 文章

Testing

forge test --contracts 08_Clone/Clone.T.sol --gas-report

Gas report

Create Type Gas Cost
clone 41493 ✅
create2 93031
new 79515

9. packing storage slots

Code | 文章

Testing

forge test --contracts 09_Packing/Packing.T.sol --gas-report

Gas report

Create Type Gas Cost
normal 133521
packing 111351 ✅

10. use ++i as better increment

Code | 文章

forge test --contracts 10_Increment/Increment.T.sol --gas-report

Gas report

Increment Gas Cost
i += 1 204
i = i +1 204
i++ 198
++i 193 ✅

11. use Uint in Reentrancy Guard

Code | 文章

Testing

forge test --contracts 11_ReentrancyGuard/ReentrancyGuard.T.sol --gas-report

Gas report

ReentrancyGuard Gas Cost tips
Bool 27757
Uint01 27604 0 to non-zero -> 20000 gas
Uint12 13908 ✅ non-zero to non-zero -> 2900 gas

12. use < over <=

Code | 文章

Testing

forge test --contracts 12_LessThan/LessThan.t.sol --gas-report

Gas report

Operator Gas Cost
<= 250
< 247 ✅

13 optimized selector

Code | 文章

Testing

forge test --contracts 13_MethodName/MethodName.t.sol --gas-report

Gas report

Operator Gas Cost
regular selector 0xf8a8fd6d 5285
optimized selector 0x000073eb 5265 ✅

14 selector order

Code | 文章

Testing

forge test --contracts 14_MethodIdSort/MethodIdSort.t.sol --gas-report

Gas report

Operator Gas Cost
test1 0x0dbe671f 164
test2 0x66e41cb7 142
test3 0x0a8e8e01 120
test_y2K 0x000073eb 98 ✅

15 shorter string in require()

Code

Testing

forge test --contracts 15_RequireString/RequireString.t.sol --gas-report

Gas report

Operator Gas Cost
longString 2578
shortString 2347 ✅

16. short circuit in logic operation

Code

Testing

forge test --contracts 16_ShortCircuit/ShortCircuit.t.sol --gas-report

Gas report

Operator Gas Cost
normal 191,282
shortCircuit 120 ✅

17. delete variables to get gas refund

Code

Testing

forge test --contracts 17_DeleteVar/DeleteVar.t.sol --gas-report

Gas report

Operator Gas Cost
update 22,238
updateDefault 2360 ✅
updateDelete 2316 ✅

18. do not initialize state variables with default values

Code

Testing

forge test --contracts 18_InitDefault/InitDefault.t.sol --gas-report

Gas report

Operator Gas Cost
testDefault 67,148 ✅
testInitDefault 69,376

19. swap 2 variables in 1 line with destructuring assignment

Code

Testing

forge test --contracts 19_SwapVars/SwapVars.t.sol --gas-report

Gas report

This technique will not save gas, but it makes your code look better :p

Operator Gas Cost
swap 282
desSwap 282 ✅

20. set constructor to payable to save gas

You can cut out 10 opcodes in the creation-time EVM bytecode if you declare a constructor payable. The following opcodes are cut out:

  • CALLVALUE
  • DUP1
  • ISZERO
  • PUSH2
  • JUMPI
  • PUSH1
  • DUP1
  • REVERT
  • JUMPDEST
  • POP

In Solidity, this chunk of assembly would mean the following:

if(msg.value != 0) revert();

Code

Testing

forge test --contracts 20_PayableConstructor/PayableConstructor.t.sol --gas-report

Gas report

Operator Gas Cost
default 67,171
payable constructor 67,102 ✅

21. use bytes32 for short string

Code

Testing

forge test --contracts 21_Bytes32String/Bytes32String.t.sol --gas-report

Gas report

Operator Gas Cost
setBytes32 22,222 ✅
setString 22,682

22. use fixed-size array over dynamic array

Code

Testing

forge test --contracts 22_FixedSize/FixedSize.t.sol --gas-report

Gas report

Operator Gas Cost
set dynamic-length array 2,224,770 gas ✅
set fixed-length array 2,182,608

23. use event to store data when possible

Code

Testing

forge test --contracts 23_Event/Event.t.sol --gas-report

Gas report

Operator Gas Cost
useVar 22,216
useEvent 1,189 ✅

24. use mapping over array when possible

Code

Testing

forge test --contracts 24_MappingArray/MappingArray.t.sol --gas-report

Gas report

Operator Gas Cost
Mapping get 451 ✅
Mapping insert 22,385 ✅
Mapping remove 305 ✅
Array get 710
Array insert 44,442
Array remove 748

WTF Gas Optimization 贡献者

贡献者是WTF学院的基石

Reference

  1. Solidity-Gas-Optimization-Tips