-
Notifications
You must be signed in to change notification settings - Fork 106
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
server/eth: Match fee rate = MaxFeeRate #1447
Conversation
ed158f8
to
261d51d
Compare
e8a29cf
to
791bee3
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Working well.
- server/asset: Add `SupportsDynamicTxFee` and `ValidateFeeRate` functions - server/dex: Add `SwapFeeRate` function to `FeeFetcher`. This will return the max fee rate for assets that support dynamic transaction fees, but the regular tx fee otherwise - server/market: Use `SwapFeeRate` instead of the regular `FeeRate` - server/swap: Use `ValidateFeeRate` function instead of just comparing the fee rates. This is to allow eth to check the prority fee in addition to the `MaxFeeCap`.
791bee3
to
7b88fb5
Compare
7b88fb5
to
8e353d7
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM. Keeping open to see if @buck54321 is good with SupportsDynamicTxFee + ValidateFeeRate
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Concept ACK. Untested and one suggestion, but feel free to merge when you're comfy, @chappjc.
server/asset/eth/eth.go
Outdated
return false | ||
} | ||
|
||
if sc.dynamicTx && sc.gasTipCap < dexeth.MinGasTipCap { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should probably just enforce dynamicTx = true for all of our transactions.
server/asset/btc/btc.go
Outdated
// SupportsDynamicTxFee returns true if the tx fee for this asset adjusts based | ||
// on market conditions | ||
func (*Backend) SupportsDynamicTxFee() bool { | ||
return false | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wouldn't need to implement this here and in dcr if you made SupportsDynamicTxFee
part of an optional interface like we're doing with the client.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually, I'm now thinking this might not work like I expected, since it's just a boolean return value. So we'd verify that the interface is a DynamicFeeSupporter or whatever, and then still check the boolean? What we really need is something akin to WalletInfo, but on the server side. I'm okay with this as is too
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, it works as is. @martonp can try some stuff out I guess, but I can see the optional method being SwapFeeRate
, which would make feeFetcher
unaware of the whole dynamic<->max_fee relationship. Maybe we like that dynamic/max concept front and center?
Specifically, changing
// SwapFeeRate returns the tx fee that needs to be used to initiate a swap.
// This fee will be the max fee rate if the asset supports dynamic tx fees,
// and otherwise it will be the current market fee rate.
func (f *feeFetcher) SwapFeeRate(ctx context.Context) uint64 {
if f.Backend.SupportsDynamicTxFee() {
return f.MaxFeeRate()
}
return f.FeeRate(ctx)
}
into
// SwapFeeRate returns the tx fee that needs to be used to initiate a swap.
// This will use the Backend's SwapFeeRate method if it exists, otherwise
// it will request the fee rate based on current network conditions.
func (f *feeFetcher) SwapFeeRate(ctx context.Context) uint64 {
if fr, ok := f.Backend.(asset.SwapFeeRater); ok {
return fr.SwapFeeRate()
}
return f.FeeRate(ctx)
}
The question is do we hide the whole dynamic-must-use-max concept in the Backend's methods or do we apply that notion at the higher levels like done currently in this PR?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This wouldn't work because the backend doesn't have access to the MaxFeeRate
. It's stored in the dex.Asset
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ahh, that's right. Max fee rate is a market/swapper concept, so must be done higher up. ✔️
I like both of your suggestions, enforce dynamic tx and consider an interface assertion for server's asset Backends |
We don't really need to check for dynamic vs legacy, in the geth |
167081a
to
71ce046
Compare
@martonp I noticed that too: func (tx *LegacyTx) gasPrice() *big.Int { return tx.GasPrice }
func (tx *LegacyTx) gasTipCap() *big.Int { return tx.GasPrice }
func (tx *LegacyTx) gasFeeCap() *big.Int { return tx.GasPrice } vs. func (tx *DynamicFeeTx) gasFeeCap() *big.Int { return tx.GasFeeCap }
func (tx *DynamicFeeTx) gasTipCap() *big.Int { return tx.GasTipCap }
func (tx *DynamicFeeTx) gasPrice() *big.Int { return tx.GasFeeCap } accessed via // GasPrice returns the gas price of the transaction.
func (tx *Transaction) GasPrice() *big.Int { return new(big.Int).Set(tx.inner.gasPrice()) }
// GasTipCap returns the gasTipCap per gas of the transaction.
func (tx *Transaction) GasTipCap() *big.Int { return new(big.Int).Set(tx.inner.gasTipCap()) }
// GasFeeCap returns the fee cap per gas of the transaction.
func (tx *Transaction) GasFeeCap() *big.Int { return new(big.Int).Set(tx.inner.gasFeeCap()) } But your point is that if it's a legacy txn with a So you are proposing setting Finally, given the above code snippets, was our way of detecting legacy/dynamic tx type incorrect before? Should we have been using |
Yes, I think the client should definitely use a dynamic transaction, but I don't see a reason to block legacy ones.
Yeah, what we had was pointless lol. |
gasTipCap := tx.GasTipCap() | ||
if gasTipCap == nil || gasTipCap.Cmp(zero) <= 0 { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
With a legacy transaction, which returns the same gas price for both GasFeeCap
and GasTipCap
, I think that the swapCoin.gasTipCap
check in (*Backend).ValidateFeeRate
is wrong or at least misleading.
Say we are debugging and we inspect a swapCoin
, we'd see a gasTipCap == gasFeeCap
(a huge gasTipCap
).
I guess we can solve this with documentation spelling out the logic of why a legacy txn can be treated as a dynamic tx with a massive tip, but I do think we should spell that out in both methods (baseCoin
construction and ValidateFeeRate
)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I added some docs.
1600c33
to
0f83b18
Compare
Info
andValidateFeeRate
functionsSwapFeeRate
function toFeeFetcher
. This will return the max fee rate for assets that support dynamic transaction fees, but the regular tx fee otherwiseSwapFeeRate
instead of the regularFeeRate
ValidateFeeRate
function instead of just comparing the fee rates. This is to allow ETH to check the prority fee in addition to theMaxFeeCap
Closes #1372.