Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

GasUsed does not affect gas fees taken from the user #3805

Open
zivkovicmilos opened this issue Feb 21, 2025 · 1 comment
Open

GasUsed does not affect gas fees taken from the user #3805

zivkovicmilos opened this issue Feb 21, 2025 · 1 comment
Labels
📦 ⛰️ gno.land Issues or PRs gno.land package related

Comments

@zivkovicmilos
Copy link
Member

zivkovicmilos commented Feb 21, 2025

Description

This issue is meant to bring light to some cumbersome aspects of dealing with user fees in gno.land, which started on a rabbit hole from #3771.

Issue 1 - actual gas used for a tx doesn't affect fees taken from the user

Our std.Fee is very misleading:

type Fee struct {
	GasWanted int64 `json:"gas_wanted" yaml:"gas_wanted"`
	GasFee    Coin  `json:"gas_fee" yaml:"gas_fee"`
}

The amount the user puts in the Fee is actually the total amount of whatever the user is willing to pay for the entire transaction, not just a single unit of gas.

The effective gas price is the ratio of the maximum gas wanted and the maximum fee (for the entire tx).

There are 2 problems I see with this approach:

  • we always subtract the entire fee the user set, regardless of the gas used, while on the other hand we force the user to find a good ratio that is above the minimum one set by the node / network (ex. if the transaction requires a lot of gas as a limit like 5M, the fee needs to be tuned as well manually in order to fall into the correct ratio range set by the network and validator, in this case 1M ugnot, if the min gas price is 0.2ugnot/gas). Additionally, two users can end up paying different amounts for a transaction, because they put down different valid fee ratios.
    • ⚠️ Our mempool implementation doesn't even sort transactions for a block by their gas price! ⚠️
  • the gas fees don't actually go anywhere, they are burned (see DeductFees, and trace where the banker sends the funds). This is a separate effort / issue
    err := bank.SendCoins(ctx, acc.GetAddress(), FeeCollectorAddress(), fees)
    if err != nil {
    return abciResult(err)
    }

I don't see how the GasWanted is not useless for transaction payments, given the user just specifies the maximum amount of gas to bypass a node limit, and the actual source of truth for what the user pays is whatever they put down as the Fee.Amount:

// deduct the fees
if !tx.Fee.GasFee.IsZero() {
res = DeductFees(bank, newCtx, signerAccs[0], std.Coins{tx.Fee.GasFee})
if !res.IsOK() {
return newCtx, res, true
}
// reload the account as fees have been deducted
signerAccs[0] = ak.GetAccount(newCtx, signerAccs[0].GetAddress())
}


Issue 2 - it's impossible to fetch the minimum price per unit of gas

The gno chain has a set minimum gas price in the form of a ratio, ex. 0.001ugnot/gas. There is a limit which is node controlled (validator), and a limit which is set by the network.

The second issue with utilizing fees and fee ratios the way we do -- is that the client (user) sending the transaction to the gno.land chain cannot estimate the gas fee ratio they'd need to put down for their transaction to go through.

For example, a user (client) who wants to send a transaction needs to do a few things:

  • estimate the gas limit (wanted) ----> they do this using the abci.simulate query. We have this endpoint in all of our gno clients (Go & JS). It is worth noting that the user needs to set an initial guessed value for the gas limit which is high, so the transaction will even be simulated by the node
    • In order to simulate a tx, they need to sign it (with the guessed gas wanted), get the appropriate gas wanted back from the endpoint, then proceed to put it into the transaction and resign it (the gas fee is a param that goes into the transaction signature). Imagine a multisig transaction that needs to go through this route.
  • they need to guess, literally guess the minimum gas fee ratio on the network, either though using an indexer service, or retrying with different values until the transaction is accepted into the mempool. Example error message a user will receive when guessing: insufficient fees; got: {Gas-Wanted: 100000, Gas-Fee 5ugnot}, fee required: {Gas:1000 Price:1ugnot} as block gas

These 2 issues affect different types of UX:

  • the user UX when sending transactions through wallets like Adena
  • the developer UX when programmatically trying to send transactions to the network

I'd like to know if we can reach some kind of agreement on user transaction fees that mitigates these issues, given we're not too far from the launch, and they have the biggest impact on user experience.

cc @jaekwon @moul @piux2 @dongwon8247

@salmad3
Copy link
Member

salmad3 commented Feb 21, 2025

With the code freeze in place and recognizing that a complete overhaul (such as moving away from the lumpsum model to a true pay-per-gas system, revising the transaction structure, and possibly introducing a standardized fee estimation API) is too complex to implement by launch, the immediate stopgap can be to add more predictability to the guesswork. This can be achieved by documenting the fixed gasPrice and a clear estimation process (to improve how closely the estimated fee matches the actual gas consumed) in the docs to ensure that the same values and approach are used everywhere (but this is not ideal).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
📦 ⛰️ gno.land Issues or PRs gno.land package related
Projects
Status: Triage
Development

No branches or pull requests

2 participants