Home

Awesome

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 NameGas Cost
varConstant161 ✅
varImmutable161 ✅
variable2261

2. use calldata over memory

Code | 文章

Testing

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

Gas report

Function NameGas Cost
writeByCalldata67905 ✅
writeByMemory68456

3. use Bitmap

Code | 文章

Testing

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

Gas report

Function NameGas Cost
setDataWithBitmap22366 ✅
setDataWithBoolArray35729

4. use unchecked

Code | 文章

Testing

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

Gas report

Function NameGas Cost
forNormal1910309
forUnckecked570287 ✅

5. use uint256 over uint8

Code | 文章

Testing

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

Gas report

Function NameGas Cost
read Uint82301
read Uint322301
read Uint2562261 ✅
set Uint822234
set Uint12822234
set Uint25622238
UseUint853,427
UseUint3253,895
UseUint25642,950 ✅

6. use custom error over require/assert

Code | 文章

Testing

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

Gas report

Error NameGas Cost
Assert180
Require268
Revert164 ✅

7. use local variable over storage

Code | 文章

Testing

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

Gas report

Data TypeGas Cost
localData1902339 ✅
storageData4022155

8. use clone over new/create2 to deploy contract

Code | 文章

Testing

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

Gas report

Create TypeGas Cost
clone41493 ✅
create293031
new79515

9. packing storage slots

Code | 文章

Testing

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

Gas report

Create TypeGas Cost
normal133521
packing111351 ✅

10. use ++i as better increment

Code | 文章

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

Gas report

IncrementGas Cost
i += 1204
i = i +1204
i++198
++i193 ✅

11. use Uint in Reentrancy Guard

Code | 文章

Testing

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

Gas report

ReentrancyGuardGas Costtips
Bool27757
Uint01276040 to non-zero -> 20000 gas
Uint1213908 ✅non-zero to non-zero -> 2900 gas

12. use < over <=

Code | 文章

Testing

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

Gas report

OperatorGas Cost
<=250
<247 ✅

13 optimized selector

Code | 文章

Testing

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

Gas report

OperatorGas Cost
regular selector 0xf8a8fd6d5285
optimized selector 0x000073eb5265 ✅

14 selector order

Code | 文章

Testing

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

Gas report

OperatorGas Cost
test1 0x0dbe671f164
test2 0x66e41cb7142
test3 0x0a8e8e01120
test_y2K 0x000073eb98 ✅

15 shorter string in require()

Code文章

Testing

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

Gas report

OperatorGas Cost
longString2578
shortString2347 ✅

16. short circuit in logic operation

Code | 文章

Testing

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

Gas report

OperatorGas Cost
normal191,282
shortCircuit120 ✅

17. delete variables to get gas refund

Code | 文章

Testing

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

Gas report

OperatorGas Cost
update22,238
updateDefault2360 ✅
updateDelete2316 ✅

18. do not initialize state variables with default values

Code

Testing

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

Gas report

OperatorGas Cost
testDefault67,148 ✅
testInitDefault69,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

OperatorGas Cost
swap282
desSwap282 ✅

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:

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

OperatorGas Cost
default67,171
payable constructor67,102 ✅

21. use bytes32 for short string

Code

Testing

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

Gas report

OperatorGas Cost
setBytes3222,222 ✅
setString22,682

22. use fixed-size array over dynamic array

Code

Testing

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

Gas report

OperatorGas Cost
set dynamic-length array2,224,770
set fixed-length array2,182,608 ✅

23. use event to store data when possible

Code

Testing

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

Gas report

OperatorGas Cost
useVar22,216
useEvent1,189 ✅

24. use mapping over array when possible

Code

Testing

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

Gas report

OperatorGas Cost
Mapping get451 ✅
Mapping insert22,385 ✅
Mapping remove305 ✅
Array get710
Array insert44,442
Array remove748

WTF Gas Optimization 贡献者

<div align="center"> <h4 align="center"> 贡献者是WTF学院的基石 </h4> <a href="https://github.com/WTFAcademy/WTF-gas-optimization/graphs/contributors"> <img src="https://contrib.rocks/image?repo=WTFAcademy/WTF-gas-optimization" /> </a> </div>

Reference

  1. Solidity-Gas-Optimization-Tips