From c96c681758a9bb62b4444ce21747c3781e9dc742 Mon Sep 17 00:00:00 2001 From: Fabio Berger Date: Thu, 9 Nov 2017 10:09:20 -0500 Subject: Add assert.isValidBaseUnitAmount that checks for decimals in amounts that should be in baseUnits. This can sometimes alert developers whenever they accidentally pass in unitAmounts. --- src/contract_wrappers/ether_token_wrapper.ts | 2 ++ src/contract_wrappers/exchange_wrapper.ts | 10 ++++++++++ src/contract_wrappers/token_wrapper.ts | 4 ++++ src/utils/assert.ts | 6 ++++++ 4 files changed, 22 insertions(+) (limited to 'src') diff --git a/src/contract_wrappers/ether_token_wrapper.ts b/src/contract_wrappers/ether_token_wrapper.ts index 7c94e314a..6db07228e 100644 --- a/src/contract_wrappers/ether_token_wrapper.ts +++ b/src/contract_wrappers/ether_token_wrapper.ts @@ -30,6 +30,7 @@ export class EtherTokenWrapper extends ContractWrapper { */ public async depositAsync(amountInWei: BigNumber, depositor: string): Promise { assert.isBigNumber('amountInWei', amountInWei); + assert.isValidBaseUnitAmount('amountInWei', amountInWei); await assert.isSenderAddressAsync('depositor', depositor, this._web3Wrapper); const ethBalanceInWei = await this._web3Wrapper.getBalanceInWeiAsync(depositor); @@ -51,6 +52,7 @@ export class EtherTokenWrapper extends ContractWrapper { */ public async withdrawAsync(amountInWei: BigNumber, withdrawer: string): Promise { assert.isBigNumber('amountInWei', amountInWei); + assert.isValidBaseUnitAmount('amountInWei', amountInWei); await assert.isSenderAddressAsync('withdrawer', withdrawer, this._web3Wrapper); const wethContractAddress = await this.getContractAddressAsync(); diff --git a/src/contract_wrappers/exchange_wrapper.ts b/src/contract_wrappers/exchange_wrapper.ts index b027d46df..ddb1d6bd4 100644 --- a/src/contract_wrappers/exchange_wrapper.ts +++ b/src/contract_wrappers/exchange_wrapper.ts @@ -167,6 +167,7 @@ export class ExchangeWrapper extends ContractWrapper { orderTransactionOpts?: OrderTransactionOpts): Promise { assert.doesConformToSchema('signedOrder', signedOrder, schemas.signedOrderSchema); assert.isBigNumber('fillTakerTokenAmount', fillTakerTokenAmount); + assert.isValidBaseUnitAmount('fillTakerTokenAmount', fillTakerTokenAmount); assert.isBoolean('shouldThrowOnInsufficientBalanceOrAllowance', shouldThrowOnInsufficientBalanceOrAllowance); await assert.isSenderAddressAsync('takerAddress', takerAddress, this._web3Wrapper); @@ -240,6 +241,7 @@ export class ExchangeWrapper extends ContractWrapper { assert.hasAtMostOneUniqueValue(exchangeContractAddresses, ExchangeContractErrs.BatchOrdersMustHaveSameExchangeAddress); assert.isBigNumber('fillTakerTokenAmount', fillTakerTokenAmount); + assert.isValidBaseUnitAmount('fillTakerTokenAmount', fillTakerTokenAmount); assert.isBoolean('shouldThrowOnInsufficientBalanceOrAllowance', shouldThrowOnInsufficientBalanceOrAllowance); await assert.isSenderAddressAsync('takerAddress', takerAddress, this._web3Wrapper); @@ -409,6 +411,7 @@ export class ExchangeWrapper extends ContractWrapper { orderTransactionOpts?: OrderTransactionOpts): Promise { assert.doesConformToSchema('signedOrder', signedOrder, schemas.signedOrderSchema); assert.isBigNumber('fillTakerTokenAmount', fillTakerTokenAmount); + assert.isValidBaseUnitAmount('fillTakerTokenAmount', fillTakerTokenAmount); await assert.isSenderAddressAsync('takerAddress', takerAddress, this._web3Wrapper); const exchangeInstance = await this._getExchangeContractAsync(); @@ -544,6 +547,7 @@ export class ExchangeWrapper extends ContractWrapper { orderTransactionOpts?: OrderTransactionOpts): Promise { assert.doesConformToSchema('order', order, schemas.orderSchema); assert.isBigNumber('takerTokenCancelAmount', cancelTakerTokenAmount); + assert.isValidBaseUnitAmount('takerTokenCancelAmount', cancelTakerTokenAmount); await assert.isSenderAddressAsync('order.maker', order.maker, this._web3Wrapper); const exchangeInstance = await this._getExchangeContractAsync(); @@ -739,6 +743,7 @@ export class ExchangeWrapper extends ContractWrapper { takerAddress: string): Promise { assert.doesConformToSchema('signedOrder', signedOrder, schemas.signedOrderSchema); assert.isBigNumber('fillTakerTokenAmount', fillTakerTokenAmount); + assert.isValidBaseUnitAmount('fillTakerTokenAmount', fillTakerTokenAmount); await assert.isSenderAddressAsync('takerAddress', takerAddress, this._web3Wrapper); const zrxTokenAddress = await this.getZRXTokenAddressAsync(); const exchangeTradeEmulator = new ExchangeTransferSimulator(this._tokenWrapper); @@ -755,6 +760,7 @@ export class ExchangeWrapper extends ContractWrapper { order: Order, cancelTakerTokenAmount: BigNumber): Promise { assert.doesConformToSchema('order', order, schemas.orderSchema); assert.isBigNumber('cancelTakerTokenAmount', cancelTakerTokenAmount); + assert.isValidBaseUnitAmount('cancelTakerTokenAmount', cancelTakerTokenAmount); const orderHash = utils.getOrderHashHex(order); const unavailableTakerTokenAmount = await this.getUnavailableTakerAmountAsync(orderHash); await this._orderValidationUtils.validateCancelOrderThrowIfInvalidAsync( @@ -773,6 +779,7 @@ export class ExchangeWrapper extends ContractWrapper { takerAddress: string): Promise { assert.doesConformToSchema('signedOrder', signedOrder, schemas.signedOrderSchema); assert.isBigNumber('fillTakerTokenAmount', fillTakerTokenAmount); + assert.isValidBaseUnitAmount('fillTakerTokenAmount', fillTakerTokenAmount); await assert.isSenderAddressAsync('takerAddress', takerAddress, this._web3Wrapper); const zrxTokenAddress = await this.getZRXTokenAddressAsync(); const exchangeTradeEmulator = new ExchangeTransferSimulator(this._tokenWrapper); @@ -792,8 +799,11 @@ export class ExchangeWrapper extends ContractWrapper { takerTokenAmount: BigNumber, makerTokenAmount: BigNumber): Promise { assert.isBigNumber('fillTakerTokenAmount', fillTakerTokenAmount); + assert.isValidBaseUnitAmount('fillTakerTokenAmount', fillTakerTokenAmount); assert.isBigNumber('takerTokenAmount', takerTokenAmount); + assert.isValidBaseUnitAmount('takerTokenAmount', takerTokenAmount); assert.isBigNumber('makerTokenAmount', makerTokenAmount); + assert.isValidBaseUnitAmount('makerTokenAmount', makerTokenAmount); const exchangeInstance = await this._getExchangeContractAsync(); const isRoundingError = await exchangeInstance.isRoundingError.callAsync( fillTakerTokenAmount, takerTokenAmount, makerTokenAmount, diff --git a/src/contract_wrappers/token_wrapper.ts b/src/contract_wrappers/token_wrapper.ts index 5d6d61cef..c479aa30f 100644 --- a/src/contract_wrappers/token_wrapper.ts +++ b/src/contract_wrappers/token_wrapper.ts @@ -73,6 +73,7 @@ export class TokenWrapper extends ContractWrapper { assert.isETHAddressHex('spenderAddress', spenderAddress); assert.isETHAddressHex('tokenAddress', tokenAddress); assert.isBigNumber('amountInBaseUnits', amountInBaseUnits); + assert.isValidBaseUnitAmount('amountInBaseUnits', amountInBaseUnits); const tokenContract = await this._getTokenContractAsync(tokenAddress); // Hack: for some reason default estimated gas amount causes `base fee exceeds gas limit` exception @@ -153,6 +154,7 @@ export class TokenWrapper extends ContractWrapper { assert.isETHAddressHex('ownerAddress', ownerAddress); assert.isETHAddressHex('tokenAddress', tokenAddress); assert.isBigNumber('amountInBaseUnits', amountInBaseUnits); + assert.isValidBaseUnitAmount('amountInBaseUnits', amountInBaseUnits); const proxyAddress = await this._getTokenTransferProxyAddressAsync(); const txHash = await this.setAllowanceAsync(tokenAddress, ownerAddress, proxyAddress, amountInBaseUnits); @@ -188,6 +190,7 @@ export class TokenWrapper extends ContractWrapper { await assert.isSenderAddressAsync('fromAddress', fromAddress, this._web3Wrapper); assert.isETHAddressHex('toAddress', toAddress); assert.isBigNumber('amountInBaseUnits', amountInBaseUnits); + assert.isValidBaseUnitAmount('amountInBaseUnits', amountInBaseUnits); const tokenContract = await this._getTokenContractAsync(tokenAddress); @@ -222,6 +225,7 @@ export class TokenWrapper extends ContractWrapper { assert.isETHAddressHex('toAddress', toAddress); await assert.isSenderAddressAsync('senderAddress', senderAddress, this._web3Wrapper); assert.isBigNumber('amountInBaseUnits', amountInBaseUnits); + assert.isValidBaseUnitAmount('amountInBaseUnits', amountInBaseUnits); const tokenContract = await this._getTokenContractAsync(tokenAddress); diff --git a/src/utils/assert.ts b/src/utils/assert.ts index 286105345..48aed6ad3 100644 --- a/src/utils/assert.ts +++ b/src/utils/assert.ts @@ -11,6 +11,12 @@ export const assert = { const isBigNumber = _.isObject(value) && (value as any).isBigNumber; this.assert(isBigNumber, this.typeAssertionMessage(variableName, 'BigNumber', value)); }, + isValidBaseUnitAmount(variableName: string, value: BigNumber) { + const hasDecimals = value.decimalPlaces() !== 0; + this.assert( + !hasDecimals, `${variableName} should be in baseUnits (no decimals), found value: ${value.toNumber()}`, + ); + }, isUndefined(value: any, variableName?: string): void { this.assert(_.isUndefined(value), this.typeAssertionMessage(variableName, 'undefined', value)); }, -- cgit v1.2.3