forked from MetaMask/metamask-extension
-
Notifications
You must be signed in to change notification settings - Fork 17
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Allow editing max spend limit (MetaMask#7919)
In the case where the initial spend limit for the `approve` function was set to the maximum amount, editing this value would result in the new limit being silently ignored. The transaction would be submitted with the original max spend limit. This occurred because function to generate the new custom data would look for the expected spend limit in the existing data, then bail if it was not found (and in these cases, it was never found). The reason the value was not found is that it was erroneously being converted to a `Number`. A JavaScript `Number` is not precise enough to represent larger spend limits, so it would give the wrong hex value (after rounding had taken place in the conversion to a floating-point number). The data string is now updated without relying upon the original token value; the new value is inserted after the `spender` argument instead, as the remainder of the `data` string is guaranteed to be the original limit. Additionally, the conversion to a `Number` is now omitted so that the custom spend limit is encoded correctly. Fixes MetaMask#7915
- Loading branch information
Showing
5 changed files
with
46 additions
and
52 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,36 +1,33 @@ | ||
import { decimalToHex } from '../../helpers/utils/conversions.util' | ||
import { calcTokenValue } from '../../helpers/utils/token-util.js' | ||
import { getTokenData } from '../../helpers/utils/transactions.util' | ||
|
||
export function getCustomTxParamsData ( | ||
data, | ||
{ customPermissionAmount, tokenAmount, decimals } | ||
) { | ||
if (customPermissionAmount) { | ||
const tokenValue = decimalToHex(calcTokenValue(tokenAmount, decimals)) | ||
export function getCustomTxParamsData (data, { customPermissionAmount, decimals }) { | ||
const tokenData = getTokenData(data) | ||
|
||
const re = new RegExp('(^.+)' + tokenValue + '$') | ||
const matches = re.exec(data) | ||
|
||
if (!matches || !matches[1]) { | ||
return data | ||
} | ||
let dataWithoutCurrentAmount = matches[1] | ||
const customPermissionValue = decimalToHex( | ||
calcTokenValue(Number(customPermissionAmount), decimals) | ||
) | ||
if (!tokenData) { | ||
throw new Error('Invalid data') | ||
} else if (tokenData.name !== 'approve') { | ||
throw new Error(`Invalid data; should be 'approve' method, but instead is '${tokenData.name}'`) | ||
} | ||
let spender = tokenData.params[0].value | ||
if (spender.startsWith('0x')) { | ||
spender = spender.substring(2) | ||
} | ||
const [signature, tokenValue] = data.split(spender) | ||
|
||
const differenceInLengths = customPermissionValue.length - tokenValue.length | ||
const zeroModifier = dataWithoutCurrentAmount.length - differenceInLengths | ||
if (differenceInLengths > 0) { | ||
dataWithoutCurrentAmount = dataWithoutCurrentAmount.slice(0, zeroModifier) | ||
} else if (differenceInLengths < 0) { | ||
dataWithoutCurrentAmount = dataWithoutCurrentAmount.padEnd( | ||
zeroModifier, | ||
0 | ||
) | ||
} | ||
if (!signature || !tokenValue) { | ||
throw new Error('Invalid data') | ||
} else if (tokenValue.length !== 64) { | ||
throw new Error('Invalid token value; should be exactly 64 hex digits long (u256)') | ||
} | ||
|
||
const customTxParamsData = dataWithoutCurrentAmount + customPermissionValue | ||
return customTxParamsData | ||
let customPermissionValue = decimalToHex(calcTokenValue(customPermissionAmount, decimals)) | ||
if (customPermissionValue.length > 64) { | ||
throw new Error('Custom value is larger than u256') | ||
} | ||
|
||
customPermissionValue = customPermissionValue.padStart(tokenValue.length, '0') | ||
const customTxParamsData = `${signature}${spender}${customPermissionValue}` | ||
return customTxParamsData | ||
} |