# Gno Fee Taskforce WIP
## Goal
- Find how much gas is used for common types of transactions
- Estimate the amount of transactions of each type can be done by an average GNOT token holder
- Recommend gas fee adjustments
## Distribution (based on [indepence-day balances](https://github.com/gnolang/independence-day/blob/main/mkgenesis/balances.txt.gz))
Total number of accounts: 656,740
### Totals
- All: 752,454,999,663,089 ugnot
- Top 1000 accounts: 621,654,079,086,191 ugnot
- Bottom 1000 accounts: 2,000 ugnot
- All excluding the top and bottom 1000: 130,800,920,574,898 ugnot
### Weight
- Top 1000 accounts (0.15% of the total number of accounts) hold 82.62% of the total balance
- Bottom 1000 accounts (0.15% of the total number of accounts) hold 0.0000000003% of the total balance
### Averages
- All: 1,145,742,606.91 ugnot
- Top 1000 accounts: 621,654,079,086.19 ugnot
- Bottom 1000 accounts: 2.00 ugnot
- All excluding the top and bottom 1000: 199,775,362.09 ugnot
### Spread
- Variance of balances: 18,446,744,073,709,551,615
- Standard deviation of balances: 4,294,967,296
### Percentiles
- 99th percentile of balances: 4,060,691,105 ugnot
- 95th percentile of balances: 552,862,608 ugnot
- 90th percentile of balances: 239,673,979 ugnot
- 75th percentile of balances: 52,359,891 ugnot
- 50th percentile of balances: 8,388,001 ugnot (median)
- 25th percentile of balances: 194,150 ugnot
- 10th percentile of balances: 7,496 ugnot
- 5th percentile of balances: 4,872 ugnot
- 1st percentile of balances: 9 ugnot
## Gas usage
- Global average cost: 6,744,429 ugnot
- Median user (50th percentile) can call 1.24 times
- Bottom quarter user (25th percentile) can call 0.03 times
- Average user can call 169.88 times
- Average (excluding top and bottom 1000) can call 29.62 times
### Bank transfer
- Average cost: 45,116 ugnot
- Median user (50th percentile) can transfer 185.92 times
- Bottom quarter user (25th percentile) can transfer 4.30 times
- Average user can transfer 25,395.48 times
- Average (excluding top and bottom 1000) can transfer 4,428.04 times
### Realm "gno.land/r/demo/boards"
- Realm average cost: 6,357,615 ugnot
- Median user (50th percentile) can call 1.32 times
- Bottom quarter user (25th percentile) can call 0.03 times
- Average user can call 180.22 times
- Average (excluding top and bottom 1000) can call 31.42 times
#### Func "CreateBoard"
- Func "CreateBoard" average cost: 10,282,870 ugnot
- Median user (50th percentile) can call 0.82 times
- Bottom quarter user (25th percentile) can call 0.02 times
- Average user can call 111.42 times
- Average (excluding top and bottom 1000) can call 19.43 times
#### Func "GetBoardIDFromName"
- Func "GetBoardIDFromName" average cost: 1,137,910 ugnot
- Median user (50th percentile) can call 7.37 times
- Bottom quarter user (25th percentile) can call 0.17 times
- Average user can call 1,006.88 times
- Average (excluding top and bottom 1000) can call 175.56 times
#### Func "CreateThread"
- Func "CreateThread" average cost: 6,821,067 ugnot
- Median user (50th percentile) can call 1.23 times
- Bottom quarter user (25th percentile) can call 0.03 times
- Average user can call 167.97 times
- Average (excluding top and bottom 1000) can call 29.29 times
#### Func "CreateReply"
- Func "CreateReply" average cost: 6,983,445 ugnot
- Median user (50th percentile) can call 1.20 times
- Bottom quarter user (25th percentile) can call 0.03 times
- Average user can call 164.07 times
- Average (excluding top and bottom 1000) can call 28.61 times
#### Func "DeletePost"
- Func "DeletePost" average cost: 6,562,785 ugnot
- Median user (50th percentile) can call 1.28 times
- Bottom quarter user (25th percentile) can call 0.03 times
- Average user can call 174.58 times
- Average (excluding top and bottom 1000) can call 30.44 times
### Realm "gno.land/r/demo/grc20factory"
- Realm average cost: 7,131,244 ugnot
- Median user (50th percentile) can call 1.18 times
- Bottom quarter user (25th percentile) can call 0.03 times
- Average user can call 160.67 times
- Average (excluding top and bottom 1000) can call 28.01 times
#### Func "NewWithAdmin"
- Func "NewWithAdmin" average cost: 7,538,156 ugnot
- Median user (50th percentile) can call 1.11 times
- Bottom quarter user (25th percentile) can call 0.03 times
- Average user can call 151.99 times
- Average (excluding top and bottom 1000) can call 26.50 times
#### Func "Mint"
- Func "Mint" average cost: 6,575,337 ugnot
- Median user (50th percentile) can call 1.28 times
- Bottom quarter user (25th percentile) can call 0.03 times
- Average user can call 174.25 times
- Average (excluding top and bottom 1000) can call 30.38 times
#### Func "Burn"
- Func "Burn" average cost: 6,198,809 ugnot
- Median user (50th percentile) can call 1.35 times
- Bottom quarter user (25th percentile) can call 0.03 times
- Average user can call 184.83 times
- Average (excluding top and bottom 1000) can call 32.23 times
#### Func "Transfer"
- Func "Transfer" average cost: 8,212,674 ugnot
- Median user (50th percentile) can call 1.02 times
- Bottom quarter user (25th percentile) can call 0.02 times
- Average user can call 139.51 times
- Average (excluding top and bottom 1000) can call 24.33 times
## Onbloc Research & Notes
### Gno Transaction Fee Comparison in Devnet
- General Transfer:
- Fee: 0.000115 GNOT
- Used/Wanted: 47,066/55,015 (85.55%)
- Mint Transaction (GnoSwap):
- Fee: 0.405793 GNOT
- Used/Wanted: 162,318,280/194,780,448 (83.33%)
- The Mint transaction consumes about x3500 more fees than a general GNOT transfer transaction
- Even if the Mint transaction requires complex computation such as uint256, this gap is too large and seems abnormal.
- Mint function: https://github.com/gnoswap-labs/gnoswap/blob/main/contract/r/gnoswap/position/position.gno#L75
- A simple direct swap (not a complex routed swap) consumes 0.251787 GNOT, Used/Wanted of (100,715,640/120,857,292 (83.33%).
- Swap function: https://github.com/gnoswap-labs/gnoswap/blob/main/contract/r/gnoswap/pool/swap.gno#L44
### Transaction Fee Comparison in Portal-loop
- General Transfer:
- Fee: 0.000114 GNOT
- Used/Wanted: 44,310/54,271 (81.65%)
- Deposit (r/demo/wugnot, a simple contract):
- Fee: 0.01727 GNOT
- Used/Wanted: 6,908,950/8,289,264 (83.35%)
- A simple contract use consumes x151 more gas than a general transfer.
### Transaction execution information
- Realm Package: gno.land/r/demo/wugnot
- Function: Deposit
```shell
gnokey maketx call \
-pkgpath "gno.land/r/demo/wugnot" \
-func "Deposit" \
-send "1000ugnot" \
-gas-fee 1000000ugnot \
-gas-wanted 20000000 \
-broadcast \
-chainid dev \
test1
```
### Gas consumption by item
```
description: ReadFlat , consumed: 10000
description: WriteFlat , consumed: 10000
description: WritePerByte , consumed: 17610
description: ante verify: secp256k1 , consumed: 1000
description: GetPackageRealmPerByte , consumed: 35632
description: SetObjectPerByte , consumed: 31360
description: txSize , consumed: 2510
description: ReadPerByte , consumed: 3522
description: GetObjectPerByte , consumed: 2668848
description: CPUCycles , consumed: 158313
description: SetPackageRealmPerByte , consumed: 35632
description: DeleteObjectFlat , consumed: 7430
```
- Gas consumption is about 89.5% being consumed by the item called GetObjectPerByte.
- Items that load the VM’s state objects
Consuming gas to load objects seems like a reasonable gas consumption.
However, the gas weight of `GetObjectPerByte` is multiplied by `16` and is consuming a lot of gas.
I have a couple questions here.
I’ll have to track what is being loaded further, but is a weight of `16` appropriate?
- GasConfig: https://github.com/gnolang/gno/blob/f35bbf2669aab346e59f9b1f66aff3880f258f8f/gnovm/pkg/gnolang/store.go#L116
Or what do you think about separating the weight of load package realms from load state objects?
- GetPackageRealm: https://github.com/gnolang/gno/blob/f35bbf2669aab346e59f9b1f66aff3880f258f8f/gnovm/pkg/gnolang/store.go#L342
- GetObject: https://github.com/gnolang/gno/blob/f35bbf2669aab346e59f9b1f66aff3880f258f8f/gnovm/pkg/gnolang/store.go#L397
---
## Giuseppe / Milos gas fee message
Here is where we do the fee validation:
https://github.com/gnolang/gno/blob/6f91a35f3fcb0da593a8b45f6b19d70865406e05/tm2/pkg/sdk/auth/ante.go#L333-L406
The block gas context value is set in the app setup:
https://github.com/gnolang/gno/blob/6f91a35f3fcb0da593a8b45f6b19d70865406e05/gno.land/pkg/gnoland/app.go#L124-L125
the initial value of the block gas context (price) is set in the init chainer:
https://github.com/gnolang/gno/blob/6f91a35f3fcb0da593a8b45f6b19d70865406e05/gno.land/pkg/gnoland/app.go#L330-L331
this param value is set in the initial auth params:
https://github.com/gnolang/gno/blob/6f91a35f3fcb0da593a8b45f6b19d70865406e05/tm2/pkg/sdk/auth/params.go#L34 (by default it's 0.001ugnot/gas, it's part of the genesis state in genesis.json):
```json
"auth": {
"params": {
"max_memo_bytes": "65536",
"tx_sig_limit": "7",
"tx_size_cost_per_byte": "10",
"sig_verify_cost_ed25519": "590",
"sig_verify_cost_secp256k1": "1000",
"gas_price_change_compressor": "10",
"target_gas_ratio": "70",
"initial_gasprice": {
"gas": "1000",
"price": "1ugnot"
}
}
}
```
This block-level gas price is updated in the EndBlocker logic:
https://github.com/gnolang/gno/blob/6f91a35f3fcb0da593a8b45f6b19d70865406e05/tm2/pkg/sdk/auth/keeper.go#L195-L205
The validators set the target gas ratio to move the minimum network gas fee up or down (check `calcBlockGasPrice`).
This value is updated through the params keeper, which we can call through governance proposals in gno code
---
The node-specific gas limit is also set in the app setup (config.toml param):
https://github.com/gnolang/gno/blob/6f91a35f3fcb0da593a8b45f6b19d70865406e05/gno.land/pkg/gnoland/app.go#L88.
Node operators can update this at any time before they start their node
@Ray Qin can correct me if I missed something in haste, but this should be it:
- network (block) gas fee limits are controlled through governance (govdao), using the params module. Initial state set in genesis state
- validator (node) gas fee limits are set through the config.toml , and are node-specific