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)

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

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


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

  "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