From 68a26e3984bb38dac3615bc2aacab6c02a27fdc9 Mon Sep 17 00:00:00 2001 From: Erik Date: Fri, 19 Jan 2024 18:36:15 +0000 Subject: [PATCH] Refactor error handling in LogExpMath.sol --- contracts/libraries/LogExpMath.sol | 14 +- contracts/utils/Errors.sol | 238 ----------------------------- 2 files changed, 6 insertions(+), 246 deletions(-) delete mode 100644 contracts/utils/Errors.sol diff --git a/contracts/libraries/LogExpMath.sol b/contracts/libraries/LogExpMath.sol index cca0567a..38abc80b 100644 --- a/contracts/libraries/LogExpMath.sol +++ b/contracts/libraries/LogExpMath.sol @@ -23,8 +23,6 @@ // XXX: 0.8.10; unchecked functions pragma solidity 0.8.10; -import "../utils/Errors.sol"; - /* solhint-disable */ /** @@ -115,14 +113,14 @@ library LogExpMath { // x^y = exp(y * ln(x)). // The ln function takes a signed value, so we need to make sure x fits in the signed 256 bit range. - _require(x < 2 ** 255, Errors.X_OUT_OF_BOUNDS); + require(x < 2 ** 255, "x out of bounds"); int256 x_int256 = int256(x); // We will compute y * ln(x) in a single step. Depending on the value of x, we can either use ln or ln_36. In // both cases, we leave the division by ONE_18 (due to fixed point multiplication) to the end. // This prevents y * ln(x) from overflowing, and at the same time guarantees y fits in the signed 256 bit range. - _require(y < MILD_EXPONENT_BOUND, Errors.Y_OUT_OF_BOUNDS); + require(y < MILD_EXPONENT_BOUND, "y out of bounds"); int256 y_int256 = int256(y); int256 logx_times_y; @@ -141,9 +139,9 @@ library LogExpMath { logx_times_y /= ONE_18; // Finally, we compute exp(y * ln(x)) to arrive at x^y - _require( + require( MIN_NATURAL_EXPONENT <= logx_times_y && logx_times_y <= MAX_NATURAL_EXPONENT, - Errors.PRODUCT_OUT_OF_BOUNDS + "product out of bounds" ); return uint256(exp(logx_times_y)); @@ -156,7 +154,7 @@ library LogExpMath { * Reverts if `x` is smaller than MIN_NATURAL_EXPONENT, or larger than `MAX_NATURAL_EXPONENT`. */ function exp(int256 x) internal pure returns (int256) { - _require(x >= MIN_NATURAL_EXPONENT && x <= MAX_NATURAL_EXPONENT, Errors.INVALID_EXPONENT); + require(x >= MIN_NATURAL_EXPONENT && x <= MAX_NATURAL_EXPONENT, "invalid exponent"); unchecked { if (x < 0) { @@ -328,7 +326,7 @@ library LogExpMath { */ function ln(int256 a) internal pure returns (int256) { // The real natural logarithm is not defined for negative numbers or zero. - _require(a > 0, Errors.OUT_OF_BOUNDS); + require(a > 0, "out of bounds"); unchecked { if (LN_36_LOWER_BOUND < a && a < LN_36_UPPER_BOUND) { diff --git a/contracts/utils/Errors.sol b/contracts/utils/Errors.sol deleted file mode 100644 index 05204caf..00000000 --- a/contracts/utils/Errors.sol +++ /dev/null @@ -1,238 +0,0 @@ -// SPDX-License-Identifier: GPL-3.0-or-later -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . - -pragma solidity 0.8.10; - -// solhint-disable - -/** - * @dev Reverts if `condition` is false, with a revert reason containing `errorCode`. Only codes up to 999 are - * supported. - */ -function _require(bool condition, uint256 errorCode) pure { - if (!condition) _revert(errorCode); -} - -/** - * @dev Reverts with a revert reason containing `errorCode`. Only codes up to 999 are supported. - */ -function _revert(uint256 errorCode) pure { - // We're going to dynamically create a revert string based on the error code, with the following format: - // 'BAL#{errorCode}' - // where the code is left-padded with zeroes to three digits (so they range from 000 to 999). - // - // We don't have revert strings embedded in the contract to save bytecode size: it takes much less space to store a - // number (8 to 16 bits) than the individual string characters. - // - // The dynamic string creation algorithm that follows could be implemented in Solidity, but assembly allows for a - // much denser implementation, again saving bytecode size. Given this function unconditionally reverts, this is a - // safe place to rely on it without worrying about how its usage might affect e.g. memory contents. - assembly { - // First, we need to compute the ASCII representation of the error code. We assume that it is in the 0-999 - // range, so we only need to convert three digits. To convert the digits to ASCII, we add 0x30, the value for - // the '0' character. - - let units := add(mod(errorCode, 10), 0x30) - - errorCode := div(errorCode, 10) - let tenths := add(mod(errorCode, 10), 0x30) - - errorCode := div(errorCode, 10) - let hundreds := add(mod(errorCode, 10), 0x30) - - // With the individual characters, we can now construct the full string. The "BAL#" part is a known constant - // (0x42414c23): we simply shift this by 24 (to provide space for the 3 bytes of the error code), and add the - // characters to it, each shifted by a multiple of 8. - // The revert reason is then shifted left by 200 bits (256 minus the length of the string, 7 characters * 8 bits - // per character = 56) to locate it in the most significant part of the 256 slot (the beginning of a byte - // array). - - let revertReason := - shl(200, add(0x42414c23000000, add(add(units, shl(8, tenths)), shl(16, hundreds)))) - - // We can now encode the reason in memory, which can be safely overwritten as we're about to revert. The encoded - // message will have the following layout: - // [ revert reason identifier ] [ string location offset ] [ string length ] [ string contents ] - - // The Solidity revert reason identifier is 0x08c739a0, the function selector of the Error(string) function. We - // also write zeroes to the next 28 bytes of memory, but those are about to be overwritten. - mstore(0x0, 0x08c379a000000000000000000000000000000000000000000000000000000000) - // Next is the offset to the location of the string, which will be placed immediately after (20 bytes away). - mstore(0x04, 0x0000000000000000000000000000000000000000000000000000000000000020) - // The string length is fixed: 7 characters. - mstore(0x24, 7) - // Finally, the string itself is stored. - mstore(0x44, revertReason) - - // Even if the string is only 7 bytes long, we need to return a full 32 byte slot containing it. The length of - // the encoded message is therefore 4 + 32 + 32 + 32 = 100. - revert(0, 100) - } -} - -library Errors { - // Math - uint256 internal constant ADD_OVERFLOW = 0; - uint256 internal constant SUB_OVERFLOW = 1; - uint256 internal constant SUB_UNDERFLOW = 2; - uint256 internal constant MUL_OVERFLOW = 3; - uint256 internal constant ZERO_DIVISION = 4; - uint256 internal constant DIV_INTERNAL = 5; - uint256 internal constant X_OUT_OF_BOUNDS = 6; - uint256 internal constant Y_OUT_OF_BOUNDS = 7; - uint256 internal constant PRODUCT_OUT_OF_BOUNDS = 8; - uint256 internal constant INVALID_EXPONENT = 9; - - // Input - uint256 internal constant OUT_OF_BOUNDS = 100; - uint256 internal constant UNSORTED_ARRAY = 101; - uint256 internal constant UNSORTED_TOKENS = 102; - uint256 internal constant INPUT_LENGTH_MISMATCH = 103; - uint256 internal constant ZERO_TOKEN = 104; - - // Shared pools - uint256 internal constant MIN_TOKENS = 200; - uint256 internal constant MAX_TOKENS = 201; - uint256 internal constant MAX_SWAP_FEE_PERCENTAGE = 202; - uint256 internal constant MIN_SWAP_FEE_PERCENTAGE = 203; - uint256 internal constant MINIMUM_BPT = 204; - uint256 internal constant CALLER_NOT_VAULT = 205; - uint256 internal constant UNINITIALIZED = 206; - uint256 internal constant BPT_IN_MAX_AMOUNT = 207; - uint256 internal constant BPT_OUT_MIN_AMOUNT = 208; - uint256 internal constant EXPIRED_PERMIT = 209; - uint256 internal constant NOT_TWO_TOKENS = 210; - uint256 internal constant DISABLED = 211; - - // Pools - uint256 internal constant MIN_AMP = 300; - uint256 internal constant MAX_AMP = 301; - uint256 internal constant MIN_WEIGHT = 302; - uint256 internal constant MAX_STABLE_TOKENS = 303; - uint256 internal constant MAX_IN_RATIO = 304; - uint256 internal constant MAX_OUT_RATIO = 305; - uint256 internal constant MIN_BPT_IN_FOR_TOKEN_OUT = 306; - uint256 internal constant MAX_OUT_BPT_FOR_TOKEN_IN = 307; - uint256 internal constant NORMALIZED_WEIGHT_INVARIANT = 308; - uint256 internal constant INVALID_TOKEN = 309; - uint256 internal constant UNHANDLED_JOIN_KIND = 310; - uint256 internal constant ZERO_INVARIANT = 311; - uint256 internal constant ORACLE_INVALID_SECONDS_QUERY = 312; - uint256 internal constant ORACLE_NOT_INITIALIZED = 313; - uint256 internal constant ORACLE_QUERY_TOO_OLD = 314; - uint256 internal constant ORACLE_INVALID_INDEX = 315; - uint256 internal constant ORACLE_BAD_SECS = 316; - uint256 internal constant AMP_END_TIME_TOO_CLOSE = 317; - uint256 internal constant AMP_ONGOING_UPDATE = 318; - uint256 internal constant AMP_RATE_TOO_HIGH = 319; - uint256 internal constant AMP_NO_ONGOING_UPDATE = 320; - uint256 internal constant STABLE_INVARIANT_DIDNT_CONVERGE = 321; - uint256 internal constant STABLE_GET_BALANCE_DIDNT_CONVERGE = 322; - uint256 internal constant RELAYER_NOT_CONTRACT = 323; - uint256 internal constant BASE_POOL_RELAYER_NOT_CALLED = 324; - uint256 internal constant REBALANCING_RELAYER_REENTERED = 325; - uint256 internal constant GRADUAL_UPDATE_TIME_TRAVEL = 326; - uint256 internal constant SWAPS_DISABLED = 327; - uint256 internal constant CALLER_IS_NOT_LBP_OWNER = 328; - uint256 internal constant PRICE_RATE_OVERFLOW = 329; - uint256 internal constant INVALID_JOIN_EXIT_KIND_WHILE_SWAPS_DISABLED = 330; - uint256 internal constant WEIGHT_CHANGE_TOO_FAST = 331; - uint256 internal constant LOWER_GREATER_THAN_UPPER_TARGET = 332; - uint256 internal constant UPPER_TARGET_TOO_HIGH = 333; - uint256 internal constant UNHANDLED_BY_LINEAR_POOL = 334; - uint256 internal constant OUT_OF_TARGET_RANGE = 335; - uint256 internal constant UNHANDLED_EXIT_KIND = 336; - uint256 internal constant UNAUTHORIZED_EXIT = 337; - uint256 internal constant MAX_MANAGEMENT_SWAP_FEE_PERCENTAGE = 338; - uint256 internal constant UNHANDLED_BY_MANAGED_POOL = 339; - uint256 internal constant UNHANDLED_BY_PHANTOM_POOL = 340; - uint256 internal constant TOKEN_DOES_NOT_HAVE_RATE_PROVIDER = 341; - uint256 internal constant INVALID_INITIALIZATION = 342; - uint256 internal constant OUT_OF_NEW_TARGET_RANGE = 343; - uint256 internal constant UNAUTHORIZED_OPERATION = 344; - uint256 internal constant UNINITIALIZED_POOL_CONTROLLER = 345; - - // Lib - uint256 internal constant REENTRANCY = 400; - uint256 internal constant SENDER_NOT_ALLOWED = 401; - uint256 internal constant PAUSED = 402; - uint256 internal constant PAUSE_WINDOW_EXPIRED = 403; - uint256 internal constant MAX_PAUSE_WINDOW_DURATION = 404; - uint256 internal constant MAX_BUFFER_PERIOD_DURATION = 405; - uint256 internal constant INSUFFICIENT_BALANCE = 406; - uint256 internal constant INSUFFICIENT_ALLOWANCE = 407; - uint256 internal constant ERC20_TRANSFER_FROM_ZERO_ADDRESS = 408; - uint256 internal constant ERC20_TRANSFER_TO_ZERO_ADDRESS = 409; - uint256 internal constant ERC20_MINT_TO_ZERO_ADDRESS = 410; - uint256 internal constant ERC20_BURN_FROM_ZERO_ADDRESS = 411; - uint256 internal constant ERC20_APPROVE_FROM_ZERO_ADDRESS = 412; - uint256 internal constant ERC20_APPROVE_TO_ZERO_ADDRESS = 413; - uint256 internal constant ERC20_TRANSFER_EXCEEDS_ALLOWANCE = 414; - uint256 internal constant ERC20_DECREASED_ALLOWANCE_BELOW_ZERO = 415; - uint256 internal constant ERC20_TRANSFER_EXCEEDS_BALANCE = 416; - uint256 internal constant ERC20_BURN_EXCEEDS_ALLOWANCE = 417; - uint256 internal constant SAFE_ERC20_CALL_FAILED = 418; - uint256 internal constant ADDRESS_INSUFFICIENT_BALANCE = 419; - uint256 internal constant ADDRESS_CANNOT_SEND_VALUE = 420; - uint256 internal constant SAFE_CAST_VALUE_CANT_FIT_INT256 = 421; - uint256 internal constant GRANT_SENDER_NOT_ADMIN = 422; - uint256 internal constant REVOKE_SENDER_NOT_ADMIN = 423; - uint256 internal constant RENOUNCE_SENDER_NOT_ALLOWED = 424; - uint256 internal constant BUFFER_PERIOD_EXPIRED = 425; - uint256 internal constant CALLER_IS_NOT_OWNER = 426; - uint256 internal constant NEW_OWNER_IS_ZERO = 427; - uint256 internal constant CODE_DEPLOYMENT_FAILED = 428; - uint256 internal constant CALL_TO_NON_CONTRACT = 429; - uint256 internal constant LOW_LEVEL_CALL_FAILED = 430; - uint256 internal constant NOT_PAUSED = 431; - uint256 internal constant ADDRESS_ALREADY_ALLOWLISTED = 432; - uint256 internal constant ADDRESS_NOT_ALLOWLISTED = 433; - uint256 internal constant ERC20_BURN_EXCEEDS_BALANCE = 434; - - // Vault - uint256 internal constant INVALID_POOL_ID = 500; - uint256 internal constant CALLER_NOT_POOL = 501; - uint256 internal constant SENDER_NOT_ASSET_MANAGER = 502; - uint256 internal constant USER_DOESNT_ALLOW_RELAYER = 503; - uint256 internal constant INVALID_SIGNATURE = 504; - uint256 internal constant EXIT_BELOW_MIN = 505; - uint256 internal constant JOIN_ABOVE_MAX = 506; - uint256 internal constant SWAP_LIMIT = 507; - uint256 internal constant SWAP_DEADLINE = 508; - uint256 internal constant CANNOT_SWAP_SAME_TOKEN = 509; - uint256 internal constant UNKNOWN_AMOUNT_IN_FIRST_SWAP = 510; - uint256 internal constant MALCONSTRUCTED_MULTIHOP_SWAP = 511; - uint256 internal constant INTERNAL_BALANCE_OVERFLOW = 512; - uint256 internal constant INSUFFICIENT_INTERNAL_BALANCE = 513; - uint256 internal constant INVALID_ETH_INTERNAL_BALANCE = 514; - uint256 internal constant INVALID_POST_LOAN_BALANCE = 515; - uint256 internal constant INSUFFICIENT_ETH = 516; - uint256 internal constant UNALLOCATED_ETH = 517; - uint256 internal constant ETH_TRANSFER = 518; - uint256 internal constant CANNOT_USE_ETH_SENTINEL = 519; - uint256 internal constant TOKENS_MISMATCH = 520; - uint256 internal constant TOKEN_NOT_REGISTERED = 521; - uint256 internal constant TOKEN_ALREADY_REGISTERED = 522; - uint256 internal constant TOKENS_ALREADY_SET = 523; - uint256 internal constant TOKENS_LENGTH_MUST_BE_2 = 524; - uint256 internal constant NONZERO_TOKEN_BALANCE = 525; - uint256 internal constant BALANCE_TOTAL_OVERFLOW = 526; - uint256 internal constant POOL_NO_TOKENS = 527; - uint256 internal constant INSUFFICIENT_FLASH_LOAN_BALANCE = 528; - - // Fees - uint256 internal constant SWAP_FEE_PERCENTAGE_TOO_HIGH = 600; - uint256 internal constant FLASH_LOAN_FEE_PERCENTAGE_TOO_HIGH = 601; - uint256 internal constant INSUFFICIENT_FLASH_LOAN_FEE_AMOUNT = 602; -}