# Arbitrum Gas Tests
This document aims to get a sense of gas costs on arbitrum and gas optimisations:
- [L1 Fixed cost](#L1-Fixed-Cost)
- [L1 Calldata cost](#L1-Calldata-Cost)
- [L2 Computation cost](#L2-Computation-Cost)
- [L2 Storage cost](#L2-Storage-Cost)
### Notes:
- Assuming Arbitrum Gas Price: 1 Gwei and 4000 ETHUSD ($4*10^-6^ per ArbGas).
- Reference doc for [ArbGas](https://developer.offchainlabs.com/docs/arbgas).
- Cost of $4.59 Uniswap V3 Trade (0.97 gwei) on Arbitrum ([arbiscan](https://arbiscan.io/tx/0x79db9d925014a9500bdc0d813d75fa7af238447f5f07e2fe4106d135710fa315#txninfo)):
- $1.78 due to L1 Fixed
- $2.57 due to L1 Calldata
- $0.24 due to L2 Computation
- $0 due to L2 Storage (no slots were initialized)
## L1 Fixed Cost
Just like the intrinsic gas cost on L1, here it is 460,000 ArbGas ($1.84).
But still it's a lot fee (like almost 1/3rd of entire tx), can be optimised if the application can allow users to batch multiple operations in one transaction. But need to keep an eye on the calldata cost :P
## L1 Calldata Cost
Each non-zero byte of calldata adds about 2116 ArbGas ($0.0084), and each zero byte of calldata costs about 460 ArbGas ($0.0018). One null bytes32 costs about $0.084 and one non-null bytes32 costs about $0.3.
Can be optimised if calldata can be minimized or made compact.
```
example: transfer(address,uint96)
standard ABI encoded:
0xa0017938 00000000000000000000000074cde9f903af94a59b74df2252611f3b30e1dba2 0000000000000000000000000000000000000000000000000de0b6b3a7640000
Zeros: 0+12+26 = 38
NonZeros: 4+20+6 = 30
Cost: $0.32
compact ABI encoded:
0x01 74cde9f903af94a59b74df2252611f3b30e1dba2 000000000de0b6b3a7640000
Zeros: 0+0+4 = 4
NonZeros: 1+20+6 = 27
Cost: $0.26
```
About 20% gas savings directly but if things are further optimised, i.e. using an account id instead of address, it can render more savings.
```
transfer(uint32,uint96) // representing user as uint32
0x01 74cde9f9 000000000de0b6b3a7640000
Zeros: 0+0+4 = 4
NonZeros: 1+4+6 = 11
Cost: $0.1
```
It means not only calldata should be encoded compactly, but contracts should try to avoid bulky values like address and bytes32 hash stuff on L2s (only use it if there is no way out).
<!--
```
Rough work
0x: 639400 (1380)
0x11: 642620 (+3220)
0x00: 641240 (+1840 460*4)
0x0000: 641700 (+2300 460*5)
0x000000: 642160 (+2760 460*6)
0x00000000: 642620 (+3220 460*7)
0x0000000000: 643080 (+3680 460*8)
0x1212121212: 649980 (+10580)
0x00000000000000000000: 645380 (+5980)
0x11111111111111111111: 660560 (+21160)
0x0000000000000000000000000000000000000000: 649980 (+10580)
0x00000000000000000000000000000000000000000000000000000000000000000000000000000000: 660560 (+21160)
0x11111111111111111111111111111111111111110000000000000000000000000000000000000000: 688160 (+48760)
0x11111111111111111111111111111111111111111111111111111111111111111111111111111111: 714380 (+74980)
460 per 00
2116 per 11
```
-->
## L2 Computation Cost
Reference: [AVM](https://developer.offchainlabs.com/docs/avm_specification)
TL;DL it's pretty cheap, something that should not be worried much about.
## L2 Storage Cost
This is Storage expansion cost. When a contract changes a slot from 0 to non zero, a storage unit is added (200K ArbGas or $1). This is pretty massive. Also there are no refunds when storage is uninitialized. A contract should try to not uninitialize a storage if the slot will be used again (think of ERC20 balances, user transfers all balance out, slot gets uninitialized).
### SSTORE
- Slot initialization: 200K ArbGas ($1)
- In a transaction:
- First SSTORE in the transaction: 3K ArbGas ($0.024)
- SSTOREs after that 100 ArbGas ($0.0008)
<!--
```
Raw Data:
0 sstore tx: 663667
1 sstore tx: 666619 (first time: 863907)
10 sstore tx: 668347
100 sstore tx: 684252
``` -->
### SLOAD
- Reading uninitialized storage are not charged
- In a transation:
- First SLOAD is 2100 ($0.017)
- SLOADs for same slots are about 100 ArbGas ($0.0008)
<!--
```
Raw Data:
0 base cost: 663668; with unint sload: 663661
1 event tx: 666661; with unint sload: 666644
2: 666894 665488
3: 665748 665711
4: 667361 665935
5: 666215 667539
10 event tx: 666002; with unint sload: 667278
100 event tx: 687010; with unint sload: 688795
| Loops | Base Tx Cost | Uninitialized storage | Initialized Storage |
| ----- | ------------ | --------------------- | ------------------- |
| 0 | 663668 | 663661 | 663661 |
| 1 | 666661 | 666644 | 665265 |
| 10 | 666002 | 667278 | 667281 |
| 100 | 687010 | 688795 | 688828 |
```
```
Loops SLOAD SSTORE
0 648804 647424 647258
1 650266 850343 848798
1 650269 648911 647366 650126 (sstore that doesnt change value is cheaper)
2 650354 663501 650232 648852 646092
``` -->