From 0955bb9524ec6d4764df3682108a9af49a273678 Mon Sep 17 00:00:00 2001 From: Shunji Zhan Date: Mon, 4 Dec 2023 13:31:19 +0800 Subject: [PATCH] estimateGas supports blocktag --- packages/eth-providers/src/base-provider.ts | 18 +++++++++++++----- .../src/__tests__/e2e/endpoint.test.ts | 3 +++ .../eth-rpc-adapter/src/__tests__/e2e/utils.ts | 5 +++-- packages/eth-rpc-adapter/src/eip1193-bridge.ts | 4 ++-- packages/eth-rpc-adapter/src/validate.ts | 5 +++++ 5 files changed, 26 insertions(+), 9 deletions(-) diff --git a/packages/eth-providers/src/base-provider.ts b/packages/eth-providers/src/base-provider.ts index 8130aaeb2..e328da215 100644 --- a/packages/eth-providers/src/base-provider.ts +++ b/packages/eth-providers/src/base-provider.ts @@ -928,8 +928,11 @@ export abstract class BaseProvider extends AbstractProvider { * @param transaction The transaction to estimate the gas of * @returns The estimated gas used by this transaction */ - estimateGas = async (transaction: Deferrable): Promise => { - const { usedGas, gasLimit, usedStorage } = await this.estimateResources(transaction); + estimateGas = async ( + transaction: Deferrable, + blockTag?: BlockTag | Promise + ): Promise => { + const { usedGas, gasLimit, usedStorage } = await this.estimateResources(transaction, blockTag); const tx = await resolveProperties(transaction); const data = tx.data?.toString() ?? '0x'; @@ -1098,7 +1101,8 @@ export abstract class BaseProvider extends AbstractProvider { * @returns The estimated resources used by this transaction */ estimateResources = async ( - transaction: Deferrable + transaction: Deferrable, + blockTag?: BlockTag | Promise, ): Promise<{ usedGas: BigNumber; gasLimit: BigNumber; @@ -1116,7 +1120,11 @@ export abstract class BaseProvider extends AbstractProvider { storageLimit: STORAGE_LIMIT, }; - const gasInfo = await this._ethCall(txRequest); + const blockHash = blockTag && blockTag !== 'latest' + ? await this._getBlockHash(blockTag) + : undefined; // if blockTag is latest, avoid explicit blockhash for better performance + + const gasInfo = await this._ethCall(txRequest, blockHash); const usedGas = BigNumber.from(gasInfo.used_gas).toNumber(); const usedStorage = gasInfo.used_storage; @@ -1523,7 +1531,7 @@ export abstract class BaseProvider extends AbstractProvider { switch (blockTag) { case 'pending': { - return logger.throwError('pending tag not implemented', Logger.errors.UNSUPPORTED_OPERATION); + return logger.throwError('pending tag not supported', Logger.errors.UNSUPPORTED_OPERATION); } case 'latest': { return this.safeMode ? this.finalizedBlockHash : this.bestBlockHash; diff --git a/packages/eth-rpc-adapter/src/__tests__/e2e/endpoint.test.ts b/packages/eth-rpc-adapter/src/__tests__/e2e/endpoint.test.ts index 48bff861d..44a66d5e3 100644 --- a/packages/eth-rpc-adapter/src/__tests__/e2e/endpoint.test.ts +++ b/packages/eth-rpc-adapter/src/__tests__/e2e/endpoint.test.ts @@ -1940,6 +1940,9 @@ describe('endpoint', () => { const { gasLimit } = await estimateGas(tx); const bbb = (gasLimit.toNumber() % 100000) / 100; + const { gasLimit: gasLimitWithBlockTag } = await estimateGas(tx, 'latest'); + expect(gasLimitWithBlockTag).to.equal(gasLimit); + // should be passing gasLimit instead of usedGas expect(bbb).to.gt(GAS_MONSTER_GAS_REQUIRED / 30000); diff --git a/packages/eth-rpc-adapter/src/__tests__/e2e/utils.ts b/packages/eth-rpc-adapter/src/__tests__/e2e/utils.ts index 3550f8142..b96a01990 100644 --- a/packages/eth-rpc-adapter/src/__tests__/e2e/utils.ts +++ b/packages/eth-rpc-adapter/src/__tests__/e2e/utils.ts @@ -1,4 +1,5 @@ import { BigNumber, ContractFactory, Signer } from 'ethers'; +import { BlockTagish } from '@acala-network/eth-providers'; import { Log, TransactionRequest } from '@ethersproject/abstract-provider'; import { expect } from 'vitest'; import { hexValue } from '@ethersproject/bytes'; @@ -71,9 +72,9 @@ export const eth_getTransactionByHash_karura = rpcGet('eth_getTransactionByHash' export const eth_getBlockByNumber_karura = rpcGet('eth_getBlockByNumber', KARURA_ETH_RPC_URL); export const eth_getStorageAt_karura = rpcGet('eth_getStorageAt', KARURA_ETH_RPC_URL); -export const estimateGas = async (tx: TransactionRequest) => { +export const estimateGas = async (tx: TransactionRequest, blockTag?: BlockTagish) => { const gasPrice = (await eth_gasPrice([])).data.result; - const res = await eth_estimateGas([{ ...tx, gasPrice }]); + const res = await eth_estimateGas([{ ...tx, gasPrice }, blockTag]); if (res.data.error) { throw new Error(res.data.error.message); } diff --git a/packages/eth-rpc-adapter/src/eip1193-bridge.ts b/packages/eth-rpc-adapter/src/eip1193-bridge.ts index a29c90a36..548328b21 100644 --- a/packages/eth-rpc-adapter/src/eip1193-bridge.ts +++ b/packages/eth-rpc-adapter/src/eip1193-bridge.ts @@ -293,8 +293,8 @@ class Eip1193BridgeImpl { * @returns GAS USED - the amount of gas used. */ async eth_estimateGas(params: any[]): Promise { - validate([{ type: 'transaction' }], params); - const val = await this.#provider.estimateGas(params[0]); + validate([{ type: 'transaction' }, { type: 'block?' }], params); + const val = await this.#provider.estimateGas(params[0], params[1]); return hexValue(val); } diff --git a/packages/eth-rpc-adapter/src/validate.ts b/packages/eth-rpc-adapter/src/validate.ts index a90b1d0d6..2e2d51054 100644 --- a/packages/eth-rpc-adapter/src/validate.ts +++ b/packages/eth-rpc-adapter/src/validate.ts @@ -4,6 +4,7 @@ export type Schema = { type: | 'address' | 'block' + | 'block?' | 'transaction' | 'blockHash' | 'trasactionHash' @@ -148,6 +149,10 @@ export const validate = (schema: Schema, data: unknown[]) => { validateBlock(data[i]); break; } + case 'block?': { + data[i] && validateBlock(data[i]); + break; + } case 'transaction': { validateTransaction(data[i]); break;