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

client/eth: Respect user's max fee. #1485

Closed
wants to merge 1 commit into from

Conversation

JoeGruffins
Copy link
Member

@JoeGruffins JoeGruffins commented Feb 24, 2022

Check initiation and redeem fee suggestions are not zero or too high. If
so attempt to get our own gas limit value. If that also fails or is above
our max limit, do not send the transaction.

closes #1336

@JoeGruffins JoeGruffins force-pushed the respectusermax branch 2 times, most recently from e60d00b to d3313f1 Compare February 24, 2022 06:52
Check initiation and redeem fee suggestions are not zero or too high. If
so attempt to get our own gas rate limit value. If that also fails or is
above our max limit, do not send the transaction.
@JoeGruffins
Copy link
Member Author

JoeGruffins commented Feb 24, 2022

Actually the server is pretty strict about this, so I guess we can't use our estimation for initiations if the server's is too high. It has to be the suggestion.

Copy link
Member

@buck54321 buck54321 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We realistically never have a fee suggestion from the server, since the wallet implements FeeRater.

Comment on lines -721 to +736
tx, err := eth.node.initiate(eth.ctx, swaps.Contracts, swaps.FeeRate, swaps.AssetVersion)
tx, err := eth.node.initiate(eth.ctx, swaps.Contracts, gasFeeLimit, swaps.AssetVersion)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can't do this part. This is validated by the server.

Copy link
Member

@chappjc chappjc Feb 24, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

More than that, the "fee limit" was only ever intended to block order funding, nothing else. In fact, this is the setting that I fought to keep out of the wallet since Core's trade methods (prepareTrackedTrade) could have just as easily applied this user set limit in the one place it was intended. #874 (comment)
I suppose the limit can expand in scope somewhat to limit the wallet's own local estimate though.

if lowerRate > 0 {
eth.log.Warnf("Eth gas rate limit too low! Set above %d gwei to complete current transaction!",
lowerRate)
return 0, fmt.Errorf("the needed gas fee rate limit (%d gwei) is higher than set max (%d gwei)", lowerRate, eth.gasFeeLimit)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No way we can just block inits, redeems, or refunds.

@chappjc
Copy link
Member

chappjc commented Feb 24, 2022

nACK, Unless really I'm misunderstanding something.

  • We cannot just not do the swap, redeem, or refund txn because the fee suggestion is "too high". Placing and funding the order commits us to executing the swap tnx, and we'd be insane not to refund or redeem on account of fee rates.
  • The fee rate limit setting was initially only meant for order funding. That would be in (*ExchangeWallet).FundOrder although when the setting was initially introduced, I fought hard to keep it out of the wallet entirely and instead applied at the level of Core, for exactly these reasons - scope of the setting in the wallet. EDIT: Possibly the limit can be applied to cap our own local estimates though.
  • Overpaying gas in eth with dynamic txns is not an issue at all afaik.

But I do approve of the formula for computing a local fee rate (localFeeRate := dexeth.WeiToGwei(tipCap.Add(baseFee.Mul(baseFee, big.NewInt(2)), tipCap))) and it seems that can be part of a FeeRate method just like the one that exists server-side. We've settled on this formula in several discussions I think: #1447 (comment), #1372 (comment), https://github.com/ethereum/go-ethereum/blob/356bbe343a30789e77bb38f25983c8f2f2bfbb47/accounts/abi/bind/base.go#L250-L255
I don't object to the configured fee rate limit being used to cap the result of that formula, although it is a deviation from original purpose of that setting.

@chappjc
Copy link
Member

chappjc commented Feb 24, 2022

We realistically never have a fee suggestion from the server, since the wallet implements FeeRater.

Looks like only server has FeeRate implemented, but I do think it's reasonable to have client be a FeeRater using the tip + 2*base formula also.

@JoeGruffins
Copy link
Member Author

JoeGruffins commented Feb 25, 2022

We cannot just not do the swap, redeem, or refund txn because the fee suggestion is "too high". Placing and funding the order commits us to executing the swap tnx, and we'd be insane not to refund or redeem on account of fee rates.

While I agree, the server can currently insert any value here and unless the total gas goes over 1 eth (#1304) the wallet will not reject it. On the other side, the server could send something too low and screw the user, which this pr wouldn't solve. There is currently no resolution for txn with fees that are too low with eth. Low fee tx are a bigger problem with eth. IMO client can not blindly trust the server.

Also, I guess I misundersood the meaning of the gas limit. It only applies to initiations, and not to anything else.

Can't we just not do the swap if fee is too high/low though? I mean initiation. I agree it could be catastrophic to not redeem/refund. I would agree that after you initiate, you kinda agreed to pay whatever fees you need to to complete the swap.

@chappjc
Copy link
Member

chappjc commented Feb 25, 2022

can currently insert any value here and ... wallet will not reject it

It does not need to reject it because this swaps.FeeRate is checked at match time. When the match is made, that is when the client checks the prescribed swap fee rate to make sure it's not higher than the limit that was recorded at order placement time when FundOrder enforces the user's fee rate limit. See parseMatches and it's check for swapRate > tracker.metaData.MaxFeeRate:

dcrdex/client/core/core.go

Lines 577 to 579 in 26b0c82

if !isCancel && swapRate > tracker.metaData.MaxFeeRate {
errs = append(errs, fmt.Sprintf("rejecting match %s for order %s because assigned rate (%d) is > MaxFeeRate (%d)",
msgMatch.MatchID, msgMatch.OrderID, swapRate, tracker.metaData.MaxFeeRate))

and the db type where the expected max fee rate is recorded during order placement

dcrdex/client/db/types.go

Lines 259 to 261 in 26b0c82

// MaxFeeRate is the dex.Asset.MaxFeeRate at the time of ordering. The rates
// assigned to matches will be validated against this value.
MaxFeeRate uint64

and FundOrder actually rejecting order funding if the server's max fee rate (above) is too high

dcrdex/client/asset/dcr/dcr.go

Lines 1061 to 1070 in 26b0c82

if ord.FeeSuggestion > dcr.feeRateLimit {
return nil, nil, fmt.Errorf("suggested fee > configured limit. %d > %d", ord.FeeSuggestion, dcr.feeRateLimit)
}
// Check wallet's fee rate limit against server's max fee rate
if dcr.feeRateLimit < ord.DEXConfig.MaxFeeRate {
return nil, nil, fmt.Errorf(
"%v: server's max fee rate %v higher than configured fee rate limit %v",
ord.DEXConfig.Symbol,
ord.DEXConfig.MaxFeeRate,
dcr.feeRateLimit)

From PRs #874 and #898

@chappjc
Copy link
Member

chappjc commented Feb 25, 2022

As for too low, sure we can use any fee rate minimum as long as its not over the MaxFeeRate because that would potentially eat into the reserves required for the swap(s) for the order.

On the high end limit though, if the wallet did block a swap/init because the fee was higher than it's configured fee limit, that could just be because the fee limit was changed after the order was placed (funded). I wouldn't object to a second very high limit as a sanity check, but it would have to be super high, as in beyond any setting the user might switch their gasFeeLimit setting to.

@chappjc
Copy link
Member

chappjc commented Feb 25, 2022

As for too low, sure we can use any fee rate minimum as long as its not over the MaxFeeRate because that would potentially eat into the reserves required for the swap(s) for the order.

In fact, I would 100% support changes to all asset impls to do this. Particularly BTC where as taker you are using a fee rate prescribed at match time that was potentially a long time ago if the maker's swap took a while to confirm. It should be fine to use any rate x that is on swapRate <= x <= db.OrderMetaData.MaxFeeRate. For a FeeRater, the asset could use it's own rate as long as it is in that range. For a non-FeeRater it could do a c.feeSuggestionAny or a dc.fetchFeeRate.

@JoeGruffins
Copy link
Member Author

I think I see it now. The ord.DEXConfig.MaxFeeRate is saved to the order metadata and used for all the matches, as a max. So it's not per match I guess? Ignoring changes in the fee rate from time of placing order?

@chappjc
Copy link
Member

chappjc commented Feb 25, 2022

I think I see it now. The ord.DEXConfig.MaxFeeRate is saved to the order metadata and used for all the matches, as a max. So it's not per match I guess? Ignoring changes in the fee rate from time of placing order?

Right, you have a certain configured fee rate limit at order time. If the server's MaxFeeRate is less than that limit, it is recorded in the order's metadata. That max is enforced for all matches made for that order. When each match is made, the prescribed rate is checked against that recorded per-order limit.

@JoeGruffins
Copy link
Member Author

Ok, then we were respecting the max in the manner intended.

@chappjc
Copy link
Member

chappjc commented Feb 25, 2022

Yes although in this contorted way because the user's fee limit is configurable and this need to be recorded with the order metadata.

I like the idea of bumping the rate if it looks too low though

@JoeGruffins
Copy link
Member Author

But the redeem is not checked at all, and we are using the suggestion.

@JoeGruffins
Copy link
Member Author

Oh, I see, if it were a FeeRater, it would be using the local fee?

@JoeGruffins
Copy link
Member Author

I think @martonp said on matrix he would add that.

@chappjc
Copy link
Member

chappjc commented Feb 25, 2022

Ah, yeah, @buck54321 's point there is that the eth client should be a FeeRater, not needing the suggestion at all. @martonp said he was going to make that change in his PR. Would be good to coordinate with him on this so we're on the same page.

@JoeGruffins
Copy link
Member Author

I guess I will close this pr and the linked issue. Will make a new issue for suggested fees that are too low.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

client/eth: Respect user's max fee rate.
3 participants