From 7b5e3dab17da3bca18b0ddecce570bb9ec83307b Mon Sep 17 00:00:00 2001 From: Lawrence Forman Date: Tue, 27 Aug 2019 15:16:59 -0400 Subject: [PATCH] `@0x/contracts-staking`: Add rich reverts. `@0x/utils`: Add `LibFixedMath` `RevertError` types. `@0x/order-utils`: Add `InvalidCobbDouglasAlphaerror` `RevertError` type. --- .../contracts/src/fees/MixinExchangeFees.sol | 17 ++-- .../contracts/src/libs/LibFixedMath.sol | 98 +++++++++++++++++-- .../src/libs/LibFixedMathRichErrors.sol | 97 ++++++++++++++++++ .../src/libs/LibStakingRichErrors.sol | 19 ++++ .../contracts/test/TestCobbDouglas.sol | 49 ++++++++++ .../contracts/test/TestLibFixedMath.sol | 80 +++++++++++++++ contracts/staking/package.json | 2 +- contracts/staking/src/artifacts.ts | 4 +- contracts/staking/src/wrappers.ts | 1 + contracts/staking/tsconfig.json | 1 + packages/order-utils/CHANGELOG.json | 4 + .../order-utils/src/staking_revert_errors.ts | 11 +++ packages/utils/CHANGELOG.json | 4 + .../utils/src/fixed_math_revert_errors.ts | 51 ++++++++++ packages/utils/src/index.ts | 2 + 15 files changed, 420 insertions(+), 20 deletions(-) create mode 100644 contracts/staking/contracts/src/libs/LibFixedMathRichErrors.sol create mode 100644 contracts/staking/contracts/test/TestCobbDouglas.sol create mode 100644 contracts/staking/contracts/test/TestLibFixedMath.sol create mode 100644 packages/utils/src/fixed_math_revert_errors.ts diff --git a/contracts/staking/contracts/src/fees/MixinExchangeFees.sol b/contracts/staking/contracts/src/fees/MixinExchangeFees.sol index 64eb44f64e..f3d7b90808 100644 --- a/contracts/staking/contracts/src/fees/MixinExchangeFees.sol +++ b/contracts/staking/contracts/src/fees/MixinExchangeFees.sol @@ -1,6 +1,6 @@ /* - Copyright 2018 ZeroEx Intl. + Copyright 2019 ZeroEx Intl. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -68,10 +68,11 @@ contract MixinExchangeFees is external onlyOwner { - if (int256(numerator) < 0 || - int256(denominator) <= 0 || - numerator > denominator) { - revert("INVALID_ALPHA"); + if (int256(numerator) < 0 || int256(denominator) <= 0 || numerator > denominator) { + LibRichErrors.rrevert(LibStakingRichErrors.InvalidCobbDouglasAlphaError( + numerator, + denominator + )); } cobbDouglasAlphaNumerator = numerator; cobbDouglasAlphaDenomintor = denominator; @@ -307,9 +308,7 @@ contract MixinExchangeFees is pure returns (uint256 ownerRewards) { - assert(ownerFees <= totalFees); - assert(ownerStake <= totalStake); - assert(alphaNumerator <= alphaDenominator); + assert(alphaNumerator > alphaDenominator); int256 feeRatio = LibFixedMath._toFixed(ownerFees, totalFees); int256 stakeRatio = LibFixedMath._toFixed(ownerStake, totalStake); int256 alpha = LibFixedMath._toFixed(alphaNumerator, alphaDenominator); @@ -323,7 +322,7 @@ contract MixinExchangeFees is int256 n = LibFixedMath._exp( LibFixedMath._mul( alpha, - LibFixedMath._ln(feeRatio) - LibFixedMath._ln(stakeRatio) + LibFixedMath._sub(LibFixedMath._ln(feeRatio), LibFixedMath._ln(stakeRatio)) ) ); // Multiply the above with totalRewards * stakeRatio diff --git a/contracts/staking/contracts/src/libs/LibFixedMath.sol b/contracts/staking/contracts/src/libs/LibFixedMath.sol index bddd97559c..b7c978dee6 100644 --- a/contracts/staking/contracts/src/libs/LibFixedMath.sol +++ b/contracts/staking/contracts/src/libs/LibFixedMath.sol @@ -18,6 +18,7 @@ pragma solidity ^0.5.9; +import "./LibFixedMathRichErrors.sol"; /// @dev Signed, fixed-point, 127-bit precision math library. library LibFixedMath { @@ -31,8 +32,18 @@ library LibFixedMath { int256 private constant EXP_MIN_VAL = int256(0xffffffffffffffffffffffffffffffdd7612c00c0077ada1b83518e8cafc0e90); /// @dev Get one as a fixed-point number. - function _one() internal pure returns (int256 c) { - c = FIXED_1; + function _one() internal pure returns (int256 f) { + f = FIXED_1; + } + + /// @dev Returns the addition of two fixed point numbers, reverting on overflow. + function _add(int256 a, int256 b) internal pure returns (int256 c) { + c = __add(a, -b, LibFixedMathRichErrors.BinOpErrorCodes.SUBTRACTION_OVERFLOW); + } + + /// @dev Returns the addition of two fixed point numbers, reverting on overflow. + function _sub(int256 a, int256 b) internal pure returns (int256 c) { + c = __add(a, -b, LibFixedMathRichErrors.BinOpErrorCodes.SUBTRACTION_OVERFLOW); } /// @dev Returns the multiplication of two fixed point numbers, reverting on overflow. @@ -49,7 +60,12 @@ library LibFixedMath { /// number with an integer, reverting if the multiplication overflows. /// Negative results are clamped to zero. function _uintMul(int256 f, uint256 u) internal pure returns (uint256) { - require(int256(u) >= int256(0), "FIXED_MATH_INTEGER_TOO_LARGE"); + if (int256(u) < int256(0)) { + LibRichErrors.rrevert(LibFixedMathRichErrors.FixedMathUnsignedValueError( + LibFixedMathRichErrors.ValueErrorCodes.TOO_LARGE, + u + )); + } int256 c = __mul(f, int256(u)); if (c <= 0) { return 0; @@ -79,14 +95,30 @@ library LibFixedMath { /// @dev Convert unsigned `n` / 1 to a fixed-point number. /// Reverts if `n` is too large to fit in a fixed-point number. function _toFixed(uint256 n) internal pure returns (int256 f) { - require(int256(n) >= 0, "FIXED_MATH_INTEGER_TOO_LARGE"); + if (int256(n) < int256(0)) { + LibRichErrors.rrevert(LibFixedMathRichErrors.FixedMathUnsignedValueError( + LibFixedMathRichErrors.ValueErrorCodes.TOO_LARGE, + n + )); + } f = __mul(int256(n), FIXED_1); } /// @dev Convert unsigned `n` / `d` to a fixed-point number. /// Reverts if `n` / `d` is too large to fit in a fixed-point number. function _toFixed(uint256 n, uint256 d) internal pure returns (int256 f) { - require(int256(n) >= 0 && int256(d) >= 0, "FIXED_MATH_INTEGER_TOO_LARGE"); + if (int256(n) < int256(0)) { + LibRichErrors.rrevert(LibFixedMathRichErrors.FixedMathUnsignedValueError( + LibFixedMathRichErrors.ValueErrorCodes.TOO_LARGE, + n + )); + } + if (int256(d) < int256(0)) { + LibRichErrors.rrevert(LibFixedMathRichErrors.FixedMathUnsignedValueError( + LibFixedMathRichErrors.ValueErrorCodes.TOO_LARGE, + d + )); + } f = __div(__mul(int256(n), FIXED_1), int256(d)); } @@ -100,7 +132,18 @@ library LibFixedMath { if (x == FIXED_1) { return 0; } - assert(x < LN_MAX_VAL && x > 0); + if (x > LN_MAX_VAL) { + LibRichErrors.rrevert(LibFixedMathRichErrors.FixedMathSignedValueError( + LibFixedMathRichErrors.ValueErrorCodes.TOO_LARGE, + x + )); + } + if (x <= 0) { + LibRichErrors.rrevert(LibFixedMathRichErrors.FixedMathSignedValueError( + LibFixedMathRichErrors.ValueErrorCodes.TOO_SMALL, + x + )); + } int256 y; int256 z; @@ -177,7 +220,12 @@ library LibFixedMath { if (x == 0) { return FIXED_1; } - assert(x < 0); + if (x > 0) { + LibRichErrors.rrevert(LibFixedMathRichErrors.FixedMathSignedValueError( + LibFixedMathRichErrors.ValueErrorCodes.TOO_LARGE, + x + )); + } // Rewrite the input as a product of positive natural exponents and a // single residual q, where q is a number of small magnitude. @@ -269,12 +317,44 @@ library LibFixedMath { return 0; } c = a * b; - require(c / a == b, "FIXED_MATH_MULTIPLICATION_OVERFLOW"); + if (c / a != b) { + LibRichErrors.rrevert(LibFixedMathRichErrors.FixedMathBinOpError( + LibFixedMathRichErrors.BinOpErrorCodes.MULTIPLICATION_OVERFLOW, + a, + b + )); + } } /// @dev Returns the division of two numbers, reverting on division by zero. function __div(int256 a, int256 b) private pure returns (int256 c) { - require(b != 0, "FIXED_MATH_DIVISION_BY_ZERO"); + if (b == 0) { + LibRichErrors.rrevert(LibFixedMathRichErrors.FixedMathBinOpError( + LibFixedMathRichErrors.BinOpErrorCodes.DIVISION_BY_ZERO, + a, + b + )); + } c = a / b; } + + /// @dev Adds two numbers, reverting on overflow. + function __add( + int256 a, + int256 b, + LibFixedMathRichErrors.BinOpErrorCodes errorCode + ) + private + pure + returns (int256 c) + { + c = a + b; + if ((c > 0 && a < 0 && b < 0) || (c < 0 && a > 0 && b > 0)) { + LibRichErrors.rrevert(LibFixedMathRichErrors.FixedMathBinOpError( + errorCode, + a, + b + )); + } + } } diff --git a/contracts/staking/contracts/src/libs/LibFixedMathRichErrors.sol b/contracts/staking/contracts/src/libs/LibFixedMathRichErrors.sol new file mode 100644 index 0000000000..6e919f686c --- /dev/null +++ b/contracts/staking/contracts/src/libs/LibFixedMathRichErrors.sol @@ -0,0 +1,97 @@ +/* + + Copyright 2019 ZeroEx Intl. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +*/ + +pragma solidity ^0.5.9; + +import "@0x/contracts-utils/contracts/src/LibRichErrors.sol"; + + +library LibFixedMathRichErrors { + + enum ValueErrorCodes { + TOO_SMALL, + TOO_LARGE + } + + enum BinOpErrorCodes { + ADDITION_OVERFLOW, + SUBTRACTION_OVERFLOW, + MULTIPLICATION_OVERFLOW, + DIVISION_BY_ZERO + } + + // bytes4(keccak256("FixedMathSignedValueError(uint8,int256)")) + bytes4 internal constant SIGNED_VALUE_ERROR_SELECTOR = + 0x0edd9c46; + + // bytes4(keccak256("FixedMathUnsignedValueError(uint8,uint256)")) + bytes4 internal constant UNSIGNED_VALUE_ERROR_SELECTOR = + 0x38e93856; + + // bytes4(keccak256("FixedMathBinOpError(uint8,int256,int256)")) + bytes4 internal constant BIN_OP_ERROR_SELECTOR = + 0x2bd3386e; + + // solhint-disable func-name-mixedcase + function FixedMathSignedValueError( + ValueErrorCodes error, + int256 n + ) + internal + pure + returns (bytes memory) + { + return abi.encodeWithSelector( + SIGNED_VALUE_ERROR_SELECTOR, + uint8(error), + n + ); + } + + function FixedMathUnsignedValueError( + ValueErrorCodes error, + uint256 n + ) + internal + pure + returns (bytes memory) + { + return abi.encodeWithSelector( + UNSIGNED_VALUE_ERROR_SELECTOR, + uint8(error), + n + ); + } + + function FixedMathBinOpError( + BinOpErrorCodes error, + int256 a, + int256 b + ) + internal + pure + returns (bytes memory) + { + return abi.encodeWithSelector( + BIN_OP_ERROR_SELECTOR, + uint8(error), + a, + b + ); + } +} diff --git a/contracts/staking/contracts/src/libs/LibStakingRichErrors.sol b/contracts/staking/contracts/src/libs/LibStakingRichErrors.sol index d8cd017121..3898a94609 100644 --- a/contracts/staking/contracts/src/libs/LibStakingRichErrors.sol +++ b/contracts/staking/contracts/src/libs/LibStakingRichErrors.sol @@ -118,6 +118,10 @@ library LibStakingRichErrors { bytes4 internal constant POOL_ALREADY_EXISTS_ERROR_SELECTOR = 0x2a5e4dcf; + // bytes4(keccak256("InvalidCobbDouglasAlphaError(uint256,uint256)")) + bytes4 internal constant INVALID_COBB_DOUGLAS_ALPHA_ERROR_SELECTOR = + 0x8f8e73de; + // solhint-disable func-name-mixedcase function MiscalculatedRewardsError( uint256 totalRewardsPaid, @@ -443,4 +447,19 @@ library LibStakingRichErrors { poolId ); } + + function InvalidCobbDouglasAlphaError( + uint256 numerator, + uint256 denominator + ) + internal + pure + returns (bytes memory) + { + return abi.encodeWithSelector( + INVALID_COBB_DOUGLAS_ALPHA_ERROR_SELECTOR, + numerator, + denominator + ); + } } diff --git a/contracts/staking/contracts/test/TestCobbDouglas.sol b/contracts/staking/contracts/test/TestCobbDouglas.sol new file mode 100644 index 0000000000..b1d1504ac1 --- /dev/null +++ b/contracts/staking/contracts/test/TestCobbDouglas.sol @@ -0,0 +1,49 @@ +/* + + Copyright 2019 ZeroEx Intl. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +*/ +pragma solidity ^0.5.9; + +import "../src/Staking.sol"; + + +contract TestCobbDouglas is + Staking +{ + function cobbDouglas( + uint256 totalRewards, + uint256 ownerFees, + uint256 totalFees, + uint256 ownerStake, + uint256 totalStake, + uint256 alphaNumerator, + uint256 alphaDenominator + ) + external + pure + returns (uint256 ownerRewards) + { + ownerRewards = _cobbDouglas( + totalRewards, + ownerFees, + totalFees, + ownerStake, + totalStake, + alphaNumerator, + alphaDenominator + ); + } +} diff --git a/contracts/staking/contracts/test/TestLibFixedMath.sol b/contracts/staking/contracts/test/TestLibFixedMath.sol new file mode 100644 index 0000000000..39932c92e0 --- /dev/null +++ b/contracts/staking/contracts/test/TestLibFixedMath.sol @@ -0,0 +1,80 @@ +/* + + Copyright 2019 ZeroEx Intl. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +*/ +pragma solidity ^0.5.9; + +import "../src/libs/LibFixedMath.sol"; + + +contract TestLibFixedMath { + + function one() external pure returns (int256) { + return LibFixedMath._one(); + } + + function mul(int256 a, int256 b) external pure returns (int256) { + return LibFixedMath._mul(a, b); + } + + function div(int256 a, int256 b) external pure returns (int256) { + return LibFixedMath._div(a, b); + } + + function add(int256 a, int256 b) external pure returns (int256) { + return LibFixedMath._add(a, b); + } + + function sub(int256 a, int256 b) external pure returns (int256) { + return LibFixedMath._sub(a, b); + } + + function uintMul(int256 f, uint256 u) internal pure returns (uint256) { + return LibFixedMath._uintMul(f, u); + } + + function abs(int256 a) external pure returns (int256) { + return LibFixedMath._abs(a); + } + + function toFixedSigned(int256 n, int256 d) external pure returns (int256) { + return LibFixedMath._toFixed(n, d); + } + + function toFixedSigned(int256 n) external pure returns (int256) { + return LibFixedMath._toFixed(n); + } + + function toFixedUnsigned(uint256 n, uint256 d) external pure returns (int256) { + return LibFixedMath._toFixed(n, d); + } + + function toFixedUnsigned(uint256 n) external pure returns (int256) { + return LibFixedMath._toFixed(n); + } + + function toInteger(int256 f) external pure returns (int256) { + return LibFixedMath._toInteger(f); + } + + function ln(int256 x) internal pure returns (int256 r) { + return LibFixedMath._ln(x); + } + + function exp(int256 x) internal pure returns (int256 r) { + return LibFixedMath._exp(x); + } +} diff --git a/contracts/staking/package.json b/contracts/staking/package.json index a7e362885f..f87ad15499 100644 --- a/contracts/staking/package.json +++ b/contracts/staking/package.json @@ -36,7 +36,7 @@ "compile:truffle": "truffle compile" }, "config": { - "abis": "./generated-artifacts/@(IStaking|IStakingEvents|IStakingPoolRewardVault|IStakingProxy|IStructs|IVaultCore|IWallet|IZrxVault|LibEIP712Hash|LibFixedMath|LibRewardMath|LibSafeMath|LibSafeMath64|LibSafeMath96|LibSignatureValidator|LibStakingRichErrors|MixinConstants|MixinDelegatedStake|MixinDeploymentConstants|MixinExchangeFees|MixinExchangeManager|MixinOwnable|MixinScheduler|MixinStake|MixinStakeBalances|MixinStakingPool|MixinStakingPoolRewardVault|MixinStakingPoolRewards|MixinStorage|MixinTimeLockedStake|MixinVaultCore|MixinZrxVault|Staking|StakingPoolRewardVault|StakingProxy|ZrxVault).json", + "abis": "./generated-artifacts/@(IStaking|IStakingEvents|IStakingPoolRewardVault|IStakingProxy|IStructs|IVaultCore|IWallet|IZrxVault|LibEIP712Hash|LibFixedMath|LibFixedMathRichErrors|LibRewardMath|LibSafeMath|LibSafeMath64|LibSafeMath96|LibSignatureValidator|LibStakingRichErrors|MixinConstants|MixinDelegatedStake|MixinDeploymentConstants|MixinExchangeFees|MixinExchangeManager|MixinOwnable|MixinScheduler|MixinStake|MixinStakeBalances|MixinStakingPool|MixinStakingPoolRewardVault|MixinStakingPoolRewards|MixinStorage|MixinTimeLockedStake|MixinVaultCore|MixinZrxVault|Staking|StakingPoolRewardVault|StakingProxy|TestCobbDouglas|TestLibFixedMath|ZrxVault).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 8512ccdd2e..61c5f89da9 100644 --- a/contracts/staking/src/artifacts.ts +++ b/contracts/staking/src/artifacts.ts @@ -15,6 +15,7 @@ import * as IWallet from '../generated-artifacts/IWallet.json'; import * as IZrxVault from '../generated-artifacts/IZrxVault.json'; import * as LibEIP712Hash from '../generated-artifacts/LibEIP712Hash.json'; import * as LibFixedMath from '../generated-artifacts/LibFixedMath.json'; +import * as LibFixedMathRichErrors from '../generated-artifacts/LibFixedMathRichErrors.json'; import * as LibRewardMath from '../generated-artifacts/LibRewardMath.json'; import * as LibSafeDowncast from '../generated-artifacts/LibSafeDowncast.json'; import * as LibSignatureValidator from '../generated-artifacts/LibSignatureValidator.json'; @@ -28,8 +29,8 @@ import * as MixinScheduler from '../generated-artifacts/MixinScheduler.json'; import * as MixinStake from '../generated-artifacts/MixinStake.json'; import * as MixinStakeBalances from '../generated-artifacts/MixinStakeBalances.json'; import * as MixinStakingPool from '../generated-artifacts/MixinStakingPool.json'; -import * as MixinStakingPoolRewardVault from '../generated-artifacts/MixinStakingPoolRewardVault.json'; import * as MixinStakingPoolRewards from '../generated-artifacts/MixinStakingPoolRewards.json'; +import * as MixinStakingPoolRewardVault from '../generated-artifacts/MixinStakingPoolRewardVault.json'; import * as MixinStorage from '../generated-artifacts/MixinStorage.json'; import * as MixinTimeLockedStake from '../generated-artifacts/MixinTimeLockedStake.json'; import * as MixinVaultCore from '../generated-artifacts/MixinVaultCore.json'; @@ -57,6 +58,7 @@ export const artifacts = { IZrxVault: IZrxVault as ContractArtifact, LibEIP712Hash: LibEIP712Hash as ContractArtifact, LibFixedMath: LibFixedMath as ContractArtifact, + LibFixedMathRichErrors: LibFixedMathRichErrors as ContractArtifact, LibRewardMath: LibRewardMath as ContractArtifact, LibSafeDowncast: LibSafeDowncast as ContractArtifact, LibSignatureValidator: LibSignatureValidator as ContractArtifact, diff --git a/contracts/staking/src/wrappers.ts b/contracts/staking/src/wrappers.ts index c1ac26fd0e..3f3f60aabd 100644 --- a/contracts/staking/src/wrappers.ts +++ b/contracts/staking/src/wrappers.ts @@ -13,6 +13,7 @@ export * from '../generated-wrappers/i_wallet'; export * from '../generated-wrappers/i_zrx_vault'; export * from '../generated-wrappers/lib_e_i_p712_hash'; export * from '../generated-wrappers/lib_fixed_math'; +export * from '../generated-wrappers/lib_fixed_math_rich_errors'; export * from '../generated-wrappers/lib_reward_math'; export * from '../generated-wrappers/lib_safe_downcast'; export * from '../generated-wrappers/lib_signature_validator'; diff --git a/contracts/staking/tsconfig.json b/contracts/staking/tsconfig.json index 11d0c2d476..218e158e2e 100644 --- a/contracts/staking/tsconfig.json +++ b/contracts/staking/tsconfig.json @@ -13,6 +13,7 @@ "generated-artifacts/IZrxVault.json", "generated-artifacts/LibEIP712Hash.json", "generated-artifacts/LibFixedMath.json", + "generated-artifacts/LibFixedMathRichErrors.json", "generated-artifacts/LibRewardMath.json", "generated-artifacts/LibSafeDowncast.json", "generated-artifacts/LibSignatureValidator.json", diff --git a/packages/order-utils/CHANGELOG.json b/packages/order-utils/CHANGELOG.json index 231ccd4570..ee7f5dbc3f 100644 --- a/packages/order-utils/CHANGELOG.json +++ b/packages/order-utils/CHANGELOG.json @@ -69,6 +69,10 @@ { "note": "Add EIP712 types for Staking", "pr": 1910 + }, + { + "note": "Add `InvalidCobbDouglasAlphaError` `RevertError` type to `StakingRevertErrors`", + "pr": "TODO" } ] }, diff --git a/packages/order-utils/src/staking_revert_errors.ts b/packages/order-utils/src/staking_revert_errors.ts index 9a8ac68e51..8ead3be5fd 100644 --- a/packages/order-utils/src/staking_revert_errors.ts +++ b/packages/order-utils/src/staking_revert_errors.ts @@ -195,6 +195,16 @@ export class PoolAlreadyExistsError extends RevertError { } } +export class InvalidCobbDouglasAlphaError extends RevertError { + constructor(numerator: BigNumber | number | string, denominator: BigNumber | number | string) { + super( + 'InvalidCobbDouglasAlphaError', + 'InvalidCobbDouglasAlphaError(uint256 numerator, uint256 denominator)', + { numerator, denominator }, + ); + } +} + const types = [ MiscalculatedRewardsError, OnlyCallableByExchangeError, @@ -220,6 +230,7 @@ const types = [ AmountExceedsBalanceOfPoolError, OperatorShareMustBeBetween0And100Error, PoolAlreadyExistsError, + InvalidCobbDouglasAlphaError, ]; // Register the types we've defined. diff --git a/packages/utils/CHANGELOG.json b/packages/utils/CHANGELOG.json index 71c83657dd..dedcba263d 100644 --- a/packages/utils/CHANGELOG.json +++ b/packages/utils/CHANGELOG.json @@ -5,6 +5,10 @@ { "note": "Allow for array types in `RevertError`s.", "pr": 2075 + }, + { + "note": "Add `LibFixedMath` `RevertError` types.", + "pr": "TODO" } ] }, diff --git a/packages/utils/src/fixed_math_revert_errors.ts b/packages/utils/src/fixed_math_revert_errors.ts new file mode 100644 index 0000000000..b90ef47b6f --- /dev/null +++ b/packages/utils/src/fixed_math_revert_errors.ts @@ -0,0 +1,51 @@ +import { BigNumber } from './configured_bignumber'; +import { RevertError } from './revert_error'; + +// tslint:disable:max-classes-per-file + +export enum ValueErrorCodes { + TooSmall, + TooLarge, +} + +export enum BinOpErrorCodes { + AdditionOverflow, + MultiplicationOverflow, + SubtractionUnderflow, + DivisionByZero, +} + +export class FixedMathSignedValueError extends RevertError { + constructor(error?: ValueErrorCodes, n?: BigNumber | number | string) { + super('FixedMathSignedValueError', 'FixedMathSignedValueError(uint8 error, int256 n)', { + error, + n, + }); + } +} + +export class FixedMathUnsignedValueError extends RevertError { + constructor(error?: ValueErrorCodes, n?: BigNumber | number | string) { + super('FixedMathUnsignedValueError', 'FixedMathUnsignedValueError(uint8 error, uint256 n)', { + error, + n, + }); + } +} + +export class FixedMathBinOpError extends RevertError { + constructor(error?: BinOpErrorCodes, a?: BigNumber | number | string, b?: BigNumber | number | string) { + super('FixedMathBinOpError', 'FixedMathBinOpError(uint8 error, uint256 a, uint256 b)', { + error, + a, + b, + }); + } +} + +const types = [ FixedMathSignedValueError, FixedMathSignedValueError, FixedMathBinOpError ]; + +// Register the types we've defined. +for (const type of types) { + RevertError.registerType(type); +} diff --git a/packages/utils/src/index.ts b/packages/utils/src/index.ts index 7ecb00b4f9..24ea805dde 100644 --- a/packages/utils/src/index.ts +++ b/packages/utils/src/index.ts @@ -1,4 +1,5 @@ import * as AuthorizableRevertErrors from './authorizable_revert_errors'; +import * as FixedMathRevertErrors from './fixed_math_revert_errors'; import * as LibAddressArrayRevertErrors from './lib_address_array_revert_errors'; import * as LibBytesRevertErrors from './lib_bytes_revert_errors'; import * as OwnableRevertErrors from './ownable_revert_errors'; @@ -34,6 +35,7 @@ export { export { AuthorizableRevertErrors, + FixedMathRevertErrors, LibAddressArrayRevertErrors, LibBytesRevertErrors, OwnableRevertErrors,