Skip to content

Commit 6039a8e

Browse files
committed
feat: add MAX_GAS_ALLOWANCE_HBAR configuration and update related functionality
Signed-off-by: Giuseppe Bertone <[email protected]>
1 parent 27bcc1c commit 6039a8e

File tree

8 files changed

+67
-2
lines changed

8 files changed

+67
-2
lines changed

.env.http.example

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ OPERATOR_KEY_MAIN= # Operator private key used to sign transaction
4343
# FEE_HISTORY_MAX_RESULTS=10 # Maximum number of results to return for eth_feeHistory
4444
# TX_DEFAULT_GAS=400000 # Default gas for transactions that don't specify gas
4545
# MAX_TRANSACTION_FEE_THRESHOLD=15000000 # Max transaction fee paid by relay operator account
46+
# MAX_GAS_ALLOWANCE_HBAR=0 # The maximum amount, in hbars, that the relay is willing to pay to complete the transaction in case the senders don't provide enough funds.
4647

4748
# ========== CACHE CONFIGURATION ==========
4849
# CACHE_MAX=1000 # Maximum items in cache

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ config:
5353
# FEE_HISTORY_MAX_RESULTS:
5454
# TX_DEFAULT_GAS:
5555
# MAX_TRANSACTION_FEE_THRESHOLD:
56+
# MAX_GAS_ALLOWANCE_HBAR:
5657

5758
# ========== CACHE CONFIGURATION ==========
5859
# CACHE_MAX:

docs/configuration.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,7 @@ Unless you need to set a non-default value, it is recommended to only populate o
102102
| `TX_DEFAULT_GAS` | "400000" | Default gas for transactions that do not specify gas. |
103103
| `USE_ASYNC_TX_PROCESSING` | "true" | Set to `true` to enable `eth_sendRawTransaction` to return the transaction hash immediately after passing all prechecks, while processing the transaction asynchronously in the background. |
104104
| `MAX_TRANSACTION_FEE_THRESHOLD` | "15000000" | Used to set the max transaction fee. This is the HAPI fee which is paid by the relay operator account. |
105+
| `MAX_GAS_ALLOWANCE_HBAR` | "0" | The maximum amount, in hbars, that the relay is willing to pay to complete the transaction in case the senders don't provide enough funds to pay for their transactions. Please note, in case of full subsidized transactions, the sender must set the gas price to `0` and the relay must configure both the `GAS_PRICE_TINY_BAR_BUFFER`, to a number big enough to cover the discrepancy between the base gas price and `0`, and the `MAX_GAS_ALLOWANCE_HBAR` parameters, with the max amount of hbars the relay is willing to spend to execute the transaction. |
105106
| `USE_MIRROR_NODE_MODULARIZED_SERVICES` | null | Controls routing of Mirror Node traffic through modularized services. When set to `true`, enables routing a percentage of traffic to modularized services. When set to `false`, ensures traffic follows the traditional non-modularized flow. When not set (i.e. `null` by default), no specific routing preference is applied. As Mirror Node gradually transitions to a fully modularized architecture across all networks, this setting will eventually default to `true`. |
106107

107108
## Server

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

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -454,6 +454,12 @@ const _CONFIG = {
454454
required: false,
455455
defaultValue: 15_000_000,
456456
},
457+
MAX_GAS_ALLOWANCE_HBAR: {
458+
envName: 'MAX_GAS_ALLOWANCE_HBAR',
459+
type: 'number',
460+
required: false,
461+
defaultValue: 0,
462+
},
457463
MEMWATCH_ENABLED: {
458464
envName: 'MEMWATCH_ENABLED',
459465
type: 'boolean',

packages/relay/src/lib/clients/sdkClient.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,8 @@ export class SDKClient {
172172
),
173173
);
174174

175+
ethereumTransaction.setMaxGasAllowanceHbar(ConfigService.get('MAX_GAS_ALLOWANCE_HBAR'));
176+
175177
return {
176178
fileId,
177179
txResponse: await this.executeTransaction(

packages/relay/src/lib/constants.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -236,6 +236,7 @@ export default {
236236
},
237237

238238
MAX_TRANSACTION_FEE_THRESHOLD: ConfigService.get('MAX_TRANSACTION_FEE_THRESHOLD'),
239+
MAX_GAS_ALLOWANCE_HBAR: ConfigService.get('MAX_GAS_ALLOWANCE_HBAR'),
239240
SEND_RAW_TRANSACTION_SIZE_LIMIT: ConfigService.get('SEND_RAW_TRANSACTION_SIZE_LIMIT'),
240241
CONTRACT_CODE_SIZE_LIMIT: ConfigService.get('CONTRACT_CODE_SIZE_LIMIT'),
241242
CALL_DATA_SIZE_LIMIT: ConfigService.get('CALL_DATA_SIZE_LIMIT'),

packages/relay/src/lib/precheck.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
// SPDX-License-Identifier: Apache-2.0
22

3+
import { ConfigService } from '@hashgraph/json-rpc-config-service/dist/services';
34
import { ethers, Transaction } from 'ethers';
45
import { Logger } from 'pino';
56

@@ -169,10 +170,10 @@ export class Precheck {
169170
const passes = txGasPrice >= networkGasPrice || Precheck.isDeterministicDeploymentTransaction(tx);
170171

171172
if (!passes) {
172-
if (constants.GAS_PRICE_TINY_BAR_BUFFER) {
173+
if (ConfigService.get('GAS_PRICE_TINY_BAR_BUFFER')) {
173174
// Check if failure is within buffer range (Often it's by 1 tinybar) as network gasprice calculation can change slightly.
174175
// e.g gasPrice=1450000000000, requiredGasPrice=1460000000000, in which case we should allow users to go through and let the network check
175-
const txGasPriceWithBuffer = txGasPrice + BigInt(constants.GAS_PRICE_TINY_BAR_BUFFER);
176+
const txGasPriceWithBuffer = txGasPrice + BigInt(ConfigService.get('GAS_PRICE_TINY_BAR_BUFFER'));
176177
if (txGasPriceWithBuffer >= networkGasPrice) {
177178
return;
178179
}

packages/server/tests/acceptance/rpc_batch1.spec.ts

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import { expect } from 'chai';
2222
import { ethers } from 'ethers';
2323

2424
import { ConfigServiceTestHelper } from '../../../config-service/tests/configServiceTestHelper';
25+
import { withOverriddenEnvsInMochaTest } from '../../../relay/tests/helpers';
2526
import basicContract from '../../tests/contracts/Basic.json';
2627
import RelayCalls from '../../tests/helpers/constants';
2728
import MirrorClient from '../clients/mirrorClient';
@@ -1511,6 +1512,57 @@ describe('@api-batch-1 RPC Server Acceptance Tests', function () {
15111512
);
15121513
});
15131514

1515+
withOverriddenEnvsInMochaTest(
1516+
{
1517+
GAS_PRICE_TINY_BAR_BUFFER: 2000000000000,
1518+
MAX_GAS_ALLOWANCE_HBAR: 100,
1519+
},
1520+
() => {
1521+
it('should execute "eth_sendRawTransaction" and pays the total amount of the fees on behalf of the sender', async function () {
1522+
const balanceBefore = await relay.getBalance(accounts[2].wallet.address, 'latest', requestId);
1523+
1524+
const transaction = {
1525+
type: 1,
1526+
chainId: Number(CHAIN_ID),
1527+
nonce: await relay.getAccountNonce(accounts[2].wallet.address, requestId),
1528+
gasPrice: 0,
1529+
gasLimit: Constants.MAX_TRANSACTION_FEE_THRESHOLD,
1530+
data: '0x' + '00'.repeat(Constants.CONTRACT_CODE_SIZE_LIMIT),
1531+
};
1532+
const signedTx = await accounts[2].wallet.signTransaction(transaction);
1533+
const transactionHash = await relay.sendRawTransaction(signedTx, requestId);
1534+
const info = await mirrorNode.get(`/contracts/results/${transactionHash}`, requestId);
1535+
expect(info).to.have.property('contract_id');
1536+
expect(info.contract_id).to.not.be.null;
1537+
expect(info).to.have.property('created_contract_ids');
1538+
expect(info.created_contract_ids.length).to.be.equal(1);
1539+
1540+
const balanceAfter = await relay.getBalance(accounts[2].wallet.address, 'latest', requestId);
1541+
expect(balanceAfter).to.be.equal(balanceBefore);
1542+
1543+
const transaction2 = {
1544+
type: 2,
1545+
chainId: Number(CHAIN_ID),
1546+
nonce: await relay.getAccountNonce(accounts[2].wallet.address, requestId),
1547+
maxPriorityFeePerGas: 0,
1548+
maxFeePerGas: 0,
1549+
gasLimit: Constants.MAX_TRANSACTION_FEE_THRESHOLD,
1550+
data: '0x' + '00'.repeat(Constants.CONTRACT_CODE_SIZE_LIMIT),
1551+
};
1552+
const signedTx2 = await accounts[2].wallet.signTransaction(transaction2);
1553+
const transactionHash2 = await relay.sendRawTransaction(signedTx2, requestId);
1554+
const info2 = await mirrorNode.get(`/contracts/results/${transactionHash2}`, requestId);
1555+
expect(info2).to.have.property('contract_id');
1556+
expect(info2.contract_id).to.not.be.null;
1557+
expect(info2).to.have.property('created_contract_ids');
1558+
expect(info2.created_contract_ids.length).to.be.equal(1);
1559+
1560+
const balanceAfter2 = await relay.getBalance(accounts[2].wallet.address, 'latest', requestId);
1561+
expect(balanceAfter2).to.be.equal(balanceBefore);
1562+
});
1563+
},
1564+
);
1565+
15141566
describe('Prechecks', async function () {
15151567
it('should fail "eth_sendRawTransaction" for transaction with incorrect chain_id', async function () {
15161568
const transaction = {

0 commit comments

Comments
 (0)