Skip to content

Commit cc60f05

Browse files
authored
configurable eth_call accepted errors (#1264)
* make accepted error codes from mirror node for eth_call configurable and added initial default ones Signed-off-by: Alfredo Gutierrez <[email protected]> * fixed test Signed-off-by: Alfredo Gutierrez <[email protected]> * Added more logs and returned error instead of 0x when request to mirror node returns null Signed-off-by: Alfredo Gutierrez <[email protected]> * Removed returning CONTRACT_REVERT when returning null and indeed returning 0x when receiving null from the mirror node. Signed-off-by: Alfredo Gutierrez <[email protected]> * fixed acceptance test that were failing Signed-off-by: Alfredo Gutierrez <[email protected]> * fake push Signed-off-by: Alfredo Gutierrez <[email protected]> * PR Review suggestions=: Removed leftover comments, added unit test for handleError class and improved modified test to make sure the sdk was not called. Signed-off-by: Alfredo Gutierrez <[email protected]> * removed leftover comment Signed-off-by: Alfredo Gutierrez <[email protected]> * removed leftover comment Signed-off-by: Alfredo Gutierrez <[email protected]> --------- Signed-off-by: Alfredo Gutierrez <[email protected]>
1 parent a429072 commit cc60f05

File tree

6 files changed

+60
-41
lines changed

6 files changed

+60
-41
lines changed

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

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ export class MirrorNodeClient {
9797
[MirrorNodeClient.GET_NETWORK_FEES_ENDPOINT, [400, 404]],
9898
[MirrorNodeClient.GET_TOKENS_ENDPOINT, [400, 404]],
9999
[MirrorNodeClient.GET_TRANSACTIONS_ENDPOINT, [400, 404]],
100-
[MirrorNodeClient.CONTRACT_CALL_ENDPOINT, []],
100+
[MirrorNodeClient.CONTRACT_CALL_ENDPOINT, [400,404,415,429,500]],
101101
[MirrorNodeClient.GET_STATE_ENDPOINT, [400, 404]]
102102
]);
103103

@@ -228,6 +228,13 @@ export class MirrorNodeClient {
228228

229229
this.logger.info(`Mirror Node client successfully configured to REST url: ${this.restUrl} and Web3 url: ${this.web3Url} `);
230230
this.cache = new LRU({ max: constants.CACHE_MAX, ttl: constants.CACHE_TTL.ONE_HOUR });
231+
232+
// set up eth call accepted error codes.
233+
if(process.env.ETH_CALL_ACCEPTED_ERRORS) {
234+
MirrorNodeClient.acceptedErrorStatusesResponsePerRequestPathMap
235+
.set(MirrorNodeClient.CONTRACT_CALL_ENDPOINT, JSON.parse(process.env.ETH_CALL_ACCEPTED_ERRORS));
236+
}
237+
231238
}
232239

233240
private buildUrl(baseUrl: string) {
@@ -297,6 +304,9 @@ export class MirrorNodeClient {
297304
const acceptedErrorResponses = MirrorNodeClient.acceptedErrorStatusesResponsePerRequestPathMap.get(pathLabel);
298305
if (error.response && acceptedErrorResponses && acceptedErrorResponses.indexOf(effectiveStatusCode) !== -1) {
299306
this.logger.debug(`${requestIdPrefix} [${method}] ${path} ${effectiveStatusCode} status`);
307+
if(pathLabel === MirrorNodeClient.CONTRACT_CALL_ENDPOINT) {
308+
this.logger.warn(`${requestIdPrefix} [${method}] ${path} Error details: (StatusText: '${error.response.statusText}' Data: '${JSON.stringify(error.response.data)}'"')`);
309+
}
300310
return null;
301311
}
302312

packages/relay/src/lib/eth.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1163,7 +1163,7 @@ export class EthImpl implements Eth {
11631163
gas,
11641164
value,
11651165
estimate: false
1166-
}
1166+
};
11671167

11681168
const contractCallResponse = await this.mirrorNodeClient.postContractCall(callData, requestId);
11691169
return contractCallResponse && contractCallResponse.result ? EthImpl.prepend0x(contractCallResponse.result) : EthImpl.emptyHex;

packages/relay/tests/lib/eth.spec.ts

Lines changed: 3 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3389,18 +3389,10 @@ describe('Eth calls using MirrorNode', async function () {
33893389
]
33903390
}
33913391
});
3392-
3393-
sdkClientStub.submitContractCallQueryWithRetry.returns({
3394-
asBytes: function () {
3395-
return Uint8Array.of(0);
3396-
}
3397-
}
3398-
);
3399-
3392+
sinon.reset();
34003393
const result = await ethImpl.call(callData, 'latest');
3401-
3402-
sinon.assert.calledWith(sdkClientStub.submitContractCallQueryWithRetry, contractAddress2, contractCallData, maxGasLimit, accountAddress1, 'eth_call');
3403-
expect(result).to.equal("0x00");
3394+
sinon.assert.notCalled(sdkClientStub.submitContractCallQueryWithRetry);
3395+
expect(result).to.equal("0x");
34043396
});
34053397

34063398
it('caps gas at 15_000_000', async function () {

packages/relay/tests/lib/mirrorNodeClient.spec.ts

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,10 @@ import {mockData, random20BytesAddress} from './../helpers';
3131
const registry = new Registry();
3232

3333
import pino from 'pino';
34+
import Constants from "../../src/lib/constants";
3435
const logger = pino();
3536

37+
3638
describe('MirrorNodeClient', async function () {
3739
this.timeout(20000);
3840

@@ -55,6 +57,36 @@ describe('MirrorNodeClient', async function () {
5557
mock = new MockAdapter(instance);
5658
});
5759

60+
describe('handleError', async() => {
61+
62+
const CONTRACT_CALL_ENDPOINT = 'contracts/call';
63+
const nullResponseCodes = [400,404,415,429,500];
64+
const errorRepsonseCodes = [501, 503];
65+
66+
for (const code of nullResponseCodes) {
67+
it(`returns null when ${code} is returned`, async () => {
68+
let error = new Error('test error');
69+
error["response"] = "test error";
70+
71+
const result = await mirrorNodeInstance.handleError(error, CONTRACT_CALL_ENDPOINT, CONTRACT_CALL_ENDPOINT, code, 'POST');
72+
expect(result).to.equal(null);
73+
});
74+
}
75+
76+
for (const code of errorRepsonseCodes) {
77+
it(`throws an error when ${code} is returned`, async () => {
78+
try {
79+
let error = new Error('test error');
80+
error["response"] = "test error";
81+
await mirrorNodeInstance.handleError(error, CONTRACT_CALL_ENDPOINT, CONTRACT_CALL_ENDPOINT, code, 'POST');
82+
expect.fail('should have thrown an error');
83+
} catch (e) {
84+
expect(e.message).to.equal('test error');
85+
}
86+
});
87+
}
88+
});
89+
5890
it('Can extract the account number out of an account pagination next link url', async () => {
5991
const accountId = '0.0.123';
6092
const url = `/api/v1/accounts/${accountId}?limit=100&timestamp=lt:1682455406.562695326`;

packages/server/tests/acceptance/htsPrecompile/precompileCalls.spec.ts

Lines changed: 5 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -738,14 +738,11 @@ describe('@precompile-calls Tests for eth_call with HTS', async function () {
738738
data: CALLDATA_ALLOWANCE + NON_EXISTING_ACCOUNT.padStart(64, '0') + account2LongZero.replace('0x', '').padStart(64, '0')
739739
};
740740

741-
await relay.callFailing(
742-
'eth_call',
743-
[callData, 'latest'],
744-
predefined.CONTRACT_REVERT(),
745-
requestId
746-
);
741+
const res = await relay.call('eth_call', [callData, 'latest'], requestId);
742+
expect(res).to.eq('0x'); // confirm no error
747743
});
748744

745+
749746
it("Call to allowance method of an HTS token with non-existing spender account in call data returns error", async () => {
750747
const callData = {
751748
from: '0x' + accounts[0].address,
@@ -754,12 +751,8 @@ describe('@precompile-calls Tests for eth_call with HTS', async function () {
754751
data: CALLDATA_ALLOWANCE + adminAccountLongZero.replace('0x', '').padStart(64, '0') + NON_EXISTING_ACCOUNT.padStart(64, '0')
755752
};
756753

757-
await relay.callFailing(
758-
'eth_call',
759-
[callData, 'latest'],
760-
predefined.CONTRACT_REVERT(),
761-
requestId
762-
);
754+
const res = await relay.call('eth_call', [callData, 'latest'], requestId);
755+
expect(res).to.eq('0x'); // confirm no error
763756
});
764757
});
765758
});

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

Lines changed: 8 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -348,7 +348,8 @@ describe('@api-batch-3 RPC Server Acceptance Tests', function () {
348348
data: '0x3ec4de3800000000000000000000000067d8d32e9bf1a9968a5ff53b87d777aa8ebbee69'
349349
};
350350

351-
await relay.callFailing('eth_call', [callData, 'latest'], predefined.CONTRACT_REVERT(), requestId);
351+
const res = await relay.call('eth_call', [callData, 'latest'], requestId);
352+
expect(res).to.eq('0x'); // confirm no error
352353
});
353354

354355
it("007 'data' from request body with wrong encoded parameter", async function () {
@@ -423,11 +424,8 @@ describe('@api-batch-3 RPC Server Acceptance Tests', function () {
423424
data: PURE_METHOD_CALL_DATA
424425
};
425426

426-
await relay.callFailing('eth_call', [callData, 'latest'], {
427-
code: -32008,
428-
message: PURE_METHOD_ERROR_MESSAGE,
429-
data: PURE_METHOD_ERROR_DATA
430-
}, requestId);
427+
const res = await relay.call('eth_call', [callData, 'latest'], requestId);
428+
expect(res).to.eq('0x'); // confirm no error
431429
});
432430

433431
it('Returns revert message for view methods', async () => {
@@ -438,11 +436,8 @@ describe('@api-batch-3 RPC Server Acceptance Tests', function () {
438436
data: VIEW_METHOD_CALL_DATA
439437
};
440438

441-
await relay.callFailing('eth_call', [callData, 'latest'], {
442-
code: -32008,
443-
message: VIEW_METHOD_ERROR_MESSAGE,
444-
data: VIEW_METHOD_ERROR_DATA
445-
}, requestId);
439+
const res = await relay.call('eth_call', [callData, 'latest'], requestId);
440+
expect(res).to.eq('0x'); // confirm no error
446441
});
447442

448443
it('Returns revert reason in receipt for payable methods', async () => {
@@ -590,11 +585,8 @@ describe('@api-batch-3 RPC Server Acceptance Tests', function () {
590585
data: pureMethodsData[i].data
591586
};
592587

593-
await relay.callFailing('eth_call', [callData, 'latest'], {
594-
code: -32008,
595-
message: pureMethodsData[i].message,
596-
data: pureMethodsData[i].errorData
597-
}, requestId);
588+
const res = await relay.call('eth_call', [callData, 'latest'], requestId);
589+
expect(res).to.eq('0x'); // confirm no error
598590
});
599591
}
600592
});

0 commit comments

Comments
 (0)