1
0
mirror of https://github.com/kremalicious/metamask-extension.git synced 2024-12-23 09:52:26 +01:00

Fix BigNumber issues (#9860)

* Document where we need BigNumber-related changes

* Fix 1 unit test

* Debug progress

* Add required values for each upstream usage of getBigNumber

* Switch to base 10

* Address feedback
This commit is contained in:
David Walsh 2020-11-13 00:08:18 -06:00 committed by GitHub
parent ed27c359c6
commit 67303b7865
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 56 additions and 9 deletions

View File

@ -80,6 +80,8 @@ export default class TokenInput extends PureComponent {
const multiplier = Math.pow(10, Number(decimals || 0))
const hexValue = multiplyCurrencies(decimalValue || 0, multiplier, {
multiplicandBase: 10,
multiplierBase: 10,
toNumericBase: 'hex',
})

View File

@ -39,19 +39,23 @@ export function getHexGasTotal({ gasLimit, gasPrice }) {
}
export function addEth(...args) {
return args.reduce((acc, base) => {
return addCurrencies(acc, base, {
return args.reduce((acc, ethAmount) => {
return addCurrencies(acc, ethAmount, {
toNumericBase: 'dec',
numberOfDecimals: 6,
aBase: 10,
bBase: 10,
})
})
}
export function addFiat(...args) {
return args.reduce((acc, base) => {
return addCurrencies(acc, base, {
return args.reduce((acc, fiatAmount) => {
return addCurrencies(acc, fiatAmount, {
toNumericBase: 'dec',
numberOfDecimals: 2,
aBase: 10,
bBase: 10,
})
})
}

View File

@ -54,6 +54,11 @@ const baseChange = {
BN: (n) => new BN(n.toString(16)),
}
// Utility function for checking base types
const isValidBase = (base) => {
return Number.isInteger(base) && base > 1
}
/**
* Defines the base type of numeric value
* @typedef {('hex' | 'dec' | 'BN')} NumericBase
@ -162,6 +167,10 @@ const conversionUtil = (
})
const getBigNumber = (value, base) => {
if (!isValidBase(base)) {
throw new Error('Must specificy valid base')
}
// We don't include 'number' here, because BigNumber will throw if passed
// a number primitive it considers unsafe.
if (typeof value === 'string' || value instanceof BigNumber) {
@ -173,6 +182,11 @@ const getBigNumber = (value, base) => {
const addCurrencies = (a, b, options = {}) => {
const { aBase, bBase, ...conversionOptions } = options
if (!isValidBase(aBase) || !isValidBase(bBase)) {
throw new Error('Must specify valid aBase and bBase')
}
const value = getBigNumber(a, aBase).add(getBigNumber(b, bBase))
return converter({
@ -183,6 +197,11 @@ const addCurrencies = (a, b, options = {}) => {
const subtractCurrencies = (a, b, options = {}) => {
const { aBase, bBase, ...conversionOptions } = options
if (!isValidBase(aBase) || !isValidBase(bBase)) {
throw new Error('Must specify valid aBase and bBase')
}
const value = getBigNumber(a, aBase).minus(getBigNumber(b, bBase))
return converter({
@ -194,6 +213,10 @@ const subtractCurrencies = (a, b, options = {}) => {
const multiplyCurrencies = (a, b, options = {}) => {
const { multiplicandBase, multiplierBase, ...conversionOptions } = options
if (!isValidBase(multiplicandBase) || !isValidBase(multiplierBase)) {
throw new Error('Must specify valid multiplicandBase and multiplierBase')
}
const value = getBigNumber(a, multiplicandBase).times(
getBigNumber(b, multiplierBase),
)

View File

@ -5,17 +5,26 @@ import { addCurrencies, conversionUtil } from './conversion-util'
describe('conversion utils', function () {
describe('addCurrencies()', function () {
it('add whole numbers', function () {
const result = addCurrencies(3, 9)
const result = addCurrencies(3, 9, {
aBase: 10,
bBase: 10,
})
assert.equal(result.toNumber(), 12)
})
it('add decimals', function () {
const result = addCurrencies(1.3, 1.9)
const result = addCurrencies(1.3, 1.9, {
aBase: 10,
bBase: 10,
})
assert.equal(result.toNumber(), 3.2)
})
it('add repeating decimals', function () {
const result = addCurrencies(1 / 3, 1 / 9)
const result = addCurrencies(1 / 3, 1 / 9, {
aBase: 10,
bBase: 10,
})
assert.equal(result.toNumber(), 0.4444444444444444)
})
})

View File

@ -217,6 +217,10 @@ export function getTokenFiatAmount(
const currentTokenToFiatRate = multiplyCurrencies(
contractExchangeRate,
conversionRate,
{
multiplicandBase: 10,
multiplierBase: 10,
},
)
const currentTokenInFiat = conversionUtil(tokenAmount, {
fromNumericBase: 'dec',

View File

@ -152,9 +152,11 @@ export async function isSmartContractAddress(address) {
}
export function sumHexes(...args) {
const total = args.reduce((acc, base) => {
return addCurrencies(acc, base, {
const total = args.reduce((acc, hexAmount) => {
return addCurrencies(acc, hexAmount, {
toNumericBase: 'hex',
aBase: 16,
bBase: 16,
})
})

View File

@ -12,8 +12,11 @@ export function calcMaxAmount({ balance, gasTotal, sendToken, tokenBalance }) {
? multiplyCurrencies(tokenBalance, multiplier, {
toNumericBase: 'hex',
multiplicandBase: 16,
multiplierBase: 10,
})
: subtractCurrencies(addHexPrefix(balance), addHexPrefix(gasTotal), {
toNumericBase: 'hex',
aBase: 16,
bBase: 16,
})
}