Skip to content

Commit

Permalink
Merge pull request #295 from rainlanguage/2025-01-16-zero-rpc-gas-est…
Browse files Browse the repository at this point in the history
…imate-bug [skip ci]

zero gas estimate bug
  • Loading branch information
rouzwelt authored Jan 17, 2025
2 parents d65b415 + 9c92571 commit 1723a29
Show file tree
Hide file tree
Showing 5 changed files with 37 additions and 11 deletions.
15 changes: 10 additions & 5 deletions src/gas.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
import { ChainId } from "sushi";
import { BigNumber } from "ethers";
import { getQuoteConfig } from "./utils";
import { publicActionsL2 } from "viem/op-stack";
import { encodeFunctionData, multicall3Abi, toHex } from "viem";
import { publicActionsL2, walletActionsL2 } from "viem/op-stack";
import { BotConfig, BundledOrders, OperationState, RawTx, ViemClient } from "./types";
import { ArbitrumNodeInterfaceAbi, ArbitrumNodeInterfaceAddress, OrderbookQuoteAbi } from "./abis";

// default gas price for bsc chain, 1 gwei
export const BSC_DEFAULT_GAS_PRICE = 1_000_000_000n as const;

/**
* Estimates gas cost of the given tx, also takes into account L1 gas cost if the chain is a special L2.
*/
Expand All @@ -29,9 +32,7 @@ export async function estimateGasCost(
};
if (config.isSpecialL2) {
try {
const l1Signer_ = l1Signer
? l1Signer
: signer.extend(walletActionsL2()).extend(publicActionsL2());
const l1Signer_ = l1Signer ? l1Signer : signer.extend(publicActionsL2());
if (typeof l1GasPrice !== "bigint") {
l1GasPrice = (await l1Signer_.getL1BaseFee()) as bigint;
}
Expand Down Expand Up @@ -83,7 +84,11 @@ export async function getGasPrice(config: BotConfig, state: OperationState) {
}
const [gasPriceResult, l1GasPriceResult = undefined] = await Promise.allSettled(promises);
if (gasPriceResult.status === "fulfilled") {
state.gasPrice = (gasPriceResult.value * BigInt(config.gasPriceMultiplier)) / 100n;
let gasPrice = gasPriceResult.value;
if (config.chain.id === ChainId.BSC && gasPrice < BSC_DEFAULT_GAS_PRICE) {
gasPrice = BSC_DEFAULT_GAS_PRICE;
}
state.gasPrice = (gasPrice * BigInt(config.gasPriceMultiplier)) / 100n;
}
if (l1GasPriceResult?.status === "fulfilled") {
state.l1GasPrice = l1GasPriceResult.value;
Expand Down
8 changes: 7 additions & 1 deletion src/modes/interOrderbook.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { orderbookAbi } from "../abis";
import { estimateGasCost } from "../gas";
import { BaseError, PublicClient } from "viem";
import { BigNumber, Contract, ethers } from "ethers";
import { containsNodeError, errorSnapshot } from "../error";
import { getBountyEnsureRainlang, parseRainlang } from "../task";
import { BaseError, ExecutionRevertedError, PublicClient } from "viem";
import { BotConfig, BundledOrders, ViemClient, DryrunResult, SpanAttrs } from "../types";
import {
ONE18,
Expand Down Expand Up @@ -175,6 +175,12 @@ export async function dryrun({
gasLimit = ethers.BigNumber.from(estimation.gas)
.mul(config.gasLimitMultiplier)
.div(100);
if (gasLimit.isZero()) {
throw new ExecutionRevertedError({
message:
"Failed to estimated gas, rpc returned 0 for gasEstimate call without rejection",
});
}
rawtx.gas = gasLimit.toBigInt();
gasCost = gasLimit.mul(gasPrice).add(estimation.l1Cost);
task.evaluable.bytecode = await parseRainlang(
Expand Down
8 changes: 7 additions & 1 deletion src/modes/intraOrderbook.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { orderbookAbi } from "../abis";
import { estimateGasCost } from "../gas";
import { BigNumber, ethers } from "ethers";
import { BaseError, erc20Abi, PublicClient } from "viem";
import { containsNodeError, errorSnapshot } from "../error";
import { getWithdrawEnsureRainlang, parseRainlang } from "../task";
import { BaseError, erc20Abi, ExecutionRevertedError, PublicClient } from "viem";
import { estimateProfit, scale18, withBigintSerializer, extendSpanAttributes } from "../utils";
import {
SpanAttrs,
Expand Down Expand Up @@ -177,6 +177,12 @@ export async function dryrun({
gasLimit = ethers.BigNumber.from(estimation.gas)
.mul(config.gasLimitMultiplier)
.div(100);
if (gasLimit.isZero()) {
throw new ExecutionRevertedError({
message:
"Failed to estimated gas, rpc returned 0 for gasEstimate call without rejection",
});
}
rawtx.gas = gasLimit.toBigInt();
gasCost = gasLimit.mul(gasPrice).add(estimation.l1Cost);
task.evaluable.bytecode = await parseRainlang(
Expand Down
10 changes: 8 additions & 2 deletions src/modes/routeProcessor.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { Token } from "sushi/currency";
import { estimateGasCost } from "../gas";
import { BaseError, PublicClient } from "viem";
import { ChainId, DataFetcher, Router } from "sushi";
import { BigNumber, Contract, ethers } from "ethers";
import { containsNodeError, errorSnapshot } from "../error";
import { getBountyEnsureRainlang, parseRainlang } from "../task";
import { BaseError, ExecutionRevertedError, PublicClient } from "viem";
import { SpanAttrs, BotConfig, ViemClient, DryrunResult, BundledOrders } from "../types";
import {
ONE18,
Expand Down Expand Up @@ -241,6 +241,12 @@ export async function dryrun({
gasLimit = ethers.BigNumber.from(estimation.gas)
.mul(config.gasLimitMultiplier)
.div(100);
if (gasLimit.isZero()) {
throw new ExecutionRevertedError({
message:
"Failed to estimated gas, rpc returned 0 for gasEstimate call without rejection",
});
}
rawtx.gas = gasLimit.toBigInt();
gasCost = gasLimit.mul(gasPrice).add(estimation.l1Cost);
task.evaluable.bytecode = await parseRainlang(
Expand Down Expand Up @@ -492,7 +498,7 @@ export async function findOppWithRetries({
// ie its maxInput is the greatest
const prom = allPromises[i];
if (prom.status === "fulfilled") {
if (!choice || choice.maximumInput!.lt(prom.value.value!.maximumInput!)) {
if (!choice || choice.estimatedProfit.lt(prom.value.value!.estimatedProfit)) {
// record the attributes of the choosing one
for (const attrKey in prom.value.spanAttributes) {
spanAttributes[attrKey] = prom.value.spanAttributes[attrKey];
Expand Down
7 changes: 5 additions & 2 deletions test/gas.test.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { assert } from "chai";
import { ChainId } from "sushi";
import { orderPairObject1 } from "./data";
import { OperationState, ViemClient } from "../src/types";
import { estimateGasCost, getGasPrice, getL1Fee, getQuoteGas, getTxFee } from "../src/gas";
import { ChainId } from "sushi";

describe("Test gas", async function () {
it("should estimate gas correctly for L1 and L2 chains", async function () {
Expand Down Expand Up @@ -80,7 +80,9 @@ describe("Test gas", async function () {

it("should get tx fee", async function () {
// mock config and receipt
const config = {} as any;
const config = {
chain: { id: 137 },
} as any;
const receipt = {
effectiveGasPrice: 10n,
gasUsed: 5n,
Expand All @@ -102,6 +104,7 @@ describe("Test gas", async function () {
const l1GasPrice = 2n;
// mock config and viem client
const config = {
chain: { id: 137 },
isSpecialL2: false,
gasPriceMultiplier: 100n,
viemClient: { getGasPrice: async () => gasPrice },
Expand Down

0 comments on commit 1723a29

Please sign in to comment.