1
1
// SPDX-License-Identifier: Apache-2.0
2
2
import { disassemble } from '@ethersproject/asm' ;
3
3
import { ConfigService } from '@hashgraph/json-rpc-config-service/dist/services' ;
4
- import { PrecheckStatusError } from '@hashgraph/sdk' ;
5
4
import crypto from 'crypto' ;
6
5
import { Logger } from 'pino' ;
7
6
@@ -19,16 +18,9 @@ import constants from '../../constants';
19
18
import { JsonRpcError , predefined } from '../../errors/JsonRpcError' ;
20
19
import { MirrorNodeClientError } from '../../errors/MirrorNodeClientError' ;
21
20
import { SDKClientError } from '../../errors/SDKClientError' ;
22
- import { EthImpl } from '../../eth' ;
23
21
import { Log } from '../../model' ;
24
22
import { Precheck } from '../../precheck' ;
25
- import {
26
- IContractCallRequest ,
27
- IContractCallResponse ,
28
- IContractResult ,
29
- IGetLogsParams ,
30
- RequestDetails ,
31
- } from '../../types' ;
23
+ import { IContractCallRequest , IContractCallResponse , IGetLogsParams , RequestDetails } from '../../types' ;
32
24
import { CommonService } from '..' ;
33
25
import { CacheService } from '../cacheService/cacheService' ;
34
26
import { ICommonService } from '../ethService/ethCommonService/ICommonService' ;
@@ -260,26 +252,26 @@ export class ContractService implements IContractService {
260
252
if ( ! blockInfo || parseFloat ( result . entity ?. created_timestamp ) > parseFloat ( blockInfo . timestamp . to ) ) {
261
253
return constants . EMPTY_HEX ;
262
254
}
263
- if ( result ? .type === constants . TYPE_TOKEN ) {
255
+ if ( result . type === constants . TYPE_TOKEN ) {
264
256
if ( this . logger . isLevelEnabled ( 'trace' ) ) {
265
257
this . logger . trace ( `${ requestIdPrefix } Token redirect case, return redirectBytecode` ) ;
266
258
}
267
259
return CommonService . redirectBytecodeAddressReplace ( address ) ;
268
- } else if ( result ? .type === constants . TYPE_CONTRACT ) {
269
- if ( result ? .entity . runtime_bytecode !== constants . EMPTY_HEX ) {
260
+ } else if ( result . type === constants . TYPE_CONTRACT ) {
261
+ if ( result . entity . runtime_bytecode !== constants . EMPTY_HEX ) {
270
262
const prohibitedOpcodes = [ 'CALLCODE' , 'DELEGATECALL' , 'SELFDESTRUCT' , 'SUICIDE' ] ;
271
263
const opcodes = disassemble ( result ?. entity . runtime_bytecode ) ;
272
264
const hasProhibitedOpcode =
273
265
opcodes . filter ( ( opcode ) => prohibitedOpcodes . indexOf ( opcode . opcode . mnemonic ) > - 1 ) . length > 0 ;
274
266
if ( ! hasProhibitedOpcode ) {
275
267
await this . cacheService . set (
276
268
cachedLabel ,
277
- result ? .entity . runtime_bytecode ,
269
+ result . entity . runtime_bytecode ,
278
270
constants . ETH_GET_CODE ,
279
271
requestDetails ,
280
272
) ;
281
273
}
282
- return result ? .entity . runtime_bytecode ;
274
+ return result . entity . runtime_bytecode ;
283
275
}
284
276
}
285
277
}
@@ -665,37 +657,6 @@ export class ContractService implements IContractService {
665
657
666
658
return gas ;
667
659
}
668
- /**
669
- * Attempts to get code from cache and mirror node.
670
- *
671
- * @param {string } address - The contract address
672
- * @param {string | null } blockNumber - Block number or tag
673
- * @param {RequestDetails } requestDetails - The request details
674
- * @returns {Promise<string | null> } The contract code if found, null otherwise
675
- * @private
676
- */
677
- private async getCodeWithCache (
678
- address : string ,
679
- blockNumber : string | null ,
680
- requestDetails : RequestDetails ,
681
- ) : Promise < string | null > {
682
- const cachedLabel = `getCode.${ address } .${ blockNumber } ` ;
683
- const cachedResponse : string | undefined = await this . cacheService . getAsync (
684
- cachedLabel ,
685
- constants . ETH_GET_CODE ,
686
- requestDetails ,
687
- ) ;
688
- if ( cachedResponse != undefined ) {
689
- return cachedResponse ;
690
- }
691
-
692
- const mirrorNodeResult = await this . tryGetCodeFromMirrorNode ( address , blockNumber , cachedLabel , requestDetails ) ;
693
- if ( mirrorNodeResult ) {
694
- return mirrorNodeResult ;
695
- }
696
-
697
- return null ;
698
- }
699
660
700
661
/**
701
662
* Handles errors from consensus node calls.
@@ -718,63 +679,6 @@ export class ContractService implements IContractService {
718
679
}
719
680
return predefined . INTERNAL_ERROR ( e . message . toString ( ) ) ;
720
681
}
721
-
722
- /**
723
- * Processes and caches contract bytecode if it doesn't contain prohibited opcodes.
724
- *
725
- * @param {IContractResult } result - The contract result containing bytecode
726
- * @param {string } cachedLabel - The cache key to store the bytecode
727
- * @param {RequestDetails } requestDetails - The request details for logging and tracking
728
- * @returns {Promise<string | null> } The runtime bytecode if valid, null otherwise
729
- * @private
730
- */
731
- private async handleContractBytecode (
732
- result : IContractResult ,
733
- cachedLabel : string ,
734
- requestDetails : RequestDetails ,
735
- ) : Promise < string | null > {
736
- if ( result ?. entity . runtime_bytecode !== constants . EMPTY_HEX ) {
737
- if ( ! this . hasProhibitedOpcodes ( result . entity . runtime_bytecode ) ) {
738
- await this . cacheService . set (
739
- cachedLabel ,
740
- result . entity . runtime_bytecode ,
741
- constants . ETH_GET_CODE ,
742
- requestDetails ,
743
- ) ;
744
- return result . entity . runtime_bytecode ;
745
- }
746
- }
747
- return constants . EMPTY_HEX ;
748
- }
749
-
750
- /**
751
- * Handles errors that occur during getCode operations.
752
- *
753
- * @param {any } e - The error to handle
754
- * @param {string } address - The contract address
755
- * @param {string | null } blockNumber - The block number or tag
756
- * @param {string } requestIdPrefix - The request ID prefix for logging
757
- * @returns {string | never } The error response or throws if unhandled
758
- * @private
759
- */
760
- private handleGetCodeError (
761
- e : any ,
762
- address : string ,
763
- blockNumber : string | null ,
764
- requestIdPrefix : string ,
765
- ) : string | never {
766
- if ( e instanceof SDKClientError ) {
767
- return this . handleSDKClientError ( e , address , blockNumber , requestIdPrefix ) ;
768
- }
769
-
770
- if ( e instanceof PrecheckStatusError ) {
771
- return this . handlePrecheckStatusError ( e , address , blockNumber , requestIdPrefix ) ;
772
- }
773
-
774
- this . logger . error ( e , `${ requestIdPrefix } Error raised during getCode for address ${ address } ` ) ;
775
- throw e ;
776
- }
777
-
778
682
/**
779
683
* Handles specific mirror node client errors.
780
684
*
@@ -839,127 +743,6 @@ export class ContractService implements IContractService {
839
743
return predefined . INTERNAL_ERROR ( e . message . toString ( ) ) ;
840
744
}
841
745
842
- /**
843
- * Handles precheck status errors during contract operations.
844
- *
845
- * @param {PrecheckStatusError } e - The precheck status error
846
- * @param {string } address - The contract address
847
- * @param {string | null } blockNumber - The block number or tag
848
- * @param {string } requestIdPrefix - The request ID prefix for logging
849
- * @returns {string | never } The empty hex string for known errors or throws
850
- * @private
851
- */
852
- private handlePrecheckStatusError (
853
- e : PrecheckStatusError ,
854
- address : string ,
855
- blockNumber : string | null ,
856
- requestIdPrefix : string ,
857
- ) : string | never {
858
- if (
859
- e . status . _code === constants . PRECHECK_STATUS_ERROR_STATUS_CODES . INVALID_CONTRACT_ID ||
860
- e . status . _code === constants . PRECHECK_STATUS_ERROR_STATUS_CODES . CONTRACT_DELETED
861
- ) {
862
- if ( this . logger . isLevelEnabled ( 'debug' ) ) {
863
- this . logger . debug (
864
- `${ requestIdPrefix } Unable to find code for contract ${ address } in block "${ blockNumber } ", returning 0x0, err code: ${ e . status . _code } ` ,
865
- ) ;
866
- }
867
- return constants . EMPTY_HEX ;
868
- }
869
-
870
- this . hapiService . decrementErrorCounter ( e . status . _code ) ;
871
- this . logger . error (
872
- e ,
873
- `${ requestIdPrefix } Error raised during getCode for address ${ address } , err code: ${ e . status . _code } ` ,
874
- ) ;
875
- throw e ;
876
- }
877
-
878
- /**
879
- * Handles SDK client errors during contract operations.
880
- *
881
- * @param {SDKClientError } e - The SDK client error
882
- * @param {string } address - The contract address
883
- * @param {string | null } blockNumber - The block number or tag
884
- * @param {string } requestIdPrefix - The request ID prefix for logging
885
- * @returns {string | never } The empty hex string for known errors or throws
886
- * @private
887
- */
888
- private handleSDKClientError (
889
- e : SDKClientError ,
890
- address : string ,
891
- blockNumber : string | null ,
892
- requestIdPrefix : string ,
893
- ) : string | never {
894
- if ( e . isInvalidContractId ( ) || e . isContractDeleted ( ) ) {
895
- if ( this . logger . isLevelEnabled ( 'debug' ) ) {
896
- this . logger . debug (
897
- `${ requestIdPrefix } Unable to find code for contract ${ address } in block "${ blockNumber } ", returning 0x0, err code: ${ e . statusCode } ` ,
898
- ) ;
899
- }
900
- return constants . EMPTY_HEX ;
901
- }
902
-
903
- this . hapiService . decrementErrorCounter ( e . statusCode ) ;
904
- this . logger . error (
905
- e ,
906
- `${ requestIdPrefix } Error raised during getCode for address ${ address } , err code: ${ e . statusCode } ` ,
907
- ) ;
908
- throw e ;
909
- }
910
-
911
- /**
912
- * Handles token redirect cases by generating appropriate bytecode.
913
- *
914
- * @param {string } address - The token address
915
- * @param {string } requestIdPrefix - The request ID prefix for logging
916
- * @returns {string } The redirect bytecode for the token
917
- * @private
918
- */
919
- private handleTokenRedirect ( address : string , requestIdPrefix : string ) : string {
920
- const redirectBytecodePostfix =
921
- '600052366000602037600080366018016008845af43d806000803e8160008114605857816000f35b816000fdfea2646970667358221220d8378feed472ba49a0005514ef7087017f707b45fb9bf56bb81bb93ff19a238b64736f6c634300080b0033' ;
922
- const redirectBytecodePrefix = '6080604052348015600f57600080fd5b506000610167905077618dc65e' ;
923
-
924
- if ( this . logger . isLevelEnabled ( 'trace' ) ) {
925
- this . logger . trace ( `${ requestIdPrefix } Token redirect case, return redirectBytecode` ) ;
926
- }
927
- return `${ redirectBytecodePrefix } ${ address . slice ( 2 ) } ${ redirectBytecodePostfix } ` ;
928
- }
929
-
930
- /**
931
- * Checks if the provided bytecode contains any prohibited EVM opcodes.
932
- *
933
- * @param {string } bytecode - The bytecode to check
934
- * @returns {boolean } True if prohibited opcodes are found, false otherwise
935
- * @private
936
- */
937
- private hasProhibitedOpcodes ( bytecode : string ) : boolean {
938
- const prohibitedOpcodes = [ 'CALLCODE' , 'DELEGATECALL' , 'SELFDESTRUCT' , 'SUICIDE' ] ;
939
- const opcodes = disassemble ( bytecode ) ;
940
- return opcodes . filter ( ( opcode ) => prohibitedOpcodes . indexOf ( opcode . opcode . mnemonic ) > - 1 ) . length > 0 ;
941
- }
942
-
943
- /**
944
- * Checks if the address is the HTS precompile address.
945
- *
946
- * @param {string } address - The address to check
947
- * @param {string } requestIdPrefix - The request ID prefix for logging
948
- * @returns {boolean } True if address is HTS precompile
949
- * @private
950
- */
951
- private isHTSPrecompile ( address : string , requestIdPrefix : string ) : boolean {
952
- if ( address === constants . HTS_ADDRESS ) {
953
- if ( this . logger . isLevelEnabled ( 'trace' ) ) {
954
- this . logger . trace (
955
- `${ requestIdPrefix } HTS precompile case, return ${ constants . INVALID_EVM_INSTRUCTION } for byte code` ,
956
- ) ;
957
- }
958
- return true ;
959
- }
960
- return false ;
961
- }
962
-
963
746
/**
964
747
* Fallback calculations for the amount of gas to be used for a transaction.
965
748
* This method is used when the mirror node fails to return a gas estimate.
@@ -1113,46 +896,6 @@ export class ContractService implements IContractService {
1113
896
return cachedResponse === null ? undefined : cachedResponse ;
1114
897
}
1115
898
1116
- /**
1117
- * Attempts to retrieve contract code from the mirror node.
1118
- *
1119
- * @param {string } address - The contract address
1120
- * @param {string | null } blockNumber - The block number or tag
1121
- * @param {string } cachedLabel - The cache key for storing results
1122
- * @param {RequestDetails } requestDetails - The request details for logging and tracking
1123
- * @returns {Promise<string | null> } The contract code if found, null otherwise
1124
- * @private
1125
- */
1126
- private async tryGetCodeFromMirrorNode (
1127
- address : string ,
1128
- blockNumber : string | null ,
1129
- cachedLabel : string ,
1130
- requestDetails : RequestDetails ,
1131
- ) : Promise < string | null > {
1132
- const result = await this . mirrorNodeClient . resolveEntityType ( address , constants . ETH_GET_CODE , requestDetails , [
1133
- constants . TYPE_CONTRACT ,
1134
- constants . TYPE_TOKEN ,
1135
- ] ) ;
1136
-
1137
- if ( ! result ) return null ;
1138
-
1139
- // Check if contract was created after the requested block
1140
- const blockInfo = await this . common . getHistoricalBlockResponse ( requestDetails , blockNumber , true ) ;
1141
- if ( ! blockInfo || parseFloat ( result . entity ?. created_timestamp ) > parseFloat ( blockInfo . timestamp . to ) ) {
1142
- return constants . EMPTY_HEX ;
1143
- }
1144
-
1145
- if ( result . type === constants . TYPE_TOKEN ) {
1146
- return this . handleTokenRedirect ( address , requestDetails . formattedRequestId ) ;
1147
- }
1148
-
1149
- if ( result . type === constants . TYPE_CONTRACT ) {
1150
- return await this . handleContractBytecode ( result , cachedLabel , requestDetails ) ;
1151
- }
1152
-
1153
- return constants . EMPTY_HEX ;
1154
- }
1155
-
1156
899
/**
1157
900
* Validates the from and to addresses in the call request.
1158
901
*
0 commit comments