-
Notifications
You must be signed in to change notification settings - Fork 176
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
eth: Ensure maxFeePerGas
in all transactions never exceed -masGasPrice
defined by the user
#2111
Conversation
Reaction based on a quick skim: I think this draft PR is going in the right direction. My understanding of the transaction flow after these changes:
|
Thanks for the quick feedback @yondonfu . I understand it exactly the same as you do. So, I'll perform the testing and if everything works fine, I'll update this draft PR. |
maxFeePerGas
in all transactions never exceed -masGasPrice
defined by the user
8b9a5bd
to
1566bef
Compare
1566bef
to
fa6d530
Compare
func (tm *TransactionManager) newAdjustedTx(tx *types.Transaction) *types.Transaction { | ||
baseTx := newDynamicFeeTx(tx) | ||
if tm.gpm.MaxGasPrice() != nil { | ||
baseTx.GasFeeCap = tm.gpm.MaxGasPrice() |
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 forget if we talked about this, but is there a reason for always setting this to the max gas price as opposed to only setting it to the max gas price if the max gas price exceeds the current value?
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.
Both approaches will work. However, IMO the always setting max gas price is slightly better because:
- It's simpler for the user what happens.
- Since the replacement transaction needs to be at least 10% higher, we may end up never reaching exactly
maxGasPrice
.
What do you think?
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.
Sounds reasonable. But, this also means that a replacement tx would never be sent if the user sets a maxGasPrice
because GasFeeCap
is always set to maxGasPrice
meaning that we are never able to increase GasFeeCap
for a replacement tx. And the only scenario where a replacement tx could be sent is if the user does not set a maxGasPrice
. I think this is okay, but just want to make sure we're on the same page about the expected behavior.
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.
You're right. Actually, there is one more scenario for the replacement if the user manually increases maxGasPrice
while the transaction is pending. Then the replacement can also happen.
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.
@yondonfu I addressed your comemnts. PTAL
func (tm *TransactionManager) newAdjustedTx(tx *types.Transaction) *types.Transaction { | ||
baseTx := newDynamicFeeTx(tx) | ||
if tm.gpm.MaxGasPrice() != nil { | ||
baseTx.GasFeeCap = tm.gpm.MaxGasPrice() |
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.
Both approaches will work. However, IMO the always setting max gas price is slightly better because:
- It's simpler for the user what happens.
- Since the replacement transaction needs to be at least 10% higher, we may end up never reaching exactly
maxGasPrice
.
What do you think?
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.
As of this PR, I think the -maxGasPrice
flag is basically equivalent to maxFeePerGas
since its value is always set as GasTipCap
for transactions. The gas price check in backend.SuggestGasPrice()
can be interpreted as:
- The gas price cached by the GasPriceMonitor could be interpreted as "a suggested maxFeePerGas" i.e. the current base fee + a suggested priority fee
- We compare the user provided
maxFeePerGas
(via-maxGasPrice
) against this suggested maxFeePerGas
If this is the case, I think we should make some small updates to docs in a few places:
func (tm *TransactionManager) newAdjustedTx(tx *types.Transaction) *types.Transaction { | ||
baseTx := newDynamicFeeTx(tx) | ||
if tm.gpm.MaxGasPrice() != nil { | ||
baseTx.GasFeeCap = tm.gpm.MaxGasPrice() |
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.
Sounds reasonable. But, this also means that a replacement tx would never be sent if the user sets a maxGasPrice
because GasFeeCap
is always set to maxGasPrice
meaning that we are never able to increase GasFeeCap
for a replacement tx. And the only scenario where a replacement tx could be sent is if the user does not set a maxGasPrice
. I think this is okay, but just want to make sure we're on the same page about the expected behavior.
That is correct.
That is not correct. "suggested gas price" from GasPriceMonitor is not interpreted as You made me think we should make some cleanup, but I believe it should be a separate PR, not to mix to many things here.
|
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.
@yondonfu Added my comments. PTAL
That method is actually called in backend.SuggestGasTipCap() right now. And
Yeah I was a bit off there. So, the I was just thinking about how to describe what "gas price" means. I think the way to describe this is:
How does that sound to you?
Okay yeah so if |
This is correct with one comment. The function
Yes, I think it's right.
I'm not sure what's the meaning of |
@yondonfu I updated the doc again after our conversation. PTAL. |
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!
What does this pull request do? Explain your changes. (required)
Limit the maxFeePerGas in the eth transaction to the
-maxGasPrice
value defined by the user. Before it was possible that the user paid more than they specified as-maxGasPrice
.Additionally, I removed the
calcGasPrice()
logic fromtransactionManager.go
, because I believe it was incorrect. It assumed thatmaxFeePerGas
will be calculated in the go-ethereum code, but I think we override it in our code here.Specific updates (required)
GasFeeCap
before sending the transactioncalcGasPrice
function inreplace()
How did you test each of these updates (required)
I did test the change both locally and using Rinkeby.
Local testing
maxFeePerGas
:1000000014
(2 * base fee + priority fee
)max gas price
(via livepeer CLI) to1000000013
maxFeePerGas
is set to1000000013
max gas price
to a value which is too low, e.g.5
Rinkeby testing
rinkeby
https://rinkeby.etherscan.io/tx/0x382e9a5b7635862fd8a5ac64ddf7e1b1d6111c4b67cb1318c13d7fede3fa31f0
1000000055
and run the transaction againhttps://rinkeby.etherscan.io/tx/0xc6cfc72bb7aef2e4f026332ebcf9eec00ba10b4a0a94290d7c59a3bc0d1f8e9f
Does this pull request close any open issues?
fix #2084
Checklist:
make
runs successfully./test.sh
pass