diff --git a/docker-compose.yml b/docker-compose.yml index 22eccd4f5..0e6cc8f41 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -117,7 +117,7 @@ services: # ---------- No Subql Realm ---------- # # ------------------------------------ # mandala-node: - image: ghcr.io/acalanetwork/mandala-node:sha-7ae4bf4 + image: ghcr.io/acalanetwork/mandala-node:sha-06e988b ports: - 9944:9944 healthcheck: diff --git a/examples/docker-compose-bodhi-stack.yml b/examples/docker-compose-bodhi-stack.yml index 89430346a..d5ed15e6f 100644 --- a/examples/docker-compose-bodhi-stack.yml +++ b/examples/docker-compose-bodhi-stack.yml @@ -1,6 +1,6 @@ services: mandala-node: - image: ghcr.io/acalanetwork/mandala-node:sha-7ae4bf4 + image: ghcr.io/acalanetwork/mandala-node:sha-06e988b container_name: mandala-node ports: - 9944:9944 diff --git a/examples/viem/docker-compose.yml b/examples/viem/docker-compose.yml index e23166dd9..ebe7c6144 100644 --- a/examples/viem/docker-compose.yml +++ b/examples/viem/docker-compose.yml @@ -1,6 +1,6 @@ services: mandala-node: - image: ghcr.io/acalanetwork/mandala-node:sha-7ae4bf4 + image: ghcr.io/acalanetwork/mandala-node:sha-06e988b container_name: mandala-node ports: - 9944:9944 diff --git a/examples/waffle/scheduler/test/Scheduler.test.ts b/examples/waffle/scheduler/test/Scheduler.test.ts index ef1a5324f..d7ffe11b5 100644 --- a/examples/waffle/scheduler/test/Scheduler.test.ts +++ b/examples/waffle/scheduler/test/Scheduler.test.ts @@ -161,10 +161,10 @@ describe('Schedule', () => { expect((await erc20.balanceOf(recurringPayment.address)).toNumber()).to.equal(0); if (!process.argv.includes('--with-ethereum-compatibility')) { expect((await provider.getBalance(transferTo)).toString()).to.equal( - formatAmount('4_999_969_004_075_107_000_000') + formatAmount('4999968960671632000000') ); - expect((await erc20.balanceOf(transferTo)).toString()).to.equal(formatAmount('4_999_969_004_075_107')); + expect((await erc20.balanceOf(transferTo)).toString()).to.equal(formatAmount('4999968960671632')); } else { expect((await provider.getBalance(transferTo)).toString()).to.equal(dollar.mul(5000000000).toString()); expect((await erc20.balanceOf(transferTo)).toString()).to.equal(dollar.mul(5000).toString()); diff --git a/packages/bodhi/package.json b/packages/bodhi/package.json index 75b58c1e9..b55f51363 100644 --- a/packages/bodhi/package.json +++ b/packages/bodhi/package.json @@ -1,6 +1,6 @@ { "name": "@acala-network/bodhi", - "version": "2.7.19", + "version": "2.7.20", "repository": "git@github.com:AcalaNetwork/bodhi.js.git", "author": "Acala Developers ", "license": "Apache-2.0", diff --git a/packages/bodhi/src/BodhiSigner.ts b/packages/bodhi/src/BodhiSigner.ts index d2be8f516..9a5481a28 100644 --- a/packages/bodhi/src/BodhiSigner.ts +++ b/packages/bodhi/src/BodhiSigner.ts @@ -208,7 +208,7 @@ export class BodhiSigner extends AbstractSigner implements TypedDataSigner { ..._transaction, }; - const { gasLimit, usedStorage: storageLimit } = await this.provider.estimateResources(transaction); + const { gasLimit, safeStorage: storageLimit } = await this.provider.estimateResources(transaction); const tx = await this.populateTransaction(transaction); const data = tx.data?.toString() ?? '0x'; diff --git a/packages/bodhi/src/_version.ts b/packages/bodhi/src/_version.ts index 1e221fc8e..763f88c5f 100644 --- a/packages/bodhi/src/_version.ts +++ b/packages/bodhi/src/_version.ts @@ -1 +1 @@ -export const version = 'bodhi.js/bodhi/2.7.19'; +export const version = 'bodhi.js/bodhi/2.7.20'; diff --git a/packages/eth-providers/package.json b/packages/eth-providers/package.json index 682878757..40dcf50ba 100644 --- a/packages/eth-providers/package.json +++ b/packages/eth-providers/package.json @@ -1,6 +1,6 @@ { "name": "@acala-network/eth-providers", - "version": "2.7.19", + "version": "2.7.20", "license": "MIT", "author": "Acala Developers ", "scripts": { @@ -10,7 +10,7 @@ "test:e2e": "vitest --run --config vitest.config.e2e.ts" }, "peerDependencies": { - "@acala-network/api": "~6.0.4", + "@acala-network/api": "6.1.0", "@polkadot/api": "^10.11.1" }, "dependencies": { @@ -23,7 +23,7 @@ "lru-cache": "~7.8.2" }, "devDependencies": { - "@acala-network/api": "~6.0.4", + "@acala-network/api": "6.1.0", "@types/bn.js": "~5.1.0", "@types/lru-cache": "~7.6.1", "dotenv": "~10.0.0", diff --git a/packages/eth-providers/src/__tests__/e2e/tx.test.ts b/packages/eth-providers/src/__tests__/e2e/tx.test.ts index f45b7ad94..7697feebc 100644 --- a/packages/eth-providers/src/__tests__/e2e/tx.test.ts +++ b/packages/eth-providers/src/__tests__/e2e/tx.test.ts @@ -65,27 +65,6 @@ describe('transaction tests', () => { }); describe.concurrent('test eth gas', () => { - it('getEthResources', async () => { - const randomWallet = Wallet.createRandom().connect(provider); - - const amount = '1000000000000000000'; - const resources = await provider.getEthResources({ - type: 0, - from: wallet3.address, - to: randomWallet.address, - value: BigNumber.from(amount), - }); - - await wallet3.sendTransaction({ - type: 0, - to: randomWallet.address, - value: BigNumber.from(amount), - ...resources, - }); - - expect((await randomWallet.getBalance()).toString()).eq(amount); - }); - it('use v2 gas params', async () => { const randomWallet = Wallet.createRandom().connect(provider); @@ -102,7 +81,7 @@ describe('transaction tests', () => { const expectedGasPrice = 100000000000 + validUntil; expect(Math.abs((params.gasPrice as BigNumber).toNumber() - expectedGasPrice)).to.lt(2); - expect((params.gasLimit as BigNumber).toNumber()).eq(100100); + expect(params.gasLimit?.toString()).toMatchInlineSnapshot('"100100"'); }); }); diff --git a/packages/eth-providers/src/_version.ts b/packages/eth-providers/src/_version.ts index 30bf977bf..9a7257ecb 100644 --- a/packages/eth-providers/src/_version.ts +++ b/packages/eth-providers/src/_version.ts @@ -1 +1 @@ -export const version = 'bodhi.js/providers/2.7.19'; +export const version = 'bodhi.js/providers/2.7.20'; diff --git a/packages/eth-providers/src/base-provider.ts b/packages/eth-providers/src/base-provider.ts index 84ee0e4c9..1fd8d6e0f 100644 --- a/packages/eth-providers/src/base-provider.ts +++ b/packages/eth-providers/src/base-provider.ts @@ -34,7 +34,7 @@ import { createHeaderExtended } from '@polkadot/api-derive'; import { filter, first, timeout } from 'rxjs/operators'; import { getAddress } from '@ethersproject/address'; import { hexDataLength, hexValue, hexZeroPad, hexlify, isHexString, joinSignature } from '@ethersproject/bytes'; -import { hexToU8a, isNull, u8aToHex, u8aToU8a } from '@polkadot/util'; +import { isNull, u8aToHex, u8aToU8a } from '@polkadot/util'; import BN from 'bn.js'; import LRUCache from 'lru-cache'; @@ -251,25 +251,17 @@ export interface PollFilters { [PollFilterType.Logs]: LogPollFilter[]; } -export interface CallInfo { - ok?: { - exit_reason: { - succeed?: 'Stopped' | 'Returned' | 'Suicided'; - error?: any; - revert?: 'Reverted'; - fatal?: any; - }; - value: string; - used_gas: string; - used_storage: number; - logs: Log[]; - }; - err?: { - module: { - index: number; - error: `0x${string}`; - }; - }; +export interface CallReturnInfo { + exit_reason: { + succeed?: 'Stopped' | 'Returned' | 'Suicided'; + error?: any; + revert?: 'Reverted'; + fatal?: any; + }; + value: string; + used_gas: string; + used_storage: number; + logs: Log[]; } export abstract class BaseProvider extends AbstractProvider { @@ -349,11 +341,18 @@ export abstract class BaseProvider extends AbstractProvider { } get finalizedBlockHash() { - return firstValueFrom(this.finalized$).then(({ hash }) => hash); + return firstValueFrom(this.finalized$).then( + ({ hash: chainFinalizedHash, number: chainFinalizedNumber }) => + chainFinalizedNumber <= this.bestBlockNumber + ? chainFinalizedHash + : this.bestBlockHash + ); } get finalizedBlockNumber() { - return firstValueFrom(this.finalized$).then(({ number }) => number); + return firstValueFrom(this.finalized$).then( + ({ number: chainFinalizedNumber }) => Math.min(this.bestBlockNumber, chainFinalizedNumber) + ); } static isProvider(value: any): value is Provider { @@ -814,53 +813,50 @@ export abstract class BaseProvider extends AbstractProvider { _ethCall = async (callRequest: SubstrateEvmCallRequest, at?: string) => { const api = at ? await this.api.at(at) : this.api; - const { from, to, gasLimit, storageLimit, value, data, accessList } = callRequest; - const estimate = false; - // call evm rpc when `state_call` is not supported yet if (!api.call.evmRuntimeRPCApi) { const data = await this.api.rpc.evm.call(callRequest); - const res: CallInfo = { - ok: { - exit_reason: { succeed: 'Returned' }, - value: data.toHex(), - used_gas: '0', - used_storage: 0, - logs: [], - }, + + return { + exit_reason: { succeed: 'Returned' }, + value: data.toHex(), + used_gas: '0', + used_storage: 0, + logs: [], }; - return res.ok; } + const { from, to, gasLimit, storageLimit, value, data, accessList } = callRequest; + const estimate = false; + const res = to ? await api.call.evmRuntimeRPCApi.call(from, to, data, value, gasLimit, storageLimit, accessList, estimate) : await api.call.evmRuntimeRPCApi.create(from, data, value, gasLimit, storageLimit, accessList, estimate); - const { ok, err } = res.toJSON() as CallInfo; + const ok = res.toJSON()['ok'] as CallReturnInfo | undefined; if (!ok) { // substrate level error - const errMetaValid = err?.module.index !== undefined && err?.module.error !== undefined; - if (!errMetaValid) { - return logger.throwError( - 'internal JSON-RPC error [unknown error - cannot decode error info from error meta]', - Logger.errors.CALL_EXCEPTION, - callRequest - ); - } + let errMsg: string; + const err = res.asErr; + if (err.isModule) { + const { index, error } = err.asModule; + const errInfo = this.api.registry.findMetaError({ + index: new BN(index), + error: new BN(error.toU8a()[0]), + }); - const errInfo = this.api.registry.findMetaError({ - index: new BN(err.module.index), - error: new BN(hexToU8a(err.module.error)[0]), - }); - const msg = `internal JSON-RPC error [${errInfo.section}.${errInfo.name}: ${errInfo.docs}]`; + errMsg = `internal JSON-RPC error [${errInfo.section}.${errInfo.name}: ${errInfo.docs}]`; + } else { + errMsg = err.toString(); + } - return logger.throwError(msg, Logger.errors.CALL_EXCEPTION, callRequest); + return logger.throwError(errMsg, Logger.errors.CALL_EXCEPTION, callRequest); } // check evm level error checkEvmExecutionError(ok); - return ok!; + return ok; }; getStorageAt = async ( @@ -941,7 +937,7 @@ export abstract class BaseProvider extends AbstractProvider { ? await this._getBlockHash(blockTag) : undefined; // if blockTag is latest, avoid explicit blockhash for better performance - const { usedGas, gasLimit, usedStorage } = await this.estimateResources(transaction, blockHash); + const { usedGas, gasLimit, safeStorage } = await this.estimateResources(transaction, blockHash); const tx = await resolveProperties(transaction); const data = tx.data?.toString() ?? '0x'; @@ -950,7 +946,7 @@ export abstract class BaseProvider extends AbstractProvider { data, toBN(BigNumber.from(tx.value ?? 0)), toBN(gasLimit), - toBN(usedStorage.isNegative() ? 0 : usedStorage), + toBN(safeStorage), accessListify(tx.accessList ?? []), ] as const; @@ -963,10 +959,8 @@ export abstract class BaseProvider extends AbstractProvider { let txFee = await this._estimateGasCost(extrinsic, blockHash); txFee = txFee.mul(gasLimit).div(usedGas); // scale it to the same ratio when estimate passing gasLimit - if (usedStorage.gt(0)) { - const storageFee = usedStorage.mul(this._getGasConsts().storageDepositPerByte); - txFee = txFee.add(storageFee); - } + const storageFee = safeStorage.mul(this._getGasConsts().storageDepositPerByte); + txFee = txFee.add(storageFee); const gasPrice = tx.gasPrice && BigNumber.from(tx.gasPrice).gt(0) ? BigNumber.from(tx.gasPrice) @@ -974,7 +968,7 @@ export abstract class BaseProvider extends AbstractProvider { const tokenTransferSelector = '0xa9059cbb'; // transfer(address,uint256) const isTokenTransfer = hexlify(await transaction.data ?? '0x').startsWith(tokenTransferSelector); - return encodeGasLimit(txFee, gasPrice, gasLimit, usedStorage, isTokenTransfer); + return encodeGasLimit(txFee, gasPrice, gasLimit, safeStorage, isTokenTransfer); }; _estimateGasCost = async ( @@ -1000,50 +994,6 @@ export abstract class BaseProvider extends AbstractProvider { return nativeToEthDecimal(nativeTxFee); }; - /** - * Get the gas for eth transactions - * @returns The gas used by eth transaction - */ - getEthResources = async ( - transaction: Deferrable, - { - gasLimit, - storageLimit, - validUntil, - }: { - gasLimit?: BigNumberish; - storageLimit?: BigNumberish; - validUntil?: BigNumberish; - } = {} - ): Promise<{ - gasPrice: BigNumber; - gasLimit: BigNumber; - }> => { - if (!gasLimit || !storageLimit) { - const { gasLimit: gas, usedStorage: storage } = await this.estimateResources(transaction); - gasLimit = gasLimit ?? gas; - storageLimit = storageLimit ?? storage; - } - - if (!validUntil) { - const blockNumber = await this.getBlockNumber(); - // Expires after 100 blocks by default - validUntil = blockNumber + 100; - } - - const { txGasLimit, txGasPrice } = calcEthereumTransactionParams({ - gasLimit, - storageLimit, - validUntil, - ...this._getGasConsts(), - }); - - return { - gasLimit: txGasLimit, - gasPrice: txGasPrice, - }; - }; - /** * helper to get ETH gas when don't know the whole transaction * default to return big enough gas for contract deployment @@ -1106,7 +1056,7 @@ export abstract class BaseProvider extends AbstractProvider { ): Promise<{ usedGas: BigNumber; gasLimit: BigNumber; - usedStorage: BigNumber; + safeStorage: BigNumber; }> => { const ethTx = await getTransactionRequest(transaction); @@ -1155,7 +1105,7 @@ export abstract class BaseProvider extends AbstractProvider { await this._ethCall({ ...txRequest, gasLimit, - }); + }, blockHash); } catch { gasAlreadyWorks = false; } @@ -1171,7 +1121,7 @@ export abstract class BaseProvider extends AbstractProvider { await this._ethCall({ ...txRequest, gasLimit: mid, - }); + }, blockHash); highest = mid; if ((prevHighest - highest) / prevHighest < 0.1) break; @@ -1190,10 +1140,16 @@ export abstract class BaseProvider extends AbstractProvider { gasLimit = highest; } + // Some contracts rely on block height and have different treatments. + // Transfer use `usedStorage` + const safeStorage = ethTx.data?.length > 0 + ? Math.floor((Math.max(usedStorage, 0) + 64) * 1.1) + : Math.max(usedStorage, 0); + return { - usedGas: BigNumber.from(usedGas), // actual used gas - gasLimit: BigNumber.from(gasLimit), // gasLimit to pass execution - usedStorage: BigNumber.from(usedStorage), + usedGas: BigNumber.from(usedGas), // actual used gas + gasLimit: BigNumber.from(gasLimit), // gasLimit to pass execution + safeStorage: BigNumber.from(safeStorage), // slightly over estimated storage to be safer }; }; diff --git a/packages/eth-providers/src/rpc-provider.ts b/packages/eth-providers/src/rpc-provider.ts index 1983af05d..1d0b1c363 100644 --- a/packages/eth-providers/src/rpc-provider.ts +++ b/packages/eth-providers/src/rpc-provider.ts @@ -1,14 +1,15 @@ -import { options } from '@acala-network/api'; - import { ApiPromise, WsProvider } from '@polkadot/api'; +import { withAcalaTypes } from '@acala-network/api'; + import { BaseProvider, BaseProviderOptions } from './base-provider'; export class EvmRpcProvider extends BaseProvider { constructor(endpoint: string | string[], opts?: BaseProviderOptions) { super(opts); - const provider = new WsProvider(endpoint); - const api = new ApiPromise(options({ provider })); + const api = new ApiPromise(withAcalaTypes({ + provider: new WsProvider(endpoint), + })); this.setApi(api); } diff --git a/packages/eth-providers/src/utils/utils.ts b/packages/eth-providers/src/utils/utils.ts index a9984ad4a..9c387e75b 100644 --- a/packages/eth-providers/src/utils/utils.ts +++ b/packages/eth-providers/src/utils/utils.ts @@ -1,13 +1,14 @@ import { AnyFunction } from '@polkadot/types/types'; import { BigNumber, BigNumberish } from '@ethersproject/bignumber'; -import { BlockTagish, CallInfo, Eip1898BlockTag } from '../base-provider'; -import { CacheInspect } from './BlockCache'; import { Extrinsic } from '@polkadot/types/interfaces'; import { FrameSystemEventRecord } from '@polkadot/types/lookup'; -import { _Metadata } from './gqlTypes'; import { hexToBn, hexToU8a, isHex, isU8a, u8aToBn } from '@polkadot/util'; import BN from 'bn.js'; +import { BlockTagish, CallReturnInfo, Eip1898BlockTag } from '../base-provider'; +import { CacheInspect } from './BlockCache'; +import { _Metadata } from './gqlTypes'; + export interface EthCallTimingResult { gasPriceTime: number; estimateGasTime: number; @@ -300,7 +301,7 @@ export const decodeRevertMsg = (hexMsg: string) => { }; // https://github.com/AcalaNetwork/Acala/blob/067b65bc19ff525bdccae020ad2bd4bdf41f4300/modules/evm/rpc/src/lib.rs#L87 -export const checkEvmExecutionError = (data: CallInfo['ok']): void => { +export const checkEvmExecutionError = (data: CallReturnInfo): void => { if (!data) return; const { exit_reason: exitReason, value: returnData } = data; diff --git a/packages/eth-rpc-adapter/README.md b/packages/eth-rpc-adapter/README.md index 5222558fb..8c6a820ae 100644 --- a/packages/eth-rpc-adapter/README.md +++ b/packages/eth-rpc-adapter/README.md @@ -4,7 +4,7 @@ A node service that provides [JSON-RPC](https://eth.wiki/json-rpc/API) for [Acal ## Run First run a Mandala node locally ``` -docker run -it --rm -p 9944:9944 ghcr.io/acalanetwork/mandala-node:sha-7ae4bf4 --dev --rpc-external --rpc-cors=all --rpc-methods=unsafe -levm=debug --pruning=archive --instant-sealing +docker run -it --rm -p 9944:9944 ghcr.io/acalanetwork/mandala-node:sha-06e988b --dev --rpc-external --rpc-cors=all --rpc-methods=unsafe -levm=debug --pruning=archive --instant-sealing ``` Then there are 3 ways to run an RPC adapter: @@ -118,7 +118,6 @@ These are ETH compatible RPCs, the interface and functionalities match https://e ### Custom RPCs These are EVM+ custom RPCs that only exist on Acala/Karura - `eth_getEthGas`: calculate eth transaction gas params from substrate gas params. More details please refer [here](https://evmdocs.acala.network/network/gas-parameters)] -- `eth_getEthResources`: calculate eth transaction gas params from transaction details, params: [TransactionRequest](https://docs.ethers.io/v5/api/providers/types/#providers-TransactionRequest) - `net_indexer`: get subql indexer metadata - `net_cacheInfo`: get the cache info - `net_isSafeMode`: check if this RPC is running in safe mode diff --git a/packages/eth-rpc-adapter/docker-compose.yml b/packages/eth-rpc-adapter/docker-compose.yml index 60a1590f4..852a8a4c6 100644 --- a/packages/eth-rpc-adapter/docker-compose.yml +++ b/packages/eth-rpc-adapter/docker-compose.yml @@ -2,7 +2,7 @@ version: '3' services: mandala-node: - image: ghcr.io/acalanetwork/mandala-node:sha-7ae4bf4 + image: ghcr.io/acalanetwork/mandala-node:sha-06e988b ports: - 9944:9944 command: diff --git a/packages/eth-rpc-adapter/package.json b/packages/eth-rpc-adapter/package.json index 53534e56b..5d53fd308 100644 --- a/packages/eth-rpc-adapter/package.json +++ b/packages/eth-rpc-adapter/package.json @@ -1,6 +1,6 @@ { "name": "@acala-network/eth-rpc-adapter", - "version": "2.7.19", + "version": "2.7.20", "license": "MIT", "author": "Acala Developers ", "bin": "./bin/eth-rpc-adapter.js", diff --git a/packages/eth-rpc-adapter/src/__tests__/e2e/__snapshots__/endpoint.test.ts.snap b/packages/eth-rpc-adapter/src/__tests__/e2e/__snapshots__/endpoint.test.ts.snap index 15bb85bfc..99023de58 100644 --- a/packages/eth-rpc-adapter/src/__tests__/e2e/__snapshots__/endpoint.test.ts.snap +++ b/packages/eth-rpc-adapter/src/__tests__/e2e/__snapshots__/endpoint.test.ts.snap @@ -1,5 +1,55 @@ // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html +exports[`endpoint > eth_getBlockByNumber > for very old runtime 1`] = ` +{ + "difficulty": "0x0", + "extraData": "0x", + "gasLimit": "0x1c99c80", + "gasUsed": "0x0", + "hash": "0x000643ffd6bbb04682ae1675e2e478e4c8ecd7c7b9d7e9d1eafe1b6095f751e3", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "miner": "0x8ce1cab8e0d55252720728bc495d05841ea3dc23", + "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "nonce": "0x0000000000000000", + "number": "0x5ae2c", + "parentHash": "0xe2ebe9eb139f9bc88862615f6a0c5095417595a0f80bd4f7f94c1c3753499973", + "receiptsRoot": "0xd3596ebbbb67ac571735047e856cecb63f3d8a519af4699ecc4505de59d570e5", + "sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", + "size": "0xa80", + "stateRoot": "0xd440bfe07178304657083255758ec74358a3ed592720a8484015d1d89950e81e", + "timestamp": "0x611f2b1e", + "totalDifficulty": "0x0", + "transactions": [], + "transactionsRoot": "0xd3596ebbbb67ac571735047e856cecb63f3d8a519af4699ecc4505de59d570e5", + "uncles": [], +} +`; + +exports[`endpoint > eth_getBlockByNumber > for very old runtime 2`] = ` +{ + "difficulty": "0x0", + "extraData": "0x", + "gasLimit": "0x1c99c80", + "gasUsed": "0x0", + "hash": "0x000643ffd6bbb04682ae1675e2e478e4c8ecd7c7b9d7e9d1eafe1b6095f751e3", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "miner": "0x8ce1cab8e0d55252720728bc495d05841ea3dc23", + "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "nonce": "0x0000000000000000", + "number": "0x5ae2c", + "parentHash": "0xe2ebe9eb139f9bc88862615f6a0c5095417595a0f80bd4f7f94c1c3753499973", + "receiptsRoot": "0xd3596ebbbb67ac571735047e856cecb63f3d8a519af4699ecc4505de59d570e5", + "sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", + "size": "0xa80", + "stateRoot": "0xd440bfe07178304657083255758ec74358a3ed592720a8484015d1d89950e81e", + "timestamp": "0x611f2b1e", + "totalDifficulty": "0x0", + "transactions": [], + "transactionsRoot": "0xd3596ebbbb67ac571735047e856cecb63f3d8a519af4699ecc4505de59d570e5", + "uncles": [], +} +`; + exports[`endpoint > eth_getBlockByNumber > when there are >= 2 EVM transactions 1`] = ` { "difficulty": "0x0", @@ -210,7 +260,7 @@ exports[`endpoint > eth_getTransactionByHash > finds correct tx when hash exist "blockNumber": "0xa", "from": "0x82a258cb20e2adb4788153cd5eb5839615ece9a0", "gas": "0x1fd91", - "gasPrice": "0x252bd4aa7a", + "gasPrice": "0x25315050b1", "input": "0x3d8d96200000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000e8d4a51000000000000000000000000000000000000000000000000000000000e8d4a51000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000100000000000000000001", "nonce": "0x6", "r": "0x1b5e176d927f8e9ab405058b2d2457392da3e20f328b16ddabcebc33eaac5fea", @@ -227,7 +277,7 @@ exports[`endpoint > eth_getTransactionByHash > finds correct tx when hash exist "blockNumber": "0x9", "from": "0x82a258cb20e2adb4788153cd5eb5839615ece9a0", "gas": "0x25a7f", - "gasPrice": "0x229d8bad01", + "gasPrice": "0x22a22ed358", "input": "0x3d8d962000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000e8d4a510000000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001000000000000000000010000000000000000000000000000000000000000000100000000000000000002", "nonce": "0x5", "r": "0x1b5e176d927f8e9ab405058b2d2457392da3e20f328b16ddabcebc33eaac5fea", @@ -244,7 +294,7 @@ exports[`endpoint > eth_getTransactionByHash > finds correct tx when hash exist "blockNumber": "0x6", "from": "0x82a258cb20e2adb4788153cd5eb5839615ece9a0", "gas": "0x1fdca", - "gasPrice": "0x2529a6b58c", + "gasPrice": "0x252f21c079", "input": "0x6fc4b4e50000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000e8d4a510000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000100000000000000000001", "nonce": "0x2", "r": "0x1b5e176d927f8e9ab405058b2d2457392da3e20f328b16ddabcebc33eaac5fea", @@ -261,7 +311,7 @@ exports[`endpoint > eth_getTransactionByHash > finds correct tx when hash exist "blockNumber": "0x14", "from": "0x82a258cb20e2adb4788153cd5eb5839615ece9a0", "gas": "0x200b20", - "gasPrice": "0x41d4ad9224", + "gasPrice": "0x41d4ad924b", "input": "0x", "nonce": "0x10", "r": "0x1b5e176d927f8e9ab405058b2d2457392da3e20f328b16ddabcebc33eaac5fea", @@ -417,7 +467,7 @@ exports[`endpoint > eth_getTransactionReceipt > returns correct result when hash "blockNumber": "0xa", "contractAddress": null, "cumulativeGasUsed": "0x0", - "effectiveGasPrice": "0x252bd4aa7a", + "effectiveGasPrice": "0x25315050b1", "from": "0x82a258cb20e2adb4788153cd5eb5839615ece9a0", "gasUsed": "0x1a8a4", "logs": [ @@ -446,7 +496,7 @@ exports[`endpoint > eth_getTransactionReceipt > returns correct result when hash "blockNumber": "0x9", "contractAddress": null, "cumulativeGasUsed": "0x0", - "effectiveGasPrice": "0x229d8bad01", + "effectiveGasPrice": "0x22a22ed358", "from": "0x82a258cb20e2adb4788153cd5eb5839615ece9a0", "gasUsed": "0x1f615", "logs": [ @@ -475,7 +525,7 @@ exports[`endpoint > eth_getTransactionReceipt > returns correct result when hash "blockNumber": "0x6", "contractAddress": null, "cumulativeGasUsed": "0x0", - "effectiveGasPrice": "0x2529a6b58c", + "effectiveGasPrice": "0x252f21c079", "from": "0x82a258cb20e2adb4788153cd5eb5839615ece9a0", "gasUsed": "0x1a8d3", "logs": [ @@ -504,7 +554,7 @@ exports[`endpoint > eth_getTransactionReceipt > returns correct result when hash "blockNumber": "0x14", "contractAddress": null, "cumulativeGasUsed": "0x0", - "effectiveGasPrice": "0x41d4ad9224", + "effectiveGasPrice": "0x41d4ad924b", "from": "0x82a258cb20e2adb4788153cd5eb5839615ece9a0", "gasUsed": "0xcbbd", "logs": [ 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 387bd8839..9c8edeb33 100644 --- a/packages/eth-rpc-adapter/src/__tests__/e2e/endpoint.test.ts +++ b/packages/eth-rpc-adapter/src/__tests__/e2e/endpoint.test.ts @@ -42,7 +42,6 @@ import { eth_chainId, eth_getEthGas, eth_getCode, - eth_getEthResources, net_runtimeVersion, eth_isBlockFinalized, eth_newFilter, @@ -697,7 +696,9 @@ describe('endpoint', () => { // }); expect(diffReceiptTxFee < TX_FEE_OFF_TOLERANCE).to.be.true; - expect(diffEstimateTxFee < TX_FEE_OFF_TOLERANCE).to.be.true; + + // estimated tx fee is slightly overestimated now + expect(diffEstimateTxFee < TX_FEE_OFF_TOLERANCE).to.be.false; }); }); @@ -1200,22 +1201,6 @@ describe('endpoint', () => { }); }); - describe('eth_getEthResources', () => { - it('get correct gas', async () => { - const rawRes = ( - await eth_getEthResources([ - { - from: '0xd2a5c8867d1b3665fb3b2d93d514bd1c73bb2227', - to: '0x4e3e1108e86c3fafb389629e99bff9c4fa911e54', - data: '0x', - }, - ]) - ).data.result; - expect(rawRes.gasPrice).to.equal('0x2e90f20000'); - expect(rawRes.gasLimit).to.equal('0x6270'); - }); - }); - describe('net_runtimeVersion', () => { it('get correct runtime version', async () => { const version = (await net_runtimeVersion([])).data.result; @@ -1253,11 +1238,19 @@ describe('endpoint', () => { expect(resFull).toMatchSnapshot(); expect(res).toMatchSnapshot(); }); + + it('for very old runtime', async () => { + const resFull = (await eth_getBlockByNumber_karura([372268, true])).data.result; + const res = (await eth_getBlockByNumber_karura([372268, false])).data.result; + + expect(resFull).toMatchSnapshot(); + expect(res).toMatchSnapshot(); + }); }); describe('eth_getBalance', () => { it('get correct balance', async () => { - const block8Balance = 8999995192389995117000000n; // edit me for different mandala version + const block8Balance = 8999995192313663934000000n; // edit me for different mandala version expect(BigInt((await eth_getBalance([ADDRESS_ALICE, 8])).data.result)).to.equal(block8Balance); expect(BigInt((await eth_getBalance([ADDRESS_ALICE, '0x8'])).data.result)).to.equal(block8Balance); expect(BigInt((await eth_getBalance([ADDRESS_ALICE, { blockNumber: 8 }])).data.result)).to.equal(block8Balance); diff --git a/packages/eth-rpc-adapter/src/__tests__/e2e/utils.ts b/packages/eth-rpc-adapter/src/__tests__/e2e/utils.ts index d847b9284..727b09fb6 100644 --- a/packages/eth-rpc-adapter/src/__tests__/e2e/utils.ts +++ b/packages/eth-rpc-adapter/src/__tests__/e2e/utils.ts @@ -50,7 +50,6 @@ export const eth_gasPrice = rpcGet('eth_gasPrice'); export const eth_estimateGas = rpcGet('eth_estimateGas'); export const eth_getEthGas = rpcGet('eth_getEthGas'); export const eth_getCode = rpcGet('eth_getCode'); -export const eth_getEthResources = rpcGet('eth_getEthResources'); export const net_runtimeVersion = rpcGet('net_runtimeVersion'); export const eth_isBlockFinalized = rpcGet('eth_isBlockFinalized'); export const eth_newFilter = rpcGet('eth_newFilter'); diff --git a/packages/eth-rpc-adapter/src/_version.ts b/packages/eth-rpc-adapter/src/_version.ts index 95777e8b5..8d026bd61 100644 --- a/packages/eth-rpc-adapter/src/_version.ts +++ b/packages/eth-rpc-adapter/src/_version.ts @@ -1 +1 @@ -export const version = 'bodhi.js/eth-rpc-adapter/2.7.19'; +export const version = 'bodhi.js/eth-rpc-adapter/2.7.20'; diff --git a/packages/eth-rpc-adapter/src/eip1193-bridge.ts b/packages/eth-rpc-adapter/src/eip1193-bridge.ts index 1d8782644..472d76f9d 100644 --- a/packages/eth-rpc-adapter/src/eip1193-bridge.ts +++ b/packages/eth-rpc-adapter/src/eip1193-bridge.ts @@ -312,20 +312,6 @@ class Eip1193BridgeImpl { }; } - async eth_getEthResources(params: any[]): Promise<{ - gasPrice: string; - gasLimit: string; - }> { - validate([{ type: 'transaction' }], params); - - const res = await this.#provider.getEthResources(params[0]); - - return { - gasPrice: hexValue(res.gasPrice), - gasLimit: hexValue(res.gasLimit), - }; - } - /** * Returns the information about a transaction requested by transaction hash. * @param DATA, 32 Bytes - hash of a transaction diff --git a/packages/eth-rpc-adapter/src/wrapped-provider.ts b/packages/eth-rpc-adapter/src/wrapped-provider.ts index 4baedec00..c1a15326e 100644 --- a/packages/eth-rpc-adapter/src/wrapped-provider.ts +++ b/packages/eth-rpc-adapter/src/wrapped-provider.ts @@ -1,6 +1,6 @@ import { ApiPromise, WsProvider } from '@polkadot/api'; import { BaseProvider, BaseProviderOptions } from '@acala-network/eth-providers/base-provider'; -import { options } from '@acala-network/api'; +import { withAcalaTypes } from '@acala-network/api'; import tracer from 'dd-trace'; const TRACE_METHODS = [ @@ -23,7 +23,6 @@ const TRACE_METHODS = [ 'getFeeData', 'estimateGas', '_estimateGasCost', - 'getEthResources', '_getEthGas', 'estimateResources', 'getSubstrateAddress', @@ -86,8 +85,9 @@ export class EvmRpcProviderWithTrace extends BaseProviderWithTrace { constructor(endpoint: string | string[], opts?: BaseProviderOptions) { super(opts); - const provider = new WsProvider(endpoint); - const api = new ApiPromise(options({ provider })); + const api = new ApiPromise(withAcalaTypes({ + provider: new WsProvider(endpoint), + })); this.setApi(api); } diff --git a/packages/eth-transactions/package.json b/packages/eth-transactions/package.json index fba55c0b5..16921bc24 100644 --- a/packages/eth-transactions/package.json +++ b/packages/eth-transactions/package.json @@ -1,6 +1,6 @@ { "name": "@acala-network/eth-transactions", - "version": "2.7.19", + "version": "2.7.20", "license": "MIT", "author": "Acala Developers ", "scripts": { diff --git a/packages/eth-transactions/src/_version.ts b/packages/eth-transactions/src/_version.ts index f137cdf75..eb336206c 100644 --- a/packages/eth-transactions/src/_version.ts +++ b/packages/eth-transactions/src/_version.ts @@ -1 +1 @@ -export const version = 'bodhi.js/transactions/2.7.19'; +export const version = 'bodhi.js/transactions/2.7.20'; diff --git a/packages/evm-subql/README.md b/packages/evm-subql/README.md index e164e59e6..83edcc436 100644 --- a/packages/evm-subql/README.md +++ b/packages/evm-subql/README.md @@ -51,7 +51,7 @@ npm i -g @subql/node@1.21.2 @subql/query@1.4.0 If you already have a node running elsewhere, you can skip this step. ```shell -docker run -it --rm -p 9944:9944 ghcr.io/acalanetwork/mandala-node:sha-7ae4bf4 --dev --rpc-external --rpc-cors=all --rpc-methods=unsafe -levm=debug --pruning=archive --instant-sealing +docker run -it --rm -p 9944:9944 ghcr.io/acalanetwork/mandala-node:sha-06e988b --dev --rpc-external --rpc-cors=all --rpc-methods=unsafe -levm=debug --pruning=archive --instant-sealing ``` 3. Run a Postgres service and listen to port number 5432 (in the second terminal) diff --git a/packages/evm-subql/docker-compose.yml b/packages/evm-subql/docker-compose.yml index 387f34556..4f21ea054 100644 --- a/packages/evm-subql/docker-compose.yml +++ b/packages/evm-subql/docker-compose.yml @@ -2,7 +2,7 @@ version: '3.9' services: mandala-node: - image: ghcr.io/acalanetwork/mandala-node:sha-7ae4bf4 + image: ghcr.io/acalanetwork/mandala-node:sha-06e988b ports: - 9944:9944 healthcheck: diff --git a/packages/evm-subql/project.yaml b/packages/evm-subql/project.yaml index 03e00cf48..dad5a22af 100644 --- a/packages/evm-subql/project.yaml +++ b/packages/evm-subql/project.yaml @@ -14,7 +14,7 @@ schema: file: ./schema.graphql network: # local mandala - chainId: '0x6808cd9b5035f8983328e7ddb7efa0da77ecc2e180de504d13d0e5789724e8b7' + chainId: '0x6b4acf5a0264399326a45d79037b1fcd4c4f3259589bd7642f1272b6adf0e00d' endpoint: ws://localhost:9944 chaintypes: # TODO: can generate this dynamically with `yarn build` using `@acala-network/types` diff --git a/scripts/e2e-tests/docker-compose-subway.yml b/scripts/e2e-tests/docker-compose-subway.yml index 441bf10b7..e36f7c7c3 100644 --- a/scripts/e2e-tests/docker-compose-subway.yml +++ b/scripts/e2e-tests/docker-compose-subway.yml @@ -1,6 +1,6 @@ services: mandala-node: - image: ghcr.io/acalanetwork/mandala-node:sha-7ae4bf4 + image: ghcr.io/acalanetwork/mandala-node:sha-06e988b container_name: mandala-node ports: - 9944:9944 diff --git a/scripts/new-rpc-benchmark/README.md b/scripts/new-rpc-benchmark/README.md index 7d6701aa4..8d8dd286b 100644 --- a/scripts/new-rpc-benchmark/README.md +++ b/scripts/new-rpc-benchmark/README.md @@ -1,7 +1,7 @@ # New Eth RPC Benchmark first start a local mandala with normal sealing ``` -docker run -it --rm -p 9944:9944 ghcr.io/acalanetwork/mandala-node:sha-7ae4bf4 --dev --rpc-external --rpc-cors=all --rpc-methods=unsafe -levm=debug --pruning=archive +docker run -it --rm -p 9944:9944 ghcr.io/acalanetwork/mandala-node:sha-06e988b --dev --rpc-external --rpc-cors=all --rpc-methods=unsafe -levm=debug --pruning=archive ``` then start an old rpc adapter diff --git a/yarn.lock b/yarn.lock index 098af3566..de8be0da5 100644 --- a/yarn.lock +++ b/yarn.lock @@ -12,26 +12,26 @@ __metadata: languageName: node linkType: hard -"@acala-network/api-derive@npm:6.0.4": - version: 6.0.4 - resolution: "@acala-network/api-derive@npm:6.0.4" +"@acala-network/api-derive@npm:6.1.0": + version: 6.1.0 + resolution: "@acala-network/api-derive@npm:6.1.0" dependencies: - "@acala-network/types": 6.0.4 + "@acala-network/types": 6.1.0 peerDependencies: "@polkadot/api": ^10.9.1 - checksum: b079d02405d1e9cf3dd98bab284c5d966f30766e20dfb8c818e59c6388668fe78779969b7c6a8dd081085bf3517fd08e0efc3a659b25b484348403f210f209e6 + checksum: a29227d804e451a26e9011d312fec3d35e872107e2420accd6ba76445eaf603c163150120a0325b851556ef263412ecd668aabba82acb40ef13e30ff4e71d025 languageName: node linkType: hard -"@acala-network/api@npm:~6.0.4": - version: 6.0.4 - resolution: "@acala-network/api@npm:6.0.4" +"@acala-network/api@npm:6.1.0": + version: 6.1.0 + resolution: "@acala-network/api@npm:6.1.0" dependencies: - "@acala-network/api-derive": 6.0.4 - "@acala-network/types": 6.0.4 + "@acala-network/api-derive": 6.1.0 + "@acala-network/types": 6.1.0 peerDependencies: "@polkadot/api": ^10.9.1 - checksum: 46e09c485e0227461c377fa3c032b3f138d58f084da8fa61119e5cae868ba32ebe2301dc5759512a063863ecfcfa77b99bda57b2392f62badd91547f9106cd6b + checksum: 286aa8b219d1255c89f8be8c9af2594192178b78a992b8528e1d0df5dc647f6c02dac291c3fa03025a6a30fc6b9e77a00ac4368191d1f4bd07838e32070a3181 languageName: node linkType: hard @@ -69,7 +69,7 @@ __metadata: version: 0.0.0-use.local resolution: "@acala-network/eth-providers@workspace:packages/eth-providers" dependencies: - "@acala-network/api": ~6.0.4 + "@acala-network/api": 6.1.0 "@acala-network/contracts": 4.3.4 "@acala-network/eth-transactions": "workspace:*" "@types/bn.js": ~5.1.0 @@ -83,7 +83,7 @@ __metadata: lru-cache: ~7.8.2 vitest: 0.34.2 peerDependencies: - "@acala-network/api": ~6.0.4 + "@acala-network/api": 6.1.0 "@polkadot/api": ^10.11.1 languageName: unknown linkType: soft @@ -148,12 +148,12 @@ __metadata: languageName: unknown linkType: soft -"@acala-network/types@npm:6.0.4": - version: 6.0.4 - resolution: "@acala-network/types@npm:6.0.4" +"@acala-network/types@npm:6.1.0": + version: 6.1.0 + resolution: "@acala-network/types@npm:6.1.0" peerDependencies: "@polkadot/api": ^10.9.1 - checksum: 39de2159c0973e0a9143752f013154d5527a670c79444394767fd6b3bac07c68dbd2fef344f72c6967f77ce9dc5136f571f65d7e5a4e8f9f1f0daf87f9b8a1be + checksum: 52790bf0e75ceaa2cf8533c87182b362b5da6c27055767ac535dafbcc207bd2f5ddfc7a3582d0d14e40cb5b52ef66848222ed620777b6c874c9c9936db2b300e languageName: node linkType: hard @@ -13416,23 +13416,13 @@ __metadata: languageName: node linkType: hard -"follow-redirects@npm:^1.12.1": - version: 1.15.3 - resolution: "follow-redirects@npm:1.15.3" - peerDependenciesMeta: - debug: - optional: true - checksum: 584da22ec5420c837bd096559ebfb8fe69d82512d5585004e36a3b4a6ef6d5905780e0c74508c7b72f907d1fa2b7bd339e613859e9c304d0dc96af2027fd0231 - languageName: node - linkType: hard - -"follow-redirects@npm:^1.14.0, follow-redirects@npm:^1.14.4, follow-redirects@npm:^1.14.9, follow-redirects@npm:^1.15.0": - version: 1.15.2 - resolution: "follow-redirects@npm:1.15.2" +"follow-redirects@npm:^1.12.1, follow-redirects@npm:^1.14.0, follow-redirects@npm:^1.14.4, follow-redirects@npm:^1.14.9, follow-redirects@npm:^1.15.0": + version: 1.15.5 + resolution: "follow-redirects@npm:1.15.5" peerDependenciesMeta: debug: optional: true - checksum: faa66059b66358ba65c234c2f2a37fcec029dc22775f35d9ad6abac56003268baf41e55f9ee645957b32c7d9f62baf1f0b906e68267276f54ec4b4c597c2b190 + checksum: 5ca49b5ce6f44338cbfc3546823357e7a70813cecc9b7b768158a1d32c1e62e7407c944402a918ea8c38ae2e78266312d617dc68783fac502cbb55e1047b34ec languageName: node linkType: hard @@ -24428,8 +24418,8 @@ __metadata: linkType: hard "vite@npm:^3.0.0 || ^4.0.0": - version: 4.4.9 - resolution: "vite@npm:4.4.9" + version: 4.5.2 + resolution: "vite@npm:4.5.2" dependencies: esbuild: ^0.18.10 fsevents: ~2.3.2 @@ -24463,7 +24453,7 @@ __metadata: optional: true bin: vite: bin/vite.js - checksum: c511024ceae39c68c7dbf2ac4381ee655cd7bb62cf43867a14798bc835d3320b8fa7867a336143c30825c191c1fb4e9aa3348fce831ab617e96203080d3d2908 + checksum: 9d1f84f703c2660aced34deee7f309278ed368880f66e9570ac115c793d91f7fffb80ab19c602b3c8bc1341fe23437d86a3fcca2a9ef82f7ef0cdac5a40d0c86 languageName: node linkType: hard