-
Notifications
You must be signed in to change notification settings - Fork 5k
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
Create custom addHexPrefix function #9306
Create custom addHexPrefix function #9306
Conversation
2e716ed
to
5732479
Compare
CLA Signature Action: All authors have signed the CLA. You may need to manually re-run the blocking PR check if it doesn't pass in a few minutes. |
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.
Does it make sens to allow negative numbers anywhere we're using addHexPrefix
? Addresses can't be negative, and neither can the gas price, gas limit, private key, balance, nonce, etc. Or at least not that I know of... maybe there's some type of network out there that supports negative gas price/limit or balance 🤔
If there are no valid cases for having a negative number, maybe this is better addressed with additional validation.
ui/app/hooks/useCancelTransaction.js
Outdated
@@ -17,7 +17,7 @@ import { getConversionRate, getSelectedAccount } from '../selectors' | |||
*/ | |||
export function useCancelTransaction (transactionGroup) { | |||
const { primaryTransaction, initialTransaction } = transactionGroup | |||
const gasPrice = primaryTransaction.txParams?.gasPrice | |||
const gasPrice = parseInt(primaryTransaction.txParams?.gasPrice, 16) < 0 ? '0x0' : primaryTransaction.txParams?.gasPrice |
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.
Is this necessary for cancellation transactions? These should only be possible by using our UI, and I didn't think we allowed a negative gas price there 🤔
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 would have to check that, but I'm pretty sure I added this change to allow users to "repair" their extension after getting error. I had to reinstall MM to make it work again, even with other updates, but with this change, when opening MM gas price of pending transaction was changed to 0 (instead of negative number) and it was fixing the problem. Does it make sense?
It was reported in #9262. Even if in theory there shouldn't be such situation, there is an option in our UI to set gas price < 0. Additional validation sounds good, but there could be some other ways to make one of the processed numbers negative and as result crashing whole app. The only way to make it work again is to reinstall extension. |
The reproduction example in #9262 shows the negative gas price being set by a dapp, not via our UI. We already reject incoming messages outright in some cases where they fail validation, so this seems like a case where this validation should be expanded |
5732479
to
061a71d
Compare
9de17f7
to
2ba32e8
Compare
ui/app/hooks/useCancelTransaction.js
Outdated
const gasPrice = | ||
primaryTransaction.txParams?.gasPrice?.startsWith('-') | ||
? '0x0' | ||
: primaryTransaction.txParams?.gasPrice |
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 changed this. Compare: https://github.com/MetaMask/metamask-extension/compare/2ba32e896f545ed432488d3d04a91ee42eacd9c3...89a6720?expand=1
parseInt
is not safe to use with Ethereum quantities.
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 is only labeled as outdated due to linting.
/** | ||
* Prefixes a hex string with '0x' or '-0x' and returns it. Idempotent. | ||
* | ||
* @param {string} str - The string to prefix. | ||
* @returns {string} The prefixed string. | ||
*/ | ||
const addHexPrefix = (str) => { | ||
if (typeof str !== 'string' || str.match(/^-?0x/u)) { | ||
return str | ||
} | ||
|
||
if (str.match(/^-?0X/u)) { | ||
return str.replace('0X', '0x') | ||
} | ||
|
||
if (str.startsWith('-')) { | ||
return str.replace('-', '-0x') | ||
} | ||
|
||
return `0x${str}` | ||
} |
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 changed this implementation. Comparison: https://github.com/MetaMask/metamask-extension/compare/2ba32e896f545ed432488d3d04a91ee42eacd9c3...89a6720?expand=1
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 think this is good to go, but since I made some edits I'll ask for a second review.
@@ -173,13 +162,47 @@ function isPrefixedFormattedHexString(value) { | |||
return /^0x[1-9a-f]+[0-9a-f]*$/iu.test(value) | |||
} | |||
|
|||
/** | |||
* Prefixes a hex string with '0x' or '-0x' and returns it. Idempotent. |
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.
Very nice use of the word "Idempotent" 🙌
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 code looks good. Approving.
But I think the original issue that motivated this also requires us to make a change so that gas price validation happens on gas prices suggested by the dapp. At least on ethereum mainnet, we should make sure no transaction can be submitted with a gas price we know will fail. We do prevent this when the user is manually editing gas, but we don't on the submit button on the confirm screen. This should be handled in another PR.
I don't think this was the case here. It's not that we knew the price would fail - it's that it was an invalid price, and it crashed our UI. The validation we need here is in our dapp request handling, and it should have been rejected outright without showing the user anything, just as we do with other malformed requests. I think we could avoid all of this work by some combination of request validation and migrating the state of pending transaction confirmations to remove negative gas prices. I'm not against this being merged in the meantime, but handling invalid types mid-operation is not a great approach in general - we should verify our assumptions about this data at the boundaries rather than within the app. This is only one place where a negative gas price caused things to blow up after all - there may be others that remain unaddressed. |
Well if we did ensure that 'no transaction can be submitted with a gas price we know will fail', this particular case would have been avoided. This doesn't invalidate anything else @Gudahtt said in the above comment, but this issue also points to the need to check whether gas prices that come from dapps are too low. |
Actually, my comment that "Well if we did ensure that 'no transaction can be submitted with a gas price we know will fail', this particular case would have been avoided" was wrong. This issue happens on render of confirmation screen, not after submit which I previously thought. However, I think that "this issue also points to the need to check whether gas prices that come from dapps are too low" holds true. I didn't realize, or had forgotten, that gas price set via rpc methods would be the gas price used in our confirmation screen. I now realize that this comment is tangential to this PR, but we should also add front end validation and error messaging for gas prices that are valid prices, but guaranteed to fail. |
Creates custom addHexPrefix function. The one provided by
ethereumjs-util
does not handle incorrect eth address hex formats such us starting with-
or0X
.Fixes #9262