Skip to content

WTF Solidity gas optimization techniques, verified with Foundry.

Notifications You must be signed in to change notification settings

WTFAcademy/WTF-gas-optimization

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

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
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

Releases

No releases published

Packages

No packages published