diff --git a/contracts/dev-utils/src/artifacts.ts b/contracts/dev-utils/src/artifacts.ts index 022784e6dc..3c2f022c66 100644 --- a/contracts/dev-utils/src/artifacts.ts +++ b/contracts/dev-utils/src/artifacts.ts @@ -10,6 +10,6 @@ import * as LibAssetData from '../generated-artifacts/LibAssetData.json'; import * as LibTransactionDecoder from '../generated-artifacts/LibTransactionDecoder.json'; export const artifacts = { DevUtils: DevUtils as ContractArtifact, - LibTransactionDecoder: LibTransactionDecoder as ContractArtifact, LibAssetData: LibAssetData as ContractArtifact, + LibTransactionDecoder: LibTransactionDecoder as ContractArtifact, }; diff --git a/contracts/exchange-libs/contracts/src/LibMath.sol b/contracts/exchange-libs/contracts/src/LibMath.sol index 5dee473c08..17fa08e3ca 100644 --- a/contracts/exchange-libs/contracts/src/LibMath.sol +++ b/contracts/exchange-libs/contracts/src/LibMath.sol @@ -83,7 +83,7 @@ contract LibMath is _rrevert(DivisionByZeroError()); } - if (_isRoundingErrorFloor( + if (_isRoundingErrorCeil( numerator, denominator, target diff --git a/contracts/exchange/contracts/src/MixinMatchOrders.sol b/contracts/exchange/contracts/src/MixinMatchOrders.sol index e82432a534..c595361a4c 100644 --- a/contracts/exchange/contracts/src/MixinMatchOrders.sol +++ b/contracts/exchange/contracts/src/MixinMatchOrders.sol @@ -17,7 +17,6 @@ pragma experimental ABIEncoderV2; import "@0x/contracts-utils/contracts/src/ReentrancyGuard.sol"; import "@0x/contracts-utils/contracts/src/RichErrors.sol"; import "@0x/contracts-utils/contracts/src/LibBytes.sol"; -import "@0x/contracts-exchange-libs/contracts/src/LibMath.sol"; import "@0x/contracts-exchange-libs/contracts/src/LibOrder.sol"; import "@0x/contracts-exchange-libs/contracts/src/LibFillResults.sol"; import "./interfaces/IAssetProxyDispatcher.sol"; diff --git a/contracts/exchange/src/artifacts.ts b/contracts/exchange/src/artifacts.ts index 762aa10e34..74f311c836 100644 --- a/contracts/exchange/src/artifacts.ts +++ b/contracts/exchange/src/artifacts.ts @@ -46,8 +46,8 @@ export const artifacts = { ReentrantERC20Token: ReentrantERC20Token as ContractArtifact, TestAssetProxyDispatcher: TestAssetProxyDispatcher as ContractArtifact, TestExchangeInternals: TestExchangeInternals as ContractArtifact, + TestLibExchangeRichErrorDecoder: TestLibExchangeRichErrorDecoder as ContractArtifact, TestRevertReceiver: TestRevertReceiver as ContractArtifact, TestSignatureValidator: TestSignatureValidator as ContractArtifact, TestStaticCallReceiver: TestStaticCallReceiver as ContractArtifact, - TestLibExchangeRichErrorDecoder: TestLibExchangeRichErrorDecoder as ContractArtifact, }; diff --git a/contracts/exchange/test/core.ts b/contracts/exchange/test/core.ts index 6730dfd00e..7ae58dc5b8 100644 --- a/contracts/exchange/test/core.ts +++ b/contracts/exchange/test/core.ts @@ -30,7 +30,7 @@ import { web3Wrapper, } from '@0x/contracts-test-utils'; import { BlockchainLifecycle } from '@0x/dev-utils'; -import { assetDataUtils, ExchangeRevertErrors, orderHashUtils } from '@0x/order-utils'; +import { assetDataUtils, ExchangeRevertErrors, LibMathRevertErrors, orderHashUtils } from '@0x/order-utils'; import { RevertReason, SignatureType, SignedOrder } from '@0x/types'; import { BigNumber, providerUtils, StringRevertError } from '@0x/utils'; import { Web3Wrapper } from '@0x/web3-wrapper'; @@ -598,10 +598,15 @@ describe('Exchange core', () => { }); const fillTakerAssetAmount2 = new BigNumber(1); + const expectedError = new LibMathRevertErrors.RoundingError( + fillTakerAssetAmount2, + new BigNumber(3), + new BigNumber(1001), + ); const tx = exchangeWrapper.fillOrderAsync(signedOrder, takerAddress, { takerAssetFillAmount: fillTakerAssetAmount2, }); - return expect(tx).to.revertWith(RevertReason.RoundingError); + return expect(tx).to.revertWith(expectedError); }); }); @@ -817,8 +822,13 @@ describe('Exchange core', () => { }); // Call Exchange const takerAssetFillAmount = signedOrder.takerAssetAmount.div(2); + const expectedError = new LibMathRevertErrors.RoundingError( + takerAssetFillAmount, + signedOrder.takerAssetAmount, + signedOrder.makerAssetAmount, + ); const tx = exchangeWrapper.fillOrderAsync(signedOrder, takerAddress, { takerAssetFillAmount }); - return expect(tx).to.revertWith(RevertReason.RoundingError); + return expect(tx).to.revertWith(expectedError); }); }); diff --git a/contracts/exchange/test/internal.ts b/contracts/exchange/test/internal.ts index f5ff0605a3..5c1b8ae266 100644 --- a/contracts/exchange/test/internal.ts +++ b/contracts/exchange/test/internal.ts @@ -10,6 +10,7 @@ import { web3Wrapper, } from '@0x/contracts-test-utils'; import { BlockchainLifecycle } from '@0x/dev-utils'; +import { LibMathRevertErrors } from '@0x/order-utils'; import { Order, RevertReason, SignedOrder } from '@0x/types'; import { BigNumber, providerUtils, SafeMathRevertErrors } from '@0x/utils'; import * as chai from 'chai'; @@ -50,12 +51,12 @@ const emptySignedOrder: SignedOrder = { signature: '', }; -const safeMathErrorForCall = () => new SafeMathRevertErrors.SafeMathError(); +const safeMathErrorForCall = new SafeMathRevertErrors.SafeMathError(); describe('Exchange core internal functions', () => { let chainId: number; let testExchange: TestExchangeInternalsContract; - let safeMathErrorForSendTransaction: () => Error | undefined; + let safeMathErrorForSendTransaction: Error | undefined; let divisionByZeroErrorForCall: Error | undefined; let roundingErrorForCall: Error | undefined; @@ -76,9 +77,11 @@ describe('Exchange core internal functions', () => { txDefaults, new BigNumber(chainId), ); - safeMathErrorForSendTransaction = safeMathErrorForCall; divisionByZeroErrorForCall = new Error(RevertReason.DivisionByZero); roundingErrorForCall = new Error(RevertReason.RoundingError); + safeMathErrorForSendTransaction = safeMathErrorForCall; + divisionByZeroErrorForCall = new LibMathRevertErrors.DivisionByZeroError(); + roundingErrorForCall = new LibMathRevertErrors.RoundingError(); }); // Note(albrow): Don't forget to add beforeEach and afterEach calls to reset // the blockchain state for any tests which modify it! @@ -102,10 +105,10 @@ describe('Exchange core internal functions', () => { const remainderTimes1000 = remainder.multipliedBy('1000'); const isError = remainderTimes1000.gte(product); if (product.isGreaterThan(MAX_UINT256)) { - throw safeMathErrorForCall(); + throw safeMathErrorForCall; } if (remainderTimes1000.isGreaterThan(MAX_UINT256)) { - throw safeMathErrorForCall(); + throw safeMathErrorForCall; } return isError; } @@ -130,10 +133,10 @@ describe('Exchange core internal functions', () => { const errorTimes1000 = error.multipliedBy('1000'); const isError = errorTimes1000.gte(product); if (product.isGreaterThan(MAX_UINT256)) { - throw safeMathErrorForCall(); + throw safeMathErrorForCall; } if (errorTimes1000.isGreaterThan(MAX_UINT256)) { - throw safeMathErrorForCall(); + throw safeMathErrorForCall; } return isError; } @@ -148,11 +151,11 @@ describe('Exchange core internal functions', () => { } const isRoundingError = await referenceIsRoundingErrorFloorAsync(numerator, denominator, target); if (isRoundingError) { - throw roundingErrorForCall; + throw roundingErrorForCall(); } const product = numerator.multipliedBy(target); if (product.isGreaterThan(MAX_UINT256)) { - throw safeMathErrorForCall(); + throw safeMathErrorForCall; } return product.dividedToIntegerBy(denominator); } @@ -186,7 +189,7 @@ describe('Exchange core internal functions', () => { (totalVal: BigNumber, singleVal: BigNumber) => { const newTotal = totalVal.plus(singleVal); if (newTotal.isGreaterThan(MAX_UINT256)) { - throw safeMathErrorForCall(); + throw safeMathErrorForCall; } return newTotal; }, @@ -280,7 +283,7 @@ describe('Exchange core internal functions', () => { } const product = numerator.multipliedBy(target); if (product.isGreaterThan(MAX_UINT256)) { - throw safeMathErrorForCall(); + throw safeMathErrorForCall; } return product.dividedToIntegerBy(denominator); } @@ -311,7 +314,7 @@ describe('Exchange core internal functions', () => { const product = numerator.multipliedBy(target); const offset = product.plus(denominator.minus(1)); if (offset.isGreaterThan(MAX_UINT256)) { - throw safeMathErrorForCall(); + throw safeMathErrorForCall; } const result = offset.dividedToIntegerBy(denominator); if (product.mod(denominator).eq(0)) { @@ -363,12 +366,12 @@ describe('Exchange core internal functions', () => { } const isRoundingError = await referenceIsRoundingErrorCeilAsync(numerator, denominator, target); if (isRoundingError) { - throw roundingErrorForCall; + throw roundingErrorForCall(); } const product = numerator.multipliedBy(target); const offset = product.plus(denominator.minus(1)); if (offset.isGreaterThan(MAX_UINT256)) { - throw safeMathErrorForCall(); + throw safeMathErrorForCall; } const result = offset.dividedToIntegerBy(denominator); if (product.mod(denominator).eq(0)) { diff --git a/contracts/staking/package.json b/contracts/staking/package.json index 44df50f06a..1273b0c1c9 100644 --- a/contracts/staking/package.json +++ b/contracts/staking/package.json @@ -34,7 +34,7 @@ "lint-contracts": "solhint -c ../.solhint.json contracts/**/**/**/**/*.sol" }, "config": { - "abis": "generated-artifacts/@(IStaking|Staking).json", + "abis": "./generated-artifacts/@(IStaking|Staking).json", "abis:comment": "This list is auto-generated by contracts-gen. Don't edit manually." }, "repository": { diff --git a/contracts/staking/src/artifacts.ts b/contracts/staking/src/artifacts.ts index 980e292291..9abe222616 100644 --- a/contracts/staking/src/artifacts.ts +++ b/contracts/staking/src/artifacts.ts @@ -7,4 +7,4 @@ import { ContractArtifact } from 'ethereum-types'; import * as IStaking from '../generated-artifacts/IStaking.json'; import * as Staking from '../generated-artifacts/Staking.json'; -export const artifacts = { Staking: Staking as ContractArtifact, IStaking: IStaking as ContractArtifact }; +export const artifacts = { IStaking: IStaking as ContractArtifact, Staking: Staking as ContractArtifact }; diff --git a/contracts/utils/package.json b/contracts/utils/package.json index acf2be9c0a..36c46f76e0 100644 --- a/contracts/utils/package.json +++ b/contracts/utils/package.json @@ -34,7 +34,7 @@ "lint-contracts": "solhint -c ../.solhint.json contracts/**/**/**/**/*.sol" }, "config": { - "abis": "./generated-artifacts/@(LibAddress|IOwnable|LibBytes|LibEIP712|Ownable|ReentrancyGuard|RichErrors|SafeMath|TestConstants|TestLibAddressArray|TestLibBytes).json", + "abis": "./generated-artifacts/@(IOwnable|LibAddress|LibBytes|LibEIP712|Ownable|ReentrancyGuard|RichErrors|SafeMath|TestConstants|TestLibAddressArray|TestLibBytes).json", "abis:comment": "This list is auto-generated by contracts-gen. Don't edit manually." }, "repository": { diff --git a/contracts/utils/src/artifacts.ts b/contracts/utils/src/artifacts.ts index 4b8bf40f6a..2b82dbd63f 100644 --- a/contracts/utils/src/artifacts.ts +++ b/contracts/utils/src/artifacts.ts @@ -19,11 +19,11 @@ import * as TestLibBytes from '../generated-artifacts/TestLibBytes.json'; export const artifacts = { LibAddress: LibAddress as ContractArtifact, LibBytes: LibBytes as ContractArtifact, + LibEIP712: LibEIP712 as ContractArtifact, Ownable: Ownable as ContractArtifact, ReentrancyGuard: ReentrancyGuard as ContractArtifact, - SafeMath: SafeMath as ContractArtifact, - LibEIP712: LibEIP712 as ContractArtifact, RichErrors: RichErrors as ContractArtifact, + SafeMath: SafeMath as ContractArtifact, IOwnable: IOwnable as ContractArtifact, TestConstants: TestConstants as ContractArtifact, TestLibAddressArray: TestLibAddressArray as ContractArtifact, diff --git a/contracts/utils/src/wrappers.ts b/contracts/utils/src/wrappers.ts index c2b2d10ad5..94aab4f426 100644 --- a/contracts/utils/src/wrappers.ts +++ b/contracts/utils/src/wrappers.ts @@ -3,8 +3,8 @@ * Warning: This file is auto-generated by contracts-gen. Don't edit manually. * ----------------------------------------------------------------------------- */ -export * from '../generated-wrappers/lib_address'; export * from '../generated-wrappers/i_ownable'; +export * from '../generated-wrappers/lib_address'; export * from '../generated-wrappers/lib_bytes'; export * from '../generated-wrappers/lib_e_i_p712'; export * from '../generated-wrappers/ownable'; diff --git a/contracts/utils/tsconfig.json b/contracts/utils/tsconfig.json index 41af80b7d6..962e961380 100644 --- a/contracts/utils/tsconfig.json +++ b/contracts/utils/tsconfig.json @@ -3,8 +3,8 @@ "compilerOptions": { "outDir": "lib", "rootDir": ".", "resolveJsonModule": true }, "include": ["./src/**/*", "./test/**/*", "./generated-wrappers/**/*"], "files": [ - "generated-artifacts/LibAddress.json", "generated-artifacts/IOwnable.json", + "generated-artifacts/LibAddress.json", "generated-artifacts/LibBytes.json", "generated-artifacts/LibEIP712.json", "generated-artifacts/Ownable.json", diff --git a/packages/order-utils/src/index.ts b/packages/order-utils/src/index.ts index 9279fc1a0b..3d7a3fc462 100644 --- a/packages/order-utils/src/index.ts +++ b/packages/order-utils/src/index.ts @@ -1,4 +1,5 @@ import * as ExchangeRevertErrors from './exchange_revert_errors'; +import * as LibMathRevertErrors from './lib_math_revert_errors'; export { orderHashUtils } from './order_hash'; export { signatureUtils } from './signature_utils'; @@ -84,4 +85,4 @@ export { } from './types'; export { ExchangeContract, NetworkId } from '@0x/abi-gen-wrappers'; -export { ExchangeRevertErrors }; +export { ExchangeRevertErrors, LibMathRevertErrors }; diff --git a/packages/order-utils/src/lib_math_revert_errors.ts b/packages/order-utils/src/lib_math_revert_errors.ts new file mode 100644 index 0000000000..bf132852d5 --- /dev/null +++ b/packages/order-utils/src/lib_math_revert_errors.ts @@ -0,0 +1,31 @@ +import { BigNumber, RevertError } from '@0x/utils'; +import * as _ from 'lodash'; + +// tslint:disable:max-classes-per-file + +export class DivisionByZeroError extends RevertError { + constructor() { + super('DivisionByZeroError', 'DivisionByZeroError()', {}); + } +} + +export class RoundingError extends RevertError { + constructor( + numerator?: BigNumber | number | string, + denominator?: BigNumber | number | string, + target?: BigNumber | number | string, + ) { + super('RoundingError', 'RoundingError(uint256 numerator, uint256 denominator, uint256 target)', { + numerator, + denominator, + target, + }); + } +} + +const types = [DivisionByZeroError, RoundingError]; + +// Register the types we've defined. +for (const type of types) { + RevertError.registerType(type); +}