@@ -1024,52 +1024,48 @@ export class EthImpl implements Eth {
10241024 await this . performCallChecks ( call , requestId ) ;
10251025
10261026 // Get a reasonable value for "gas" if it is not specified.
1027- let gas = Number ( call . gas ) || 400_000 ;
1028-
1029- let value : string | null = null ;
1030- if ( typeof call . value === 'string' ) {
1031- value = ( new BN ( call . value ) ) . toString ( ) ;
1032- }
1033-
1034- // Gas limit for `eth_call` is 50_000_000, but the current Hedera network limit is 15_000_000
1035- // With values over the gas limit, the call will fail with BUSY error so we cap it at 15_000_000
1036- if ( gas > constants . BLOCK_GAS_LIMIT ) {
1037- this . logger . trace ( `${ requestIdPrefix } eth_call gas amount (${ gas } ) exceeds network limit, capping gas to ${ constants . BLOCK_GAS_LIMIT } ` ) ;
1038- gas = constants . BLOCK_GAS_LIMIT ;
1039- }
1027+ let gas = this . getCappedBlockGasLimit ( call . gas ) ;
1028+ let value : string | null = EthImpl . toNullableBigNumber ( call . value ) ;
10401029
10411030 try {
10421031 // ETH_CALL_DEFAULT_TO_CONSENSUS_NODE = false enables the use of Mirror node
10431032 if ( process . env . ETH_CALL_DEFAULT_TO_CONSENSUS_NODE == 'false' ) {
10441033 //temporary workaround until precompiles are implemented in Mirror node evm module
10451034 // Execute the call and get the response
1046- this . logger . debug ( `${ requestIdPrefix } Making eth_call on contract ${ call . to } with gas ${ gas } and call data "${ call . data } " from "${ call . from } " using mirror-node.` , call . to , gas , call . data , call . from ) ;
1047- const callData = {
1048- ...call ,
1049- gas,
1050- value,
1051- estimate : false
1052- }
1053- const contractCallResponse = await this . mirrorNodeClient . postContractCall ( callData , requestId ) ;
1054- if ( contractCallResponse && contractCallResponse . result ) {
1055- return EthImpl . prepend0x ( contractCallResponse . result ) ;
1056- }
1057- return EthImpl . emptyHex ;
1035+ return await this . callMirrorNode ( call , gas , value , requestId ) ;
10581036 }
10591037
10601038 return await this . callConsensusNode ( call , gas , requestId ) ;
10611039 } catch ( e : any ) {
1062- // Temporary workaround until mirror node web3 module implements the support of precompiles
1063- // If mirror node throws NOT_SUPPORTED or precompile is not supported, rerun eth_call and force it to go through the Consensus network
1064- if ( e instanceof MirrorNodeClientError && ( e . isNotSupported ( ) || e . isNotSupportedSystemContractOperaton ( ) ) ) {
1065- return await this . callConsensusNode ( call , gas , requestId ) ;
1066- }
1040+ this . logger . error ( e , `${ requestIdPrefix } Failed to successfully submit eth_call` ) ;
1041+ return e instanceof JsonRpcError ? e : predefined . INTERNAL_ERROR ( ) ;
1042+ }
1043+ }
10671044
1068- this . logger . error ( e , `${ requestIdPrefix } Failed to successfully submit contractCallQuery` ) ;
1069- if ( e instanceof JsonRpcError ) {
1070- return e ;
1045+ async callMirrorNode ( call : any , gas : number , value : string | null , requestId ?: string ) : Promise < string | JsonRpcError > {
1046+ const requestIdPrefix = formatRequestIdMessage ( requestId ) ;
1047+ try {
1048+ this . logger . debug ( `${ requestIdPrefix } Making eth_call on contract ${ call . to } with gas ${ gas } and call data "${ call . data } " from "${ call . from } " using mirror-node.` , call . to , gas , call . data , call . from ) ;
1049+ const callData = {
1050+ ...call ,
1051+ gas,
1052+ value,
1053+ estimate : false
10711054 }
1072- return predefined . INTERNAL_ERROR ( ) ;
1055+
1056+ const contractCallResponse = await this . mirrorNodeClient . postContractCall ( callData , requestId ) ;
1057+ return contractCallResponse && contractCallResponse . result ? EthImpl . prepend0x ( contractCallResponse . result ) : EthImpl . emptyHex ;
1058+ } catch ( e : any ) {
1059+ // Temporary workaround until mirror node web3 module implements the support of precompiles
1060+ // If mirror node throws, rerun eth_call and force it to go through the Consensus network
1061+ if ( e ) {
1062+ const errorTypeMessage = e instanceof MirrorNodeClientError && ( e . isNotSupported ( ) || e . isNotSupportedSystemContractOperaton ( ) ) ? 'Unsupported' : 'Unhandled' ;
1063+ this . logger . trace ( `${ requestIdPrefix } ${ errorTypeMessage } mirror node eth_call request, retrying with consensus node` ) ;
1064+
1065+ return await this . callConsensusNode ( call , gas , requestId ) ;
1066+ }
1067+ this . logger . error ( e , `${ requestIdPrefix } Failed to successfully submit eth_call` ) ;
1068+ return e instanceof JsonRpcError ? e : predefined . INTERNAL_ERROR ( ) ;
10731069 }
10741070 }
10751071
@@ -1292,6 +1288,14 @@ export class EthImpl implements Eth {
12921288 return value . substring ( 0 , 66 ) ;
12931289 }
12941290
1291+ static toNullableBigNumber ( value : string ) : string | null {
1292+ if ( typeof value === 'string' ) {
1293+ return ( new BN ( value ) ) . toString ( ) ;
1294+ }
1295+
1296+ return null ;
1297+ }
1298+
12951299 private static toNullIfEmptyHex ( value : string ) : string | null {
12961300 return value === EthImpl . emptyHex ? null : value ;
12971301 }
@@ -1330,6 +1334,22 @@ export class EthImpl implements Eth {
13301334 }
13311335 }
13321336
1337+ private getCappedBlockGasLimit ( gasString : string , requestIdPrefix ?: string ) : number {
1338+ if ( ! gasString ) {
1339+ return 400_000 ;
1340+ }
1341+
1342+ // Gas limit for `eth_call` is 50_000_000, but the current Hedera network limit is 15_000_000
1343+ // With values over the gas limit, the call will fail with BUSY error so we cap it at 15_000_000
1344+ let gas = Number . parseInt ( gasString ) ;
1345+ if ( gas > constants . BLOCK_GAS_LIMIT ) {
1346+ this . logger . trace ( `${ requestIdPrefix } eth_call gas amount (${ gas } ) exceeds network limit, capping gas to ${ constants . BLOCK_GAS_LIMIT } ` ) ;
1347+ return constants . BLOCK_GAS_LIMIT ;
1348+ }
1349+
1350+ return gas ;
1351+ }
1352+
13331353 /**
13341354 * Gets the block with the given hash.
13351355 * Given an ethereum transaction hash, call the mirror node to get the block info.
0 commit comments