diff --git a/.eslintrc.js b/.eslintrc.js index a39903d9..1290a172 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -26,6 +26,17 @@ module.exports = { semi: ["error", "always"], "spaced-comment": ["error", "always", { exceptions: ["-", "+"] }], "no-console": 0, + "no-restricted-imports": [ + "error", + { + "patterns": [ + { group: ["@ethersproject/bignumber"], message: "Use 'src/utils/BigNumberUtils' instead" }, + ], + "paths": [ + { name: "ethers", importNames: ["BigNumber"], message: "Use 'src/utils/BigNumberUtils' instead" } + ] + } + ], "@typescript-eslint/no-unused-vars": ["error", { ignoreRestSiblings: true }], "chai-expect/missing-assertion": 2, "no-duplicate-imports": "error", diff --git a/e2e/oracle.e2e.ts b/e2e/oracle.e2e.ts index 2fc7ba32..df2b0e3d 100644 --- a/e2e/oracle.e2e.ts +++ b/e2e/oracle.e2e.ts @@ -1,8 +1,9 @@ // @note: This test is _not_ run automatically as part of git hooks or CI. import dotenv from "dotenv"; import winston from "winston"; -import { BigNumber, providers, utils as ethersUtils } from "ethers"; +import { providers, utils as ethersUtils } from "ethers"; import { getGasPriceEstimate } from "../src/gasPriceOracle"; +import { BigNumber } from "../src/utils"; import { assertPromiseError, expect } from "../test/utils"; dotenv.config({ path: ".env" }); diff --git a/package.json b/package.json index dc03e905..ef2c4e09 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "@across-protocol/sdk", "author": "UMA Team", - "version": "3.1.34", + "version": "3.1.35", "license": "AGPL-3.0", "homepage": "https://docs.across.to/reference/sdk", "files": [ @@ -101,6 +101,7 @@ "@across-protocol/constants": "^3.1.14", "@across-protocol/contracts": "^3.0.10", "@eth-optimism/sdk": "^3.3.1", + "@ethersproject/bignumber": "^5.7.0", "@pinata/sdk": "^2.1.0", "@types/mocha": "^10.0.1", "@uma/sdk": "^0.34.1", diff --git a/src/apiClient/abstractClient.ts b/src/apiClient/abstractClient.ts index adefe77b..c082731d 100644 --- a/src/apiClient/abstractClient.ts +++ b/src/apiClient/abstractClient.ts @@ -1,4 +1,4 @@ -import { ethers } from "ethers"; +import { BigNumber } from "../utils"; import { CoingeckoDataReturnType, SuggestedFeeReturnType, @@ -64,7 +64,7 @@ export default abstract class AbstractApiClient { * @throws Throws an error if the API call fails. */ public abstract getSuggestedFees( - amount: ethers.BigNumber, + amount: BigNumber, originToken: string, toChainid: number, fromChainid: number diff --git a/src/apiClient/mockedClient.ts b/src/apiClient/mockedClient.ts index f1250452..627d5ffb 100644 --- a/src/apiClient/mockedClient.ts +++ b/src/apiClient/mockedClient.ts @@ -1,6 +1,7 @@ /* eslint-disable @typescript-eslint/no-unused-vars */ import { ethers } from "ethers"; import { deepCopy } from "ethers/lib/utils"; +import { BigNumber, bnOne } from "../utils"; import AbstractApiClient from "./abstractClient"; import { AcrossBridgeStatisticsType, @@ -39,7 +40,7 @@ export default class MockedApiClient extends AbstractApiClient { ); } public getSuggestedFees( - _amount: ethers.BigNumber, + _amount: BigNumber, _originToken: string, _toChainid: number, _fromChainid: number @@ -47,20 +48,20 @@ export default class MockedApiClient extends AbstractApiClient { return Promise.resolve( this.mockedData.SuggestedFees ?? { relayerFee: { - pct: ethers.constants.One, - total: ethers.constants.One, + pct: bnOne, + total: bnOne, }, relayerCapitalFee: { - pct: ethers.constants.One, - total: ethers.constants.One, + pct: bnOne, + total: bnOne, }, relayerGasFee: { - pct: ethers.constants.One, - total: ethers.constants.One, + pct: bnOne, + total: bnOne, }, isAmountTooLow: false, - quoteBlock: ethers.constants.One, - quoteTimestamp: ethers.constants.One, + quoteBlock: bnOne, + quoteTimestamp: bnOne, } ); } @@ -71,10 +72,10 @@ export default class MockedApiClient extends AbstractApiClient { ): Promise { return Promise.resolve( this.mockedData.BridgeLimits ?? { - minDeposit: ethers.BigNumber.from("317845960607070"), - maxDeposit: ethers.BigNumber.from("1625976243310274613043"), - maxDepositInstant: ethers.BigNumber.from("148518401181482545509"), - maxDepositShortDelay: ethers.BigNumber.from("1625976243310274613043"), + minDeposit: BigNumber.from("317845960607070"), + maxDeposit: BigNumber.from("1625976243310274613043"), + maxDepositInstant: BigNumber.from("148518401181482545509"), + maxDepositShortDelay: BigNumber.from("1625976243310274613043"), } ); } diff --git a/src/apiClient/productionClient.ts b/src/apiClient/productionClient.ts index e794bedf..e6b9a83c 100644 --- a/src/apiClient/productionClient.ts +++ b/src/apiClient/productionClient.ts @@ -1,6 +1,6 @@ import axios from "axios"; -import { ethers } from "ethers"; import AbstractApiClient from "./abstractClient"; +import { BigNumber, parseEther } from "../utils"; import { CoingeckoDataReturnType, SuggestedFeeReturnType, @@ -27,14 +27,13 @@ export default class ProductionApiClient extends AbstractApiClient { }, }); const result = response.data; - const price = - baseCurrency === "usd" ? ethers.utils.parseEther(String(result.price)) : ethers.BigNumber.from(result.price); + const price = baseCurrency === "usd" ? parseEther(String(result.price)) : BigNumber.from(result.price); return { price, }; } public async getSuggestedFees( - amount: ethers.BigNumber, + amount: BigNumber, originToken: string, toChainid: number, fromChainid: number @@ -49,19 +48,19 @@ export default class ProductionApiClient extends AbstractApiClient { }, }); const result = response.data; - const relayFeePct = ethers.BigNumber.from(result["relayFeePct"]); - const relayFeeTotal = ethers.BigNumber.from(result["relayFeeTotal"]); + const relayFeePct = BigNumber.from(result["relayFeePct"]); + const relayFeeTotal = BigNumber.from(result["relayFeeTotal"]); - const capitalFeePct = ethers.BigNumber.from(result["capitalFeePct"]); - const capitalFeeTotal = ethers.BigNumber.from(result["capitalFeeTotal"]); + const capitalFeePct = BigNumber.from(result["capitalFeePct"]); + const capitalFeeTotal = BigNumber.from(result["capitalFeeTotal"]); - const relayGasFeePct = ethers.BigNumber.from(result["relayGasFeePct"]); - const relayGasFeeTotal = ethers.BigNumber.from(result["relayGasFeeTotal"]); + const relayGasFeePct = BigNumber.from(result["relayGasFeePct"]); + const relayGasFeeTotal = BigNumber.from(result["relayGasFeeTotal"]); const isAmountTooLow = result["isAmountTooLow"]; - const quoteTimestamp = ethers.BigNumber.from(result["timestamp"]); - const quoteBlock = ethers.BigNumber.from(result["quoteBlock"]); + const quoteTimestamp = BigNumber.from(result["timestamp"]); + const quoteBlock = BigNumber.from(result["quoteBlock"]); return { relayerFee: { diff --git a/src/apiClient/types.ts b/src/apiClient/types.ts index ce5b888a..f7d9a5e4 100644 --- a/src/apiClient/types.ts +++ b/src/apiClient/types.ts @@ -1,25 +1,25 @@ -import { ethers } from "ethers"; +import { BigNumber } from "../utils"; -export type CoingeckoDataReturnType = { price: ethers.BigNumber }; +export type CoingeckoDataReturnType = { price: BigNumber }; export type Fee = { - total: ethers.BigNumber; - pct: ethers.BigNumber; + total: BigNumber; + pct: BigNumber; }; export type SuggestedFeeReturnType = { relayerFee: Fee; relayerGasFee: Fee; relayerCapitalFee: Fee; isAmountTooLow: boolean; - quoteTimestamp: ethers.BigNumber; - quoteBlock: ethers.BigNumber; + quoteTimestamp: BigNumber; + quoteBlock: BigNumber; }; export type BridgeLimitsReturnType = { - minDeposit: ethers.BigNumber; - maxDeposit: ethers.BigNumber; - maxDepositInstant: ethers.BigNumber; - maxDepositShortDelay: ethers.BigNumber; + minDeposit: BigNumber; + maxDeposit: BigNumber; + maxDepositInstant: BigNumber; + maxDepositShortDelay: BigNumber; }; export type SpecificRewardType = { diff --git a/src/caching/Arweave/ArweaveClient.ts b/src/caching/Arweave/ArweaveClient.ts index 33efa21b..e0b69902 100644 --- a/src/caching/Arweave/ArweaveClient.ts +++ b/src/caching/Arweave/ArweaveClient.ts @@ -1,11 +1,10 @@ import Arweave from "arweave"; import { JWKInterface } from "arweave/node/lib/wallet"; import axios from "axios"; -import { BigNumber, ethers } from "ethers"; import { Struct, create } from "superstruct"; import winston from "winston"; import { ARWEAVE_TAG_APP_NAME, ARWEAVE_TAG_APP_VERSION, DEFAULT_ARWEAVE_STORAGE_ADDRESS } from "../../constants"; -import { isDefined, jsonReplacerWithBigNumbers, toBN } from "../../utils"; +import { BigNumber, isDefined, jsonReplacerWithBigNumbers, toBN } from "../../utils"; export class ArweaveClient { private client: Arweave; @@ -230,14 +229,14 @@ export class ArweaveClient { * The balance of the signer * @returns The balance of the signer in winston units */ - async getBalance(): Promise { + async getBalance(): Promise { const address = await this.getAddress(); const balanceInFloat = await this.client.wallets.getBalance(address); // Sometimes the balance is returned in scientific notation, so we need to // convert it to a BigNumber if (balanceInFloat.includes("e")) { const [balance, exponent] = balanceInFloat.split("e"); - const resultingBN = ethers.BigNumber.from(balance).mul(toBN(10).pow(exponent.replace("+", ""))); + const resultingBN = BigNumber.from(balance).mul(toBN(10).pow(exponent.replace("+", ""))); return BigNumber.from(resultingBN.toString()); } else { return BigNumber.from(balanceInFloat); diff --git a/src/clients/BundleDataClient/BundleDataClient.ts b/src/clients/BundleDataClient/BundleDataClient.ts index 5a62d49a..f825c1c2 100644 --- a/src/clients/BundleDataClient/BundleDataClient.ts +++ b/src/clients/BundleDataClient/BundleDataClient.ts @@ -17,6 +17,7 @@ import { } from "../../interfaces"; import { AcrossConfigStoreClient, SpokePoolClient } from ".."; import { + BigNumber, bnZero, queryHistoricalDepositForFill, assign, @@ -31,7 +32,6 @@ import { mapAsync, bnUint32Max, } from "../../utils"; -import { BigNumber } from "ethers"; import winston from "winston"; import { _buildPoolRebalanceRoot, diff --git a/src/clients/BundleDataClient/utils/PoolRebalanceUtils.ts b/src/clients/BundleDataClient/utils/PoolRebalanceUtils.ts index 01c6cbb4..dd5d3202 100644 --- a/src/clients/BundleDataClient/utils/PoolRebalanceUtils.ts +++ b/src/clients/BundleDataClient/utils/PoolRebalanceUtils.ts @@ -1,8 +1,7 @@ import { MerkleTree } from "@across-protocol/contracts/dist/utils/MerkleTree"; import { RunningBalances, PoolRebalanceLeaf, Clients, SpokePoolTargetBalance } from "../../../interfaces"; import { SpokePoolClient } from "../../SpokePoolClient"; -import { BigNumber } from "ethers"; -import { bnZero, compareAddresses } from "../../../utils"; +import { BigNumber, bnZero, compareAddresses } from "../../../utils"; import { HubPoolClient } from "../../HubPoolClient"; import { V3DepositWithBlock } from "./shims"; import { AcrossConfigStoreClient } from "../../AcrossConfigStoreClient"; diff --git a/src/clients/BundleDataClient/utils/SuperstructUtils.ts b/src/clients/BundleDataClient/utils/SuperstructUtils.ts index 6f0b69c4..3edf6b9a 100644 --- a/src/clients/BundleDataClient/utils/SuperstructUtils.ts +++ b/src/clients/BundleDataClient/utils/SuperstructUtils.ts @@ -11,7 +11,7 @@ import { boolean, defaulted, } from "superstruct"; -import { BigNumber } from "ethers"; +import { BigNumber } from "../../../utils"; const PositiveIntegerStringSS = pattern(string(), /\d+/); const Web3AddressSS = pattern(string(), /^0x[a-fA-F0-9]{40}$/); diff --git a/src/clients/HubPoolClient.ts b/src/clients/HubPoolClient.ts index 4c2e3eca..09888aca 100644 --- a/src/clients/HubPoolClient.ts +++ b/src/clients/HubPoolClient.ts @@ -1,5 +1,5 @@ import assert from "assert"; -import { BigNumber, Contract, Event, EventFilter } from "ethers"; +import { Contract, Event, EventFilter } from "ethers"; import _ from "lodash"; import winston from "winston"; import { DEFAULT_CACHING_SAFE_LAG, DEFAULT_CACHING_TTL } from "../constants"; @@ -22,6 +22,7 @@ import { } from "../interfaces"; import * as lpFeeCalculator from "../lpFeeCalculator"; import { + BigNumber, BlockFinder, bnZero, dedupArray, diff --git a/src/clients/SpokePoolClient.ts b/src/clients/SpokePoolClient.ts index 5bccb3a5..4d9c3882 100644 --- a/src/clients/SpokePoolClient.ts +++ b/src/clients/SpokePoolClient.ts @@ -1,7 +1,8 @@ -import { BigNumber, Contract, Event, EventFilter } from "ethers"; +import { Contract, Event, EventFilter } from "ethers"; import winston from "winston"; import { AnyObject, + BigNumber, bnZero, DefaultLogLevels, EventSearchConfig, diff --git a/src/clients/mocks/MockHubPoolClient.ts b/src/clients/mocks/MockHubPoolClient.ts index ca35d307..06f7f8a3 100644 --- a/src/clients/mocks/MockHubPoolClient.ts +++ b/src/clients/mocks/MockHubPoolClient.ts @@ -1,6 +1,6 @@ import winston from "winston"; -import { BigNumber, Contract, Event } from "ethers"; -import { randomAddress, assign, bnZero } from "../../utils"; +import { Contract, Event } from "ethers"; +import { BigNumber, randomAddress, assign, bnZero } from "../../utils"; import { L1Token, PendingRootBundle, RealizedLpFee } from "../../interfaces"; import { AcrossConfigStoreClient as ConfigStoreClient } from "../AcrossConfigStoreClient"; import { HubPoolClient, HubPoolUpdate, LpFeeRequest } from "../HubPoolClient"; diff --git a/src/clients/mocks/MockSpokePoolClient.ts b/src/clients/mocks/MockSpokePoolClient.ts index 4bfd4a73..d92e5f6a 100644 --- a/src/clients/mocks/MockSpokePoolClient.ts +++ b/src/clients/mocks/MockSpokePoolClient.ts @@ -1,5 +1,5 @@ import assert from "assert"; -import { BigNumber, Contract, Event, providers } from "ethers"; +import { Contract, Event, providers } from "ethers"; import { random } from "lodash"; import winston from "winston"; import { ZERO_ADDRESS } from "../../constants"; @@ -15,7 +15,7 @@ import { SlowFillLeaf, SpeedUp, } from "../../interfaces"; -import { bnZero, toBN, toBNWei, forEachAsync, getCurrentTime, randomAddress } from "../../utils"; +import { BigNumber, bnZero, toBN, toBNWei, forEachAsync, getCurrentTime, randomAddress } from "../../utils"; import { SpokePoolClient, SpokePoolUpdate } from "../SpokePoolClient"; import { HubPoolClient } from "../HubPoolClient"; import { EventManager, EventOverrides, getEventManager } from "./MockEvents"; diff --git a/src/constants.ts b/src/constants.ts index 175ae427..b377f3c8 100644 --- a/src/constants.ts +++ b/src/constants.ts @@ -1,4 +1,4 @@ -import { constants as ethersConstants, BigNumber, utils } from "ethers"; +import { constants as ethersConstants } from "ethers"; import { TOKEN_SYMBOLS_MAP } from "@across-protocol/constants"; export { @@ -44,9 +44,6 @@ export const PROTOCOL_DEFAULT_CHAIN_ID_INDICES = [1, 10, 137, 288, 42161]; export const DEFAULT_CACHING_TTL = 60 * 60 * 24 * 7 * 2; // 2 Weeks export const DEFAULT_CACHING_SAFE_LAG = 60 * 60; // 1 hour -export const UBA_BOUNDS_RANGE_MAX = BigNumber.from(String(Number.MAX_SAFE_INTEGER)).mul(utils.parseEther("1.0")); -export const UBA_BOUNDS_RANGE_MIN = UBA_BOUNDS_RANGE_MAX.mul(-1); - export const DEFAULT_SIMULATED_RELAYER_ADDRESS = "0x07aE8551Be970cB1cCa11Dd7a11F47Ae82e70E67"; export const DEFAULT_SIMULATED_RELAYER_ADDRESS_TEST = "0x9A8f92a830A5cB89a3816e3D267CB7791c16b04D"; // Görli, ... diff --git a/src/contracts/utils.ts b/src/contracts/utils.ts index 4ea1f547..daef3318 100644 --- a/src/contracts/utils.ts +++ b/src/contracts/utils.ts @@ -1,6 +1,6 @@ import assert from "assert"; -import { BigNumber, BigNumberish, Event } from "ethers"; -import { isDefined } from "../utils"; +import { Event } from "ethers"; +import { BigNumber, BigNumberish, isDefined } from "../utils"; /** * @dev Originally imported from @uma/sdk. diff --git a/src/gasPriceOracle/adapters/arbitrum.ts b/src/gasPriceOracle/adapters/arbitrum.ts index 35f29919..88d38f66 100644 --- a/src/gasPriceOracle/adapters/arbitrum.ts +++ b/src/gasPriceOracle/adapters/arbitrum.ts @@ -1,14 +1,15 @@ -import { providers, utils as ethersUtils } from "ethers"; -import { bnOne } from "../../utils"; +import { providers } from "ethers"; +import { BigNumber, bnOne, parseUnits } from "../../utils"; import { GasPriceEstimate } from "../types"; import * as ethereum from "./ethereum"; -const DEFAULT_PRIORITY_FEE = ethersUtils.parseUnits("1.5", 9); +let DEFAULT_PRIORITY_FEE: BigNumber | undefined = undefined; // Arbitrum Nitro implements EIP-1559 pricing, but the priority fee is always refunded to the caller. Further, // ethers typically hardcodes the priority fee to 1.5 Gwei. So, confirm that the priority fee supplied was 1.5 // Gwei, and then drop it to 1 Wei. Reference: https://developer.arbitrum.io/faqs/gas-faqs#q-priority export async function eip1559(provider: providers.Provider, chainId: number): Promise { + DEFAULT_PRIORITY_FEE ??= parseUnits("1.5", 9); const { maxFeePerGas: _maxFeePerGas, maxPriorityFeePerGas } = await ethereum.eip1559(provider, chainId); // If this throws, ethers default behaviour has changed, or Arbitrum RPCs are returning something more sensible. diff --git a/src/gasPriceOracle/adapters/ethereum.ts b/src/gasPriceOracle/adapters/ethereum.ts index 5d22c68c..06eb67ca 100644 --- a/src/gasPriceOracle/adapters/ethereum.ts +++ b/src/gasPriceOracle/adapters/ethereum.ts @@ -1,5 +1,5 @@ -import { BigNumber, providers } from "ethers"; -import { bnZero } from "../../utils"; +import { providers } from "ethers"; +import { BigNumber, bnZero } from "../../utils"; import { GasPriceEstimate } from "../types"; import { gasPriceError } from "../util"; diff --git a/src/gasPriceOracle/adapters/polygon.ts b/src/gasPriceOracle/adapters/polygon.ts index 0f53e440..fd95e498 100644 --- a/src/gasPriceOracle/adapters/polygon.ts +++ b/src/gasPriceOracle/adapters/polygon.ts @@ -1,6 +1,6 @@ -import { providers, utils as ethersUtils } from "ethers"; +import { providers } from "ethers"; import { BaseHTTPAdapter, BaseHTTPAdapterArgs } from "../../priceClient/adapters/baseAdapter"; -import { bnZero, isDefined } from "../../utils"; +import { bnZero, isDefined, parseUnits } from "../../utils"; import { CHAIN_IDs } from "../../constants"; import { GasPriceEstimate } from "../types"; import { gasPriceError } from "../util"; @@ -50,12 +50,12 @@ class PolygonGasStation extends BaseHTTPAdapter { [gasPrice.maxFee, gasPrice.maxPriorityFee].forEach((gasPrice) => { if (Number(gasPrice) < 0) { - gasPriceError("getFeeData()", this.chainId, ethersUtils.parseUnits(gasPrice.toString(), 9)); + gasPriceError("getFeeData()", this.chainId, parseUnits(gasPrice.toString(), 9)); } }); - const maxPriorityFeePerGas = ethersUtils.parseUnits(gasPrice.maxPriorityFee.toString(), 9); - const maxFeePerGas = ethersUtils.parseUnits(gasPrice.maxFee.toString(), 9); + const maxPriorityFeePerGas = parseUnits(gasPrice.maxPriorityFee.toString(), 9); + const maxFeePerGas = parseUnits(gasPrice.maxFee.toString(), 9); return { maxPriorityFeePerGas, maxFeePerGas }; } diff --git a/src/gasPriceOracle/types.ts b/src/gasPriceOracle/types.ts index deb51233..3385eb6c 100644 --- a/src/gasPriceOracle/types.ts +++ b/src/gasPriceOracle/types.ts @@ -1,4 +1,5 @@ -import { BigNumber, providers } from "ethers"; +import { providers } from "ethers"; +import { BigNumber } from "../utils"; export type GasPriceEstimate = { maxFeePerGas: BigNumber; diff --git a/src/gasPriceOracle/util.ts b/src/gasPriceOracle/util.ts index 661b9a22..debea4c6 100644 --- a/src/gasPriceOracle/util.ts +++ b/src/gasPriceOracle/util.ts @@ -1,4 +1,5 @@ -import { BigNumber, providers } from "ethers"; +import { providers } from "ethers"; +import { BigNumber } from "../utils"; export function gasPriceError(method: string, chainId: number, data: providers.FeeData | BigNumber): void { throw new Error(`Malformed ${method} response on chain ID ${chainId} (${JSON.stringify(data)})`); diff --git a/src/interfaces/Bridge.ts b/src/interfaces/Bridge.ts index 89909960..a29305a0 100644 --- a/src/interfaces/Bridge.ts +++ b/src/interfaces/Bridge.ts @@ -1,4 +1,4 @@ -import { BigNumber } from "ethers"; +import { BigNumber } from "../utils"; export interface OutstandingTransfers { [address: string]: { diff --git a/src/interfaces/BundleData.ts b/src/interfaces/BundleData.ts index ff160128..9e98908c 100644 --- a/src/interfaces/BundleData.ts +++ b/src/interfaces/BundleData.ts @@ -1,8 +1,9 @@ -import { BigNumber, Signer } from "ethers"; +import { Signer } from "ethers"; import { DepositWithBlock, FillWithBlock, Refund } from "./SpokePool"; import { HubPoolClient } from "../clients/HubPoolClient"; import { AcrossConfigStoreClient } from "../clients"; import { ArweaveClient } from "../caching"; +import { BigNumber } from "../utils"; export type ExpiredDepositsToRefundV3 = { [originChainId: number]: { diff --git a/src/interfaces/Common.ts b/src/interfaces/Common.ts index 2a693135..0fad1ab2 100644 --- a/src/interfaces/Common.ts +++ b/src/interfaces/Common.ts @@ -1,4 +1,4 @@ -import { BigNumber } from "ethers"; +import { BigNumber } from "../utils"; export interface SortableEvent { blockNumber: number; diff --git a/src/interfaces/ConfigStore.ts b/src/interfaces/ConfigStore.ts index b55bb59e..0be6c619 100644 --- a/src/interfaces/ConfigStore.ts +++ b/src/interfaces/ConfigStore.ts @@ -1,5 +1,5 @@ -import { BigNumber } from "ethers"; import { RateModelDictionary } from "../lpFeeCalculator/rateModel"; +import { BigNumber } from "../utils"; import { SortableEvent } from "./Common"; export interface ParsedTokenConfig { diff --git a/src/interfaces/HubPool.ts b/src/interfaces/HubPool.ts index 4e66c0ea..c559b1a7 100644 --- a/src/interfaces/HubPool.ts +++ b/src/interfaces/HubPool.ts @@ -1,4 +1,4 @@ -import { BigNumber } from "ethers"; +import { BigNumber } from "../utils"; import { SortableEvent } from "./Common"; export interface PoolRebalanceLeaf { diff --git a/src/interfaces/SpokePool.ts b/src/interfaces/SpokePool.ts index 38b0af70..4058f71e 100644 --- a/src/interfaces/SpokePool.ts +++ b/src/interfaces/SpokePool.ts @@ -1,7 +1,7 @@ -import { BigNumber } from "ethers"; import { SortableEvent } from "./Common"; import { FilledRelayEvent, FilledV3RelayEvent, FundsDepositedEvent, V3FundsDepositedEvent } from "../typechain"; import { SpokePoolClient } from "../clients"; +import { BigNumber } from "../utils"; import { RelayerRefundLeaf } from "./HubPool"; export type { FilledRelayEvent, FilledV3RelayEvent, FundsDepositedEvent, V3FundsDepositedEvent }; diff --git a/src/pool/poolClient.ts b/src/pool/poolClient.ts index bd516f06..955ab294 100644 --- a/src/pool/poolClient.ts +++ b/src/pool/poolClient.ts @@ -1,7 +1,16 @@ import assert from "assert"; import * as uma from "@uma/sdk"; -import { toBNWei, fixedPointAdjustment, calcPeriodicCompoundInterest, calcApr, BigNumberish, fromWei } from "../utils"; -import { ethers, Signer, BigNumber } from "ethers"; +import { + bnZero, + toBNWei, + fixedPointAdjustment, + calcPeriodicCompoundInterest, + calcApr, + BigNumber, + BigNumberish, + fromWei, +} from "../utils"; +import { ethers, Signer } from "ethers"; import type { Overrides } from "@ethersproject/contracts"; import { TransactionRequest, TransactionReceipt, Log } from "@ethersproject/abstract-provider"; import { Provider, Block } from "@ethersproject/providers"; @@ -256,10 +265,10 @@ class UserState { if (endBlock <= this.startBlock) return []; const { userAddress } = this; const events: TypedEvent< - [string, string, uma.oracle.types.ethers.BigNumber] & { + [string, string, BigNumber] & { from: string; to: string; - value: uma.oracle.types.ethers.BigNumber; + value: BigNumber; } >[] = ( await Promise.all([ @@ -352,9 +361,9 @@ function joinUserState( poolState: Pool, tokenEventState: hubPool.TokenEventState, userState: Awaited>, - transferValue: BigNumber = ethers.constants.Zero, - cumulativeStakeBalance: BigNumber = ethers.constants.Zero, - cumulativeStakeClaimBalance: BigNumber = ethers.constants.Zero + transferValue = bnZero, + cumulativeStakeBalance = bnZero, + cumulativeStakeClaimBalance = bnZero ): User { const positionValue = BigNumber.from(poolState.exchangeRateCurrent) .mul(userState.balanceOf.add(cumulativeStakeBalance)) @@ -534,7 +543,7 @@ export class Client { ) ) ) - ).reduce((prev, acc) => acc.add(prev), ethers.constants.Zero); + ).reduce((prev, acc) => acc.add(prev), bnZero); // Get the cumulative balance of the user from the accelerating distributor contract. const { cumulativeBalance } = await acceleratingDistributorContract.getUserStake(lpToken, userState.address); @@ -578,7 +587,7 @@ export class Client { } // we make sure to filter out any transfers where to/from is the same user return result; - }, ethers.constants.Zero); + }, bnZero); } private getOrCreateTransactionManager(signer: Signer, address: string) { if (this.transactionManagers[address]) return this.transactionManagers[address]; @@ -744,7 +753,7 @@ export class Client { const { address: userAddress } = userState; const transferValue = this.config.hasArchive ? await this.calculateLpTransferValue(l1TokenAddress, userState) - : ethers.constants.Zero; + : bnZero; const stakeData = await this.resolveStakingData(lpToken, l1TokenAddress, userState); const tokenEventState = poolEventState[l1TokenAddress]; const newUserState = this.setUserState( diff --git a/src/relayFeeCalculator/relayFeeCalculator.ts b/src/relayFeeCalculator/relayFeeCalculator.ts index 135b35e8..4d491be3 100644 --- a/src/relayFeeCalculator/relayFeeCalculator.ts +++ b/src/relayFeeCalculator/relayFeeCalculator.ts @@ -1,8 +1,8 @@ import assert from "assert"; -import { BigNumber } from "ethers"; import { DEFAULT_SIMULATED_RELAYER_ADDRESS, TOKEN_SYMBOLS_MAP } from "../constants"; import { Deposit } from "../interfaces"; import { + BigNumber, BigNumberish, MAX_BIG_INT, TransactionCostEstimate, diff --git a/src/utils/AddressUtils.ts b/src/utils/AddressUtils.ts index b8a5af99..383aaf76 100644 --- a/src/utils/AddressUtils.ts +++ b/src/utils/AddressUtils.ts @@ -1,4 +1,5 @@ -import { BigNumber, providers, utils } from "ethers"; +import { providers, utils } from "ethers"; +import { BigNumber } from "./BigNumberUtils"; /** * Checks if a contract is deployed at the given address diff --git a/src/utils/BigNumberUtils.ts b/src/utils/BigNumberUtils.ts index 832c6a60..27476328 100644 --- a/src/utils/BigNumberUtils.ts +++ b/src/utils/BigNumberUtils.ts @@ -4,14 +4,20 @@ * @author Across Protocol */ -import { ethers, BigNumber } from "ethers"; +import { utils as ethersUtils } from "ethers"; -export type BigNumberish = ethers.BigNumberish; -export type BN = ethers.BigNumber; +// eslint-disable-next-line no-restricted-imports +import { BigNumber, BigNumberish } from "@ethersproject/bignumber"; -export const { Zero: bnZero, One: bnOne, MaxUint256: bnUint256Max } = ethers.constants; +// eslint-disable-next-line no-restricted-imports +export * from "@ethersproject/bignumber"; +export type BN = BigNumber; +export const { formatEther, formatUnits, parseEther, parseUnits } = ethersUtils; +export const bnZero = BigNumber.from("0"); +export const bnOne = BigNumber.from("1"); export const bnUint32Max = BigNumber.from("0xffffffff"); +export const bnUint256Max = BigNumber.from("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"); /** * Converts a stringified number into a BigNumber with 18 decimal places. @@ -19,7 +25,7 @@ export const bnUint32Max = BigNumber.from("0xffffffff"); * @returns The parsed BigNumber. */ export function toWei(num: BigNumberish): BN { - return ethers.utils.parseEther(num.toString()); + return ethersUtils.parseEther(num.toString()); } /** @@ -28,7 +34,7 @@ export function toWei(num: BigNumberish): BN { * @returns The parsed BigNumber. */ export function toGWei(num: BigNumberish): BN { - return ethers.utils.parseUnits(num.toString(), 9); + return ethersUtils.parseUnits(num.toString(), 9); } /** diff --git a/src/utils/FormattingUtils.ts b/src/utils/FormattingUtils.ts index 5b6ee7fa..b42a1f4d 100644 --- a/src/utils/FormattingUtils.ts +++ b/src/utils/FormattingUtils.ts @@ -1,5 +1,5 @@ -import { ethers } from "ethers"; -import { BN, toBN } from "./BigNumberUtils"; +import { utils as ethersUtils } from "ethers"; +import { formatUnits, BigNumber as ethersBigNumber, BN, parseUnits, toBN } from "./BigNumberUtils"; import { fromWei } from "./common"; import assert from "assert"; import { BigNumber } from "bignumber.js"; @@ -93,7 +93,7 @@ export function createShortHexString(hex: string, maxLength = 8, delimiter = ".. * @returns The hex string. */ export function utf8ToHex(input: string): string { - return ethers.utils.formatBytes32String(input); + return ethersUtils.formatBytes32String(input); } /** @@ -102,7 +102,7 @@ export function utf8ToHex(input: string): string { * @returns The utf8 string. */ export function hexToUtf8(input: string): string { - return ethers.utils.toUtf8String(input); + return ethersUtils.toUtf8String(input); } /** @@ -112,7 +112,7 @@ export function hexToUtf8(input: string): string { * @returns The 32-byte hexadecimal string representation of the input. */ export function bnToHex(input: BN): string { - return ethers.utils.hexZeroPad(ethers.utils.hexlify(toBN(input)), 32); + return ethersUtils.hexZeroPad(ethersUtils.hexlify(toBN(input)), 32); } /** @@ -172,8 +172,8 @@ export const ConvertDecimals = (fromDecimals: number, toDecimals: number): ((amo * @param numericString The numeric string to convert * @returns The winston representation of the numeric string as a BigNumber */ -export function parseWinston(numericString: string): ethers.BigNumber { - return ethers.utils.parseUnits(numericString, 12); +export function parseWinston(numericString: string): ethersBigNumber { + return parseUnits(numericString, 12); } /** @@ -181,6 +181,6 @@ export function parseWinston(numericString: string): ethers.BigNumber { * @param winstonValue The winston value to convert * @returns The numeric string representation of the winston value */ -export function formatWinston(winstonValue: ethers.BigNumber): string { - return ethers.utils.formatUnits(winstonValue, 12); +export function formatWinston(winstonValue: ethersBigNumber): string { + return formatUnits(winstonValue, 12); } diff --git a/src/utils/JSONUtils.ts b/src/utils/JSONUtils.ts index 62dd5e79..407d582e 100644 --- a/src/utils/JSONUtils.ts +++ b/src/utils/JSONUtils.ts @@ -1,4 +1,4 @@ -import { BigNumber } from "ethers"; +import { BigNumber } from "./BigNumberUtils"; import { isDefined } from "./TypeGuards"; /** diff --git a/src/utils/Multicall.ts b/src/utils/Multicall.ts index 5ca86f9b..11f588b6 100644 --- a/src/utils/Multicall.ts +++ b/src/utils/Multicall.ts @@ -1,5 +1,6 @@ -import { BigNumber, Contract, providers, Signer, utils as ethersUtils } from "ethers"; +import { Contract, providers, Signer, utils as ethersUtils } from "ethers"; import { CHAIN_IDs } from "@across-protocol/constants"; +import { BigNumber } from "./BigNumberUtils"; import { Multicall3, Multicall3__factory } from "./abi/typechain"; type Provider = providers.Provider; diff --git a/src/utils/SpokeUtils.ts b/src/utils/SpokeUtils.ts index 554b777f..cca38583 100644 --- a/src/utils/SpokeUtils.ts +++ b/src/utils/SpokeUtils.ts @@ -1,10 +1,10 @@ import assert from "assert"; -import { BigNumber, BytesLike, Contract, PopulatedTransaction, providers, utils as ethersUtils } from "ethers"; +import { BytesLike, Contract, PopulatedTransaction, providers, utils as ethersUtils } from "ethers"; import { CHAIN_IDs, ZERO_ADDRESS } from "../constants"; import { Deposit, Fill, FillStatus, RelayData, SlowFillRequest } from "../interfaces"; import { SpokePoolClient } from "../clients"; import { chunk } from "./ArrayUtils"; -import { toBN } from "./BigNumberUtils"; +import { BigNumber, toBN } from "./BigNumberUtils"; import { isDefined } from "./TypeGuards"; import { getNetworkName } from "./NetworkUtils"; diff --git a/src/utils/TokenUtils.ts b/src/utils/TokenUtils.ts index b81428f1..5391a73e 100644 --- a/src/utils/TokenUtils.ts +++ b/src/utils/TokenUtils.ts @@ -1,8 +1,9 @@ import { BlockTag } from "@ethersproject/abstract-provider"; -import { BigNumber, Contract, providers, Signer } from "ethers"; +import { Contract, providers, Signer } from "ethers"; import * as constants from "../constants"; import { L1Token } from "../interfaces"; import { ERC20__factory } from "../typechain"; +import { BigNumber } from "./BigNumberUtils"; import { getNetworkName } from "./NetworkUtils"; import { isDefined } from "./TypeGuards"; import { compareAddressesSimple } from "./AddressUtils"; diff --git a/src/utils/ValidatorUtils.ts b/src/utils/ValidatorUtils.ts index d50ad9b8..c1a56e6d 100644 --- a/src/utils/ValidatorUtils.ts +++ b/src/utils/ValidatorUtils.ts @@ -1,10 +1,11 @@ -import { BigNumber, ethers } from "ethers"; +import { utils as ethersUtils } from "ethers"; import { object, min as Min, define, optional, string, integer, boolean } from "superstruct"; import { DepositWithBlock } from "../interfaces"; +import { BigNumber } from "../utils"; -const AddressValidator = define("AddressValidator", (v) => ethers.utils.isAddress(String(v))); -const HexValidator = define("HexValidator", (v) => ethers.utils.isHexString(String(v))); -const BigNumberValidator = define("BigNumberValidator", (v) => ethers.BigNumber.isBigNumber(v)); +const AddressValidator = define("AddressValidator", (v) => ethersUtils.isAddress(String(v))); +const HexValidator = define("HexValidator", (v) => ethersUtils.isHexString(String(v))); +const BigNumberValidator = define("BigNumberValidator", (v) => BigNumber.isBigNumber(v)); const V3DepositSchema = object({ depositId: Min(integer(), 0), diff --git a/src/utils/common.ts b/src/utils/common.ts index 9ed49751..68546b38 100644 --- a/src/utils/common.ts +++ b/src/utils/common.ts @@ -2,10 +2,10 @@ import { L2Provider } from "@eth-optimism/sdk/dist/interfaces/l2-provider"; import { isL2Provider as isOptimismL2Provider } from "@eth-optimism/sdk/dist/l2-provider"; import assert from "assert"; import Decimal from "decimal.js"; -import { BigNumber, ethers, PopulatedTransaction, providers, VoidSigner } from "ethers"; +import { ethers, PopulatedTransaction, providers, VoidSigner } from "ethers"; import { getGasPriceEstimate } from "../gasPriceOracle"; import { TypedMessage } from "../interfaces/TypedData"; -import { BigNumberish, BN, toBN } from "./BigNumberUtils"; +import { BigNumber, BigNumberish, BN, formatUnits, parseUnits, toBN } from "./BigNumberUtils"; import { ConvertDecimals } from "./FormattingUtils"; import { chainIsOPStack } from "./NetworkUtils"; @@ -20,7 +20,7 @@ export const MAX_BIG_INT = BigNumber.from(Number.MAX_SAFE_INTEGER.toString()); * @param {number} decimals * @returns {BN} */ -export const toBNWei = (num: BigNumberish, decimals?: number): BN => ethers.utils.parseUnits(num.toString(), decimals); +export const toBNWei = (num: BigNumberish, decimals?: number): BN => parseUnits(num.toString(), decimals); /** * fromWei. @@ -29,8 +29,7 @@ export const toBNWei = (num: BigNumberish, decimals?: number): BN => ethers.util * @param {number} decimals * @returns {string} */ -export const fromWei = (num: BigNumberish, decimals?: number): string => - ethers.utils.formatUnits(num.toString(), decimals); +export const fromWei = (num: BigNumberish, decimals?: number): string => formatUnits(num.toString(), decimals); /** * min. diff --git a/test/BigNumberUtils.test.ts b/test/BigNumberUtils.test.ts index dd7c6531..3835ecad 100644 --- a/test/BigNumberUtils.test.ts +++ b/test/BigNumberUtils.test.ts @@ -1,12 +1,11 @@ -import { ethers } from "ethers"; -import { toWei, toGWei, toBN } from "../src/utils/BigNumberUtils"; +import { BigNumber, parseEther, parseUnits, toWei, toGWei, toBN } from "../src/utils/BigNumberUtils"; import { expect } from "./utils"; describe("BigNumberUtils", () => { describe("toWei", () => { it("should convert a stringified number to a BigNumber with 18 decimal places", () => { const num = "123.456"; - const expected = ethers.utils.parseEther(num); + const expected = parseEther(num); const result = toWei(num); expect(result).to.be.deep.includes(expected); }); @@ -15,7 +14,7 @@ describe("BigNumberUtils", () => { describe("toGWei", () => { it("should convert a stringified number to a BigNumber with 9 decimal places", () => { const num = "123.456"; - const expected = ethers.utils.parseUnits(num, 9); + const expected = parseUnits(num, 9); const result = toGWei(num); expect(result).to.be.deep.includes(expected); }); @@ -24,28 +23,28 @@ describe("BigNumberUtils", () => { describe("toBN", () => { it("should convert a stringified integer to a BigNumber", () => { const num = "123456"; - const expected = ethers.BigNumber.from(num); + const expected = BigNumber.from(num); const result = toBN(num); expect(result).to.be.deep.includes(expected); }); it("should convert a stringified number with decimal places to a BigNumber and round down by default", () => { const num = "123.456"; - const expected = ethers.BigNumber.from("123"); + const expected = BigNumber.from("123"); const result = toBN(num); expect(result).to.be.deep.includes(expected); }); it("should round up if rounding is set to 'ceil'", () => { const num = "123.456"; - const expected = ethers.BigNumber.from("124"); + const expected = BigNumber.from("124"); const result = toBN(num, "ceil"); expect(result).to.be.deep.includes(expected); }); it("should round up if rounding is set to 'round' and the first decimal is greater than or equal to 5", () => { const num = "123.556"; - const expected = ethers.BigNumber.from("124"); + const expected = BigNumber.from("124"); const result = toBN(num, "round"); expect(result).to.be.deep.includes(expected); }); diff --git a/test/poolClient.test.ts b/test/poolClient.test.ts index a4cd3a7d..38970493 100644 --- a/test/poolClient.test.ts +++ b/test/poolClient.test.ts @@ -1,5 +1,5 @@ import * as poolClient from "../src/pool/poolClient"; -import { BigNumber } from "ethers"; +import { BigNumber } from "../src/utils"; import { expect } from "./utils"; describe("poolClient", function () { diff --git a/test/utils/utils.ts b/test/utils/utils.ts index f6505733..7a2c8df3 100644 --- a/test/utils/utils.ts +++ b/test/utils/utils.ts @@ -1,5 +1,5 @@ import * as utils from "@across-protocol/contracts/dist/test-utils"; -import { BigNumber, BigNumberish, Contract, providers } from "ethers"; +import { Contract, providers } from "ethers"; import { AcrossConfigStoreClient as ConfigStoreClient, GLOBAL_CONFIG_STORE_KEYS, @@ -15,6 +15,8 @@ import { V2Fill, } from "../../src/interfaces"; import { + BigNumber, + BigNumberish, bnUint32Max, bnOne, getCurrentTime,