Skip to content

Commit e2667dc

Browse files
committed
Merge branch 'main' into 4080-use-interpolation-values-instead-of-string-interpolation-when-logging
# Conflicts: # packages/relay/src/lib/services/ethService/contractService/ContractService.ts
2 parents 13ae128 + 14955e9 commit e2667dc

File tree

17 files changed

+608
-312
lines changed

17 files changed

+608
-312
lines changed

.env.http.example

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@ OPERATOR_KEY_MAIN= # Operator private key used to sign transaction
2222
# DEBUG_API_ENABLED=false # Enables debug methods like debug_traceTransaction
2323
# TXPOOL_API_ENABLED=true # Enables txpool related methods
2424
# FILTER_API_ENABLED=true # Enables filter related methods
25-
# ESTIMATE_GAS_THROWS=true # If true, throws actual error reason during contract reverts
2625

2726
# ========== BATCH REQUESTS ==========
2827
# BATCH_REQUESTS_ENABLED=true # Enable or disable batch requests

charts/hedera-json-rpc-relay/values.yaml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,6 @@ config:
3131
# DEBUG_API_ENABLED:
3232
# TXPOOL_API_ENABLED:
3333
# FILTER_API_ENABLED:
34-
# ESTIMATE_GAS_THROWS:
3534
# SUBSCRIPTIONS_ENABLED:
3635

3736
# ========== BATCH REQUESTS ==========

docs/configuration.md

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,6 @@ Unless you need to set a non-default value, it is recommended to only populate o
3838
| `DEBUG_API_ENABLED` | "false" | Enables all debug related methods: `debug_traceTransaction` |
3939
| `DEFAULT_RATE_LIMIT` | "200" | default fallback rate limit, if no other is configured. |
4040
| `ENABLE_TX_POOL` | "false" | Flag to determine if the system should use a tx pool or not. |
41-
| `ESTIMATE_GAS_THROWS` | "true" | Flag to determine if the system should throw an error with the actual reason during contract reverts instead of returning a predefined gas value. |
4241
| `ETH_BLOCK_NUMBER_CACHE_TTL_MS` | "1000" | Time in ms to cache response from mirror node |
4342
| `ETH_CALL_ACCEPTED_ERRORS` | "[]" | A list of acceptable error codes for eth_call requests. If an error code in this list is returned, the request will be retried. |
4443
| `ETH_CALL_CACHE_TTL` | "200" | Maximum time in ms to cache an eth_call response. |

packages/config-service/src/services/globalConfig.ts

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -173,11 +173,6 @@ const _CONFIG = {
173173
required: false,
174174
defaultValue: false,
175175
},
176-
ESTIMATE_GAS_THROWS: {
177-
type: 'boolean',
178-
required: false,
179-
defaultValue: true,
180-
},
181176
ETH_BLOCK_NUMBER_CACHE_TTL_MS: {
182177
type: 'number',
183178
required: false,

packages/relay/src/lib/errors/JsonRpcError.ts

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -196,10 +196,12 @@ export const predefined = {
196196
message: message,
197197
});
198198
},
199-
COULD_NOT_ESTIMATE_GAS_PRICE: new JsonRpcError({
200-
code: -32604,
201-
message: 'Error encountered estimating the gas price',
202-
}),
199+
COULD_NOT_SIMULATE_TRANSACTION: (errMessage: string) => {
200+
return new JsonRpcError({
201+
code: -32000,
202+
message: `Error occurred during transaction simulation: ${errMessage}`,
203+
});
204+
},
203205
COULD_NOT_RETRIEVE_LATEST_BLOCK: new JsonRpcError({
204206
code: -32607,
205207
message: 'Error encountered retrieving latest block',

packages/relay/src/lib/errors/MirrorNodeClientError.ts

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ export class MirrorNodeClientError extends Error {
99

1010
static ErrorCodes = {
1111
ECONNABORTED: 504,
12-
CONTRACT_REVERT_EXECUTED: 400,
1312
NOT_SUPPORTED: 501,
1413
};
1514

@@ -45,11 +44,7 @@ export class MirrorNodeClientError extends Error {
4544
return this.statusCode === MirrorNodeClientError.ErrorCodes.ECONNABORTED;
4645
}
4746

48-
public isContractReverted(): boolean {
49-
return this.statusCode === MirrorNodeClientError.ErrorCodes.CONTRACT_REVERT_EXECUTED;
50-
}
51-
52-
public isContractRevertOpcodeExecuted() {
47+
public isContractRevert() {
5348
return this.message === MirrorNodeClientError.messages.CONTRACT_REVERT_EXECUTED;
5449
}
5550

packages/relay/src/lib/services/ethService/contractService/ContractService.ts

Lines changed: 24 additions & 86 deletions
Original file line numberDiff line numberDiff line change
@@ -161,24 +161,26 @@ export class ContractService implements IContractService {
161161
try {
162162
const response = await this.estimateGasFromMirrorNode(transaction, requestDetails);
163163

164-
if (response?.result) {
165-
this.logger.info(`Returning gas: %s`, response.result);
166-
return prepend0x(trimPrecedingZeros(response.result));
167-
} else {
168-
this.logger.error(`No gas estimate returned from mirror-node: %s`, JSON.stringify(response));
169-
return this.predefinedGasForTransaction(transaction, requestDetails);
164+
if (!response?.result) {
165+
if (this.logger.isLevelEnabled('debug')) {
166+
this.logger.debug(`No gas estimate returned from mirror-node: ${JSON.stringify(response)}`);
167+
}
168+
return predefined.INTERNAL_ERROR('Fail to retrieve gas estimate');
170169
}
170+
171+
return prepend0x(trimPrecedingZeros(response.result));
171172
} catch (e: any) {
172-
this.logger.error(`Error raised while fetching estimateGas from mirror-node: %s`, JSON.stringify(e));
173-
// in case of contract revert, we don't want to return a predefined gas but the actual error with the reason
174-
if (
175-
ConfigService.get('ESTIMATE_GAS_THROWS') &&
176-
e instanceof MirrorNodeClientError &&
177-
e.isContractRevertOpcodeExecuted()
178-
) {
179-
return predefined.CONTRACT_REVERT(e.detail ?? e.message, e.data);
173+
if (e instanceof MirrorNodeClientError) {
174+
if (e.isContractRevert()) {
175+
throw predefined.CONTRACT_REVERT(e.detail || e.message, e.data);
176+
} else if (e.statusCode === 400) {
177+
throw predefined.COULD_NOT_SIMULATE_TRANSACTION(e.detail || e.message);
178+
}
180179
}
181-
return this.predefinedGasForTransaction(transaction, requestDetails, e);
180+
181+
// for any other error or Mirror Node upstream server errors (429, 500, 502, 503, 504, etc.),
182+
// preserve the original error and re-throw to the upper layer for further handling logic
183+
throw e;
182184
}
183185
}
184186

@@ -503,16 +505,14 @@ export class ContractService implements IContractService {
503505
return constants.EMPTY_HEX;
504506
}
505507

506-
if (e.isContractReverted()) {
507-
this.logger.trace(
508-
`mirror node eth_call request encountered contract revert. message: %s, details: %s, data: %s`,
509-
e.message,
510-
e.detail,
511-
e.data,
512-
);
513-
return predefined.CONTRACT_REVERT(e.detail || e.message, e.data);
508+
if (e.isContractRevert()) {
509+
throw predefined.CONTRACT_REVERT(e.detail || e.message, e.data);
510+
} else if (e.statusCode === 400) {
511+
throw predefined.COULD_NOT_SIMULATE_TRANSACTION(e.detail || e.message);
514512
}
515-
// for any other Mirror Node upstream server errors (429, 500, 502, 503, 504, etc.), preserve the original error and re-throw to the upper layer
513+
514+
// for any other error or Mirror Node upstream server errors (429, 500, 502, 503, 504, etc.),
515+
// preserve the original error and re-throw to the upper layer for further handling logic
516516
throw e;
517517
}
518518

@@ -536,68 +536,6 @@ export class ContractService implements IContractService {
536536
return predefined.INTERNAL_ERROR(e.message.toString());
537537
}
538538

539-
/**
540-
* Fallback calculations for the amount of gas to be used for a transaction.
541-
* This method is used when the mirror node fails to return a gas estimate.
542-
*
543-
* @param {IContractCallRequest} transaction The transaction data for the contract call.
544-
* @param {RequestDetails} requestDetails The request details for logging and tracking.
545-
* @param error (Optional) received error from the mirror-node contract call request.
546-
* @returns {Promise<string | JsonRpcError>} the calculated gas cost for the transaction
547-
*/
548-
private async predefinedGasForTransaction(
549-
transaction: IContractCallRequest,
550-
requestDetails: RequestDetails,
551-
error?: any,
552-
): Promise<string | JsonRpcError> {
553-
const isSimpleTransfer = !!transaction?.to && (!transaction.data || transaction.data === '0x');
554-
const isContractCall =
555-
!!transaction?.to && transaction?.data && transaction.data.length >= constants.FUNCTION_SELECTOR_CHAR_LENGTH;
556-
const isContractCreate = !transaction?.to && transaction?.data && transaction.data !== '0x';
557-
const contractCallAverageGas = numberTo0x(constants.TX_CONTRACT_CALL_AVERAGE_GAS);
558-
const gasTxBaseCost = numberTo0x(constants.TX_BASE_COST);
559-
560-
if (isSimpleTransfer) {
561-
// Handle Simple Transaction and Hollow Account creation
562-
const isZeroOrHigher = Number(transaction.value) >= 0;
563-
if (!isZeroOrHigher) {
564-
return predefined.INVALID_PARAMETER(
565-
0,
566-
`Invalid 'value' field in transaction param. Value must be greater than or equal to 0`,
567-
);
568-
}
569-
// when account exists return default base gas
570-
if (await this.common.getAccount(transaction.to!, requestDetails)) {
571-
this.logger.warn(`Returning predefined gas for simple transfer: ${gasTxBaseCost}`);
572-
return gasTxBaseCost;
573-
}
574-
const minGasTxHollowAccountCreation = numberTo0x(constants.MIN_TX_HOLLOW_ACCOUNT_CREATION_GAS);
575-
// otherwise, return the minimum amount of gas for hollow account creation
576-
this.logger.warn(`Returning predefined gas for hollow account creation: ${minGasTxHollowAccountCreation}`);
577-
return minGasTxHollowAccountCreation;
578-
} else if (isContractCreate) {
579-
// The size limit of the encoded contract posted to the mirror node can
580-
// cause contract deployment transactions to fail with a 400 response code.
581-
// The contract is actually deployed on the consensus node, so the contract will work.
582-
// In these cases, we don't want to return a CONTRACT_REVERT error.
583-
if (
584-
ConfigService.get('ESTIMATE_GAS_THROWS') &&
585-
error?.isContractReverted() &&
586-
error?.message !== MirrorNodeClientError.messages.INVALID_HEX
587-
) {
588-
return predefined.CONTRACT_REVERT(error.detail, error.data);
589-
}
590-
this.logger.warn(`Returning predefined gas for contract creation: %s`, gasTxBaseCost);
591-
return numberTo0x(Precheck.transactionIntrinsicGasCost(transaction.data!));
592-
} else if (isContractCall) {
593-
this.logger.warn(`Returning predefined gas for contract call: %s`, contractCallAverageGas);
594-
return contractCallAverageGas;
595-
} else {
596-
this.logger.warn(`Returning predefined gas for unknown transaction: %s`, this.defaultGas);
597-
return this.defaultGas;
598-
}
599-
}
600-
601539
/**
602540
* Prepares the call data for mirror node request.
603541
*

packages/relay/src/lib/services/ethService/ethCommonService/CommonService.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -458,7 +458,7 @@ export class CommonService implements ICommonService {
458458
}
459459
}
460460

461-
throw predefined.COULD_NOT_ESTIMATE_GAS_PRICE;
461+
throw predefined.INTERNAL_ERROR('Failed to retrieve gas price from network fees');
462462
}
463463

464464
/**

packages/relay/tests/helpers.ts

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -351,6 +351,58 @@ const mockData = {
351351
],
352352
},
353353
},
354+
355+
genericBadRequest: {
356+
_status: {
357+
messages: [
358+
{
359+
message: 'Bad request',
360+
detail: 'Invalid request parameters',
361+
data: '',
362+
},
363+
],
364+
},
365+
},
366+
367+
internalServerError: {
368+
_status: {
369+
messages: [
370+
{
371+
message: 'Internal Server Error',
372+
},
373+
],
374+
},
375+
},
376+
377+
badGateway: {
378+
_status: {
379+
messages: [
380+
{
381+
message: 'Bad Gateway',
382+
},
383+
],
384+
},
385+
},
386+
387+
serviceUnavailable: {
388+
_status: {
389+
messages: [
390+
{
391+
message: 'Service Unavailable',
392+
},
393+
],
394+
},
395+
},
396+
397+
gatewayTimeout: {
398+
_status: {
399+
messages: [
400+
{
401+
message: 'Gateway Timeout',
402+
},
403+
],
404+
},
405+
},
354406
};
355407

356408
export { expectUnsupportedMethod, expectedError, signTransaction, mockData, random20BytesAddress, getQueryParams };

0 commit comments

Comments
 (0)