-
Notifications
You must be signed in to change notification settings - Fork 14
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(gasPriceOracle): Allow caller to pass in base fee multiplier (#801)
Signed-off-by: nicholaspai <[email protected]> Co-authored-by: Paul <[email protected]>
- Loading branch information
1 parent
a7615d0
commit c183a52
Showing
22 changed files
with
659 additions
and
463 deletions.
There are no files selected for viewing
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,65 +1,96 @@ | ||
import assert from "assert"; | ||
import { providers } from "ethers"; | ||
import { BigNumber, bnZero, getNetworkName } from "../../utils"; | ||
import { BigNumber, bnZero, fixedPointAdjustment, getNetworkName } from "../../utils"; | ||
import { GasPriceEstimate } from "../types"; | ||
import { gasPriceError } from "../util"; | ||
import { GasPriceEstimateOptions } from "../oracle"; | ||
|
||
// TODO: We intend to remove `eip1559Bad()` as an option and make eip1559Raw the only option eventually. The reason | ||
// they both exist currently is because eip1559Raw is new and untested on production so we will slowly roll it out | ||
// by using the convenient environment variable safety guard. | ||
|
||
/** | ||
* @dev If GAS_PRICE_EIP1559_RAW_${chainId}=true, then constructs total fee by adding | ||
* eth_getBlock("pending").baseFee to eth_maxPriorityFeePerGas, otherwise calls the ethers provider's | ||
* getFeeData() method which adds eth_getBlock("latest").baseFee to a hardcoded priority fee of 1.5 gwei. | ||
* @param provider ethers RPC provider instance. | ||
* @param chainId Chain ID of provider instance. | ||
* @returns Promise of gas price estimate object. | ||
*/ | ||
export function eip1559(provider: providers.Provider, chainId: number): Promise<GasPriceEstimate> { | ||
const useRaw = process.env[`GAS_PRICE_EIP1559_RAW_${chainId}`] === "true"; | ||
return useRaw ? eip1559Raw(provider, chainId) : eip1559Bad(provider, chainId); | ||
export function eip1559(provider: providers.Provider, opts: GasPriceEstimateOptions): Promise<GasPriceEstimate> { | ||
const useRaw = process.env[`GAS_PRICE_EIP1559_RAW_${opts.chainId}`] === "true"; | ||
return useRaw | ||
? eip1559Raw(provider, opts.chainId, opts.baseFeeMultiplier) | ||
: eip1559Bad(provider, opts.chainId, opts.baseFeeMultiplier); | ||
} | ||
|
||
/** | ||
* @note Performs direct RPC calls to retrieve the RPC-suggested priority fee for the next block. | ||
* @dev Constructs total fee by adding eth_getBlock("pending").baseFee to eth_maxPriorityFeePerGas | ||
* @param provider ethers RPC provider instance. | ||
* @param chainId Chain ID of the provider instance. | ||
* @returns Promise of gas price estimate object. | ||
*/ | ||
export async function eip1559Raw(provider: providers.Provider, chainId: number): Promise<GasPriceEstimate> { | ||
export async function eip1559Raw( | ||
provider: providers.Provider, | ||
chainId: number, | ||
baseFeeMultiplier: BigNumber | ||
): Promise<GasPriceEstimate> { | ||
const [{ baseFeePerGas }, _maxPriorityFeePerGas] = await Promise.all([ | ||
provider.getBlock("pending"), | ||
(provider as providers.JsonRpcProvider).send("eth_maxPriorityFeePerGas", []), | ||
]); | ||
const maxPriorityFeePerGas = BigNumber.from(_maxPriorityFeePerGas); | ||
assert(BigNumber.isBigNumber(baseFeePerGas), `No baseFeePerGas received on ${getNetworkName(chainId)}`); | ||
|
||
const scaledBaseFee = baseFeePerGas.mul(baseFeeMultiplier).div(fixedPointAdjustment); | ||
return { | ||
maxFeePerGas: maxPriorityFeePerGas.add(baseFeePerGas), | ||
maxFeePerGas: maxPriorityFeePerGas.add(scaledBaseFee), | ||
maxPriorityFeePerGas, | ||
}; | ||
} | ||
|
||
/** | ||
* @note Resolves priority gas pricing poorly, because the priority fee is hardcoded to 1.5 Gwei in ethers v5. | ||
* @notice Returns fee data using provider's getFeeData() method. | ||
* @note Resolves priority gas pricing poorly, because the priority fee is hardcoded to 1.5 Gwei in ethers v5's | ||
* getFeeData() method | ||
* @dev TODO: Remove this function soon. See note above about slowly rolling out eip1559Raw. | ||
* @param provider ethers RPC provider instance. | ||
* @param chainId Chain ID of the provider instance. | ||
* @returns Promise of gas price estimate object. | ||
*/ | ||
export async function eip1559Bad(provider: providers.Provider, chainId: number): Promise<GasPriceEstimate> { | ||
export async function eip1559Bad( | ||
provider: providers.Provider, | ||
chainId: number, | ||
baseFeeMultiplier: BigNumber | ||
): Promise<GasPriceEstimate> { | ||
const feeData = await provider.getFeeData(); | ||
|
||
[feeData.lastBaseFeePerGas, feeData.maxPriorityFeePerGas].forEach((field: BigNumber | null) => { | ||
if (!BigNumber.isBigNumber(field) || field.lt(bnZero)) gasPriceError("getFeeData()", chainId, feeData); | ||
}); | ||
|
||
const maxPriorityFeePerGas = feeData.maxPriorityFeePerGas as BigNumber; | ||
const maxFeePerGas = maxPriorityFeePerGas.add(feeData.lastBaseFeePerGas as BigNumber); | ||
const scaledLastBaseFeePerGas = (feeData.lastBaseFeePerGas as BigNumber) | ||
.mul(baseFeeMultiplier) | ||
.div(fixedPointAdjustment); | ||
const maxFeePerGas = maxPriorityFeePerGas.add(scaledLastBaseFeePerGas); | ||
|
||
return { maxPriorityFeePerGas, maxFeePerGas }; | ||
} | ||
|
||
export async function legacy(provider: providers.Provider, chainId: number): Promise<GasPriceEstimate> { | ||
/** | ||
* @notice Returns result of eth_gasPrice RPC call | ||
* @dev Its recommended to use the eip1559Raw method over this one where possible as it will be more accurate. | ||
* @returns GasPriceEstimate | ||
*/ | ||
export async function legacy(provider: providers.Provider, opts: GasPriceEstimateOptions): Promise<GasPriceEstimate> { | ||
const { chainId, baseFeeMultiplier } = opts; | ||
const gasPrice = await provider.getGasPrice(); | ||
|
||
if (!BigNumber.isBigNumber(gasPrice) || gasPrice.lt(bnZero)) gasPriceError("getGasPrice()", chainId, gasPrice); | ||
|
||
return { | ||
maxFeePerGas: gasPrice, | ||
maxFeePerGas: gasPrice.mul(baseFeeMultiplier).div(fixedPointAdjustment), | ||
maxPriorityFeePerGas: bnZero, | ||
}; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
Oops, something went wrong.