Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 4 additions & 17 deletions packages/analyzer/src/txAnalyzer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,25 +40,12 @@ export class TxAnalyzer {

for (const address of contractsAddresses) {
const structLogsForAddress = getStructLogsForContractAddress(traceLogs, structlogs, address)
const dissasembleBytecode = this.dataLoader.analyzerContractData.get(address, 'disassembledBytecode')

// eslint-disable-next-line
const SOLC_BYTECODE_FLAG = true

if (SOLC_BYTECODE_FLAG) {
const isContractVerified = this.dataLoader.isContractVerified(address)
if (!isContractVerified) continue
}
const dissasembleBytecode = this.dataLoader.analyzerContractData.get(address, 'disassembledEtherscanBytecode')

structLogsForAddress.forEach((structLog: TIndexedStructLog) => {
try {
const operand = dissasembleBytecode[structLog?.pc]?.value || undefined
if (operand) {
structlogs[structLog.index].operand = operand
}
} catch (error) {
console.log(address)
// console.error('Error while extending struct logs with operand values', error)
const operand = dissasembleBytecode[structLog.pc]?.value || undefined
if (operand) {
structlogs[structLog.index].operand = operand
}
})
}
Expand Down
4 changes: 2 additions & 2 deletions packages/analyzer/src/utils/dataLoader.ts
Original file line number Diff line number Diff line change
Expand Up @@ -181,8 +181,8 @@ export class DataLoader {
),
contractsDisassembledBytecodes: Object.values(this.analyzerData.contracts).reduce<
TAnalyzerAnalysisOutput['contractsDisassembledBytecodes']
>((accumulator, { address, disassembledBytecode }) => {
accumulator[address] = { disassembledBytecode, address }
>((accumulator, { address, disassembledEtherscanBytecode }) => {
accumulator[address] = { disassembledBytecode: disassembledEtherscanBytecode, address }
return accumulator
}, {}),
contractsBaseData: Object.values(this.analyzerData.contracts).reduce<TAnalyzerAnalysisOutput['contractsBaseData']>(
Expand Down
2 changes: 1 addition & 1 deletion packages/analyzer/src/utils/functionManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ export class FunctionManager {
const initialContractFunctions = this.dataLoader.analyzerContractData.get(contractAddress, 'functions')
const contractFunctions: Record<number, TContractFunction> = { ...initialContractFunctions }

const dissasembledBytecode = this.dataLoader.analyzerContractData.get(contractAddress, 'disassembledBytecode')
const dissasembledBytecode = this.dataLoader.analyzerContractData.get(contractAddress, 'disassembledEtherscanBytecode')

const contractSourceFiles = this.dataLoader.analyzerContractData.get(contractAddress, 'sourceFiles')
const contractInstructions = this.dataLoader.analyzerContractData.get(contractAddress, 'instructions')
Expand Down
2 changes: 1 addition & 1 deletion packages/analyzer/src/utils/sourceLineParser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ export class SourceLineParser {

const uniqueSoruceMapsCodeLinesDictionary = createSourceMapToSourceCodeDictionary(contractSourceFiles, uniqueSourceMaps)

const disassembledBytecode = this.dataLoader.analyzerContractData.get(contractAddress, 'disassembledBytecode')
const disassembledBytecode = this.dataLoader.analyzerContractData.get(contractAddress, 'disassembledEtherscanBytecode')

const mapDisasemlbedBytecodeToIndex = Object.values(disassembledBytecode).reduce<Record<number, TDisassembledBytecodeStructlog>>(
(accumulator, disassembledBytecodeEntry, index) => {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { expectSaga } from 'redux-saga-test-plan'
import { ChainId } from '@evm-debuger/types'
import { combineReducers } from 'redux'
import * as matchers from 'redux-saga-test-plan/matchers'

import { transactionConfigActions, transactionConfigReducer } from '../../../transactionConfig/transactionConfig.slice'
import { analyzerActions, analyzerReducer } from '../../analyzer.slice'
Expand All @@ -11,10 +12,11 @@ import { AnalyzerStages, AnalyzerStagesStatus } from '../../analyzer.const'
import { createInfoLogMessage, createSuccessLogMessage } from '../../analyzer.utils'
import { createLogMessageActionForTests, mockLogsInAnalyer, testLogMessages } from '../../../../helpers/sagaTests'

import { initializeTransactionProcessingSaga } from './initializeTransactionProcessing.saga'
import { estimateGasUsage, initializeTransactionProcessingSaga } from './initializeTransactionProcessing.saga'

const TRANSACTION_HASH = '0x1234567890'
const CHAIN_ID = ChainId.mainnet
const GAS_USED = BigInt(1000)

describe('initializeTransactionProcessingSaga', () => {
it('should initialize transaction processing', async () => {
Expand Down Expand Up @@ -46,7 +48,7 @@ describe('initializeTransactionProcessingSaga', () => {
[StoreKeys.TRANSACTION_CONFIG]: {
...initialState[StoreKeys.TRANSACTION_CONFIG],
transactionHash: TRANSACTION_HASH,
gasUsed: '100000',
gasUsed: GAS_USED.toString(),
chainId: CHAIN_ID,
},
}
Expand All @@ -56,13 +58,15 @@ describe('initializeTransactionProcessingSaga', () => {
analyzerActions.initializeTransactionProcessing({ transactionHash: TRANSACTION_HASH, chainId: CHAIN_ID }),
)
.withReducer(combineReducers({ [StoreKeys.TRANSACTION_CONFIG]: transactionConfigReducer, [StoreKeys.ANALYZER]: analyzerReducer }))
.provide([[matchers.call.fn(estimateGasUsage), BigInt(1000)]])
.withState(initialState)
.put(analyzerActions.updateStage(inProgresStage))
.put.like({ action: addFirstLogAction })
.put(transactionConfigActions.setChainId({ chainId: CHAIN_ID }))
.put(transactionConfigActions.setTransactionHash({ transactionHash: TRANSACTION_HASH }))
.put.like({ action: addSecondLogAction })
.put(transactionConfigActions.setGasUsed({ gasUsed: '100000' }))
.call(estimateGasUsage, CHAIN_ID, TRANSACTION_HASH)
.put(transactionConfigActions.setGasUsed({ gasUsed: GAS_USED.toString() }))
.put(analyzerActions.updateStage(successStage))
.put.like({ action: addThirdLogAction })
.run()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,13 +37,13 @@ export function* initializeTransactionProcessingSaga({

yield* put(analyzerActions.addLogMessage(createInfoLogMessage('Calculating gas usage of transaction')))

// const gasUsed = yield* call(estimateGasUsage, chainId, transactionHash)
const gasUsed = yield* call(estimateGasUsage, chainId, transactionHash)

// if (gasUsed > BigInt(2000000)) {
// throw new Error(`Currently, we do not support transactions with over 2 milion gas usage. Your transaction used ${gasUsed} gas`)
// }
if (gasUsed > BigInt(2000000)) {
throw new Error(`Currently, we do not support transactions with over 2 milion gas usage. Your transaction used ${gasUsed} gas`)
}

yield* put(transactionConfigActions.setGasUsed({ gasUsed: '100000' }))
yield* put(transactionConfigActions.setGasUsed({ gasUsed: gasUsed.toString() }))

yield* put(analyzerActions.updateStage({ stageStatus: AnalyzerStagesStatus.SUCCESS, stageName: AnalyzerStages.INITIALIZING_ANALYZER }))
yield* put(analyzerActions.addLogMessage(createSuccessLogMessage('Analyzer initialized')))
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
import { expectSaga } from 'redux-saga-test-plan'
import * as matchers from 'redux-saga-test-plan/matchers'
import { ChainId } from '@evm-debuger/types'
import { combineReducers } from 'redux'

import { transactionConfigReducer } from '../../../transactionConfig/transactionConfig.slice'
import { analyzerActions, analyzerReducer } from '../../../analyzer/analyzer.slice'
import { TransactionConfigState } from '../../../transactionConfig/transactionConfig.state'
import { AnalyzerState, analyzerStagesAdapter } from '../../../analyzer/analyzer.state'
import { StoreKeys } from '../../../store.keys'
import { AnalyzerStages, AnalyzerStagesStatus } from '../../../analyzer/analyzer.const'
import { createInfoLogMessage, createSuccessLogMessage, getAnalyzerInstance } from '../../../analyzer/analyzer.utils'
import { createLogMessageActionForTests, mockLogsInAnalyer, testLogMessages } from '../../../../helpers/sagaTests'
import { createMockedContractBase } from '../../../contractBase/contractBase.mock'
import { contractBaseAdapter, contractBaseReducer } from '../../../contractBase/contractBase.slice'
import { createMockedContractRawData } from '../../contractRaw.mock'

import { fetchBytecode, fetchBytecodesSaga } from './fetchBytecodes.saga'

const TRANSACTION_HASH = '0x1234567890'
const CHAIN_ID = ChainId.mainnet

const mockedContractBase = createMockedContractBase()
const mockedContractRaw = createMockedContractRawData(mockedContractBase.address)
describe('fetchBytecodesSaga', () => {
it('should fetch bytecodes', async () => {
const analyzerInstance = getAnalyzerInstance()
analyzerInstance.dataLoader.setEmptyContracts([mockedContractBase.address])

const initialState = {
[StoreKeys.TRANSACTION_CONFIG]: { ...new TransactionConfigState(), transactionHash: TRANSACTION_HASH, chainId: CHAIN_ID },
[StoreKeys.CONTRACT_BASE]: contractBaseAdapter.addOne(contractBaseAdapter.getInitialState(), mockedContractBase),
[StoreKeys.ANALYZER]: { ...new AnalyzerState() },
}

const inProgresStage = { stageStatus: AnalyzerStagesStatus.IN_PROGRESS, stageName: AnalyzerStages.FETCHING_BYTECODES }
const successStage = { stageStatus: AnalyzerStagesStatus.SUCCESS, stageName: AnalyzerStages.FETCHING_BYTECODES }

const firstLogMessage = createInfoLogMessage('Fetching bytecodes')
const secondLogMessage = createSuccessLogMessage('Fetching bytecodes success')

const addFirstLogAction = createLogMessageActionForTests(analyzerActions.addLogMessage(firstLogMessage))
const addSecondLogAction = createLogMessageActionForTests(analyzerActions.addLogMessage(secondLogMessage))

const expectedState = {
...initialState,
[StoreKeys.ANALYZER]: {
...initialState[StoreKeys.ANALYZER],
stages: analyzerStagesAdapter.updateOne(initialState[StoreKeys.ANALYZER].stages, {
id: AnalyzerStages.FETCHING_BYTECODES,
changes: successStage,
}),
logMessages: mockLogsInAnalyer(),
},
}

const { storeState } = await expectSaga(fetchBytecodesSaga)
.withReducer(
combineReducers({
[StoreKeys.TRANSACTION_CONFIG]: transactionConfigReducer,
[StoreKeys.ANALYZER]: analyzerReducer,
[StoreKeys.CONTRACT_BASE]: contractBaseReducer,
}),
)
.withState(initialState)
.provide([
[matchers.call.fn(fetchBytecode), mockedContractRaw.etherscanBytecode],
[matchers.call.fn(getAnalyzerInstance), analyzerInstance],
])
.put.like({ action: addFirstLogAction })
.put(analyzerActions.updateStage(inProgresStage))
.call(getAnalyzerInstance)
.call(fetchBytecode, CHAIN_ID, mockedContractBase.address)
.put(analyzerActions.updateStage(successStage))
.put.like({ action: addSecondLogAction })
.run()

expect(storeState).toEqual(expectedState)
testLogMessages(storeState[StoreKeys.ANALYZER], [firstLogMessage, secondLogMessage])
})
})
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
/* eslint-disable no-return-await */
import { type SagaGenerator, put, call } from 'typed-redux-saga'
import { select, type SagaGenerator, put, call, apply } from 'typed-redux-saga'
import type { ChainId } from '@evm-debuger/types'

import { jsonRpcProvider } from '../../../../config'
import { transactionConfigSelectors } from '../../../transactionConfig/transactionConfig.selectors'
import { analyzerActions } from '../../../analyzer/analyzer.slice'
import { AnalyzerStages, AnalyzerStagesStatus } from '../../../analyzer/analyzer.const'
import { createInfoLogMessage, createSuccessLogMessage } from '../../../analyzer/analyzer.utils'
import { createInfoLogMessage, createSuccessLogMessage, getAnalyzerInstance } from '../../../analyzer/analyzer.utils'
import { contractBaseSelectors } from '../../../contractBase/contractBase.selectors'
import { handleStageFailSaga } from '../../../analyzer/saga/handleStageFail/handleStageFail.saga'

export async function fetchBytecode(chainId: ChainId, address: string): Promise<string> {
Expand All @@ -18,15 +20,15 @@ export function* fetchBytecodesSaga(): SagaGenerator<void> {
yield* put(analyzerActions.addLogMessage(createInfoLogMessage('Fetching bytecodes')))
yield* put(analyzerActions.updateStage({ stageStatus: AnalyzerStagesStatus.IN_PROGRESS, stageName: AnalyzerStages.FETCHING_BYTECODES }))

// const chainId = yield* select(transactionConfigSelectors.selectChainId)
// const contractAddresses = yield* select(contractBaseSelectors.selectAllAddresses)
const chainId = yield* select(transactionConfigSelectors.selectChainId)
const contractAddresses = yield* select(contractBaseSelectors.selectAllAddresses)

// const analyzer = yield* call(getAnalyzerInstance)
const analyzer = yield* call(getAnalyzerInstance)

// for (const address of contractAddresses) {
// const bytecode = yield* call(fetchBytecode, chainId, address)
// yield* apply(analyzer.dataLoader, analyzer.dataLoader.inputContractData.set, [address, 'etherscanBytecode', bytecode])
// }
for (const address of contractAddresses) {
const bytecode = yield* call(fetchBytecode, chainId, address)
yield* apply(analyzer.dataLoader, analyzer.dataLoader.inputContractData.set, [address, 'etherscanBytecode', bytecode])
}

yield* put(
analyzerActions.updateStage({
Expand Down