|
1 | 1 | import { Disassembler } from './Disassembler' |
2 | 2 | import { Operation } from './Operation' |
3 | 3 | import { Opcodes } from './Opcodes' |
4 | | -import { injectable } from 'inversify' |
| 4 | +import { injectable, inject } from 'inversify' |
5 | 5 | import { Opcode } from './Opcode' |
6 | 6 | import { DisassembledContract } from './DisassembledContract' |
7 | 7 | import { logger } from '../../Logger'; |
| 8 | +import { TYPES } from '../../inversify/types'; |
| 9 | +import { ContractService } from '../service/service/ContractService'; |
8 | 10 | let BN = require('bn.js') |
9 | | -let solc = require('solc') |
10 | | -let fs = require('fs') |
11 | | -let nodePath = require('path') |
| 11 | + |
12 | 12 |
|
13 | 13 | @injectable() |
14 | 14 | export class EVMDisassembler implements Disassembler { |
15 | 15 | static readonly metadataPrefix = 'a165627a7a72305820' |
16 | 16 |
|
17 | | - constructor() {} |
| 17 | + constructor( |
| 18 | + @inject(TYPES.ContractService) private contractService: ContractService |
| 19 | + ) {} |
18 | 20 |
|
19 | 21 | disassembleSourceCode(contractName: string, source: string, path: string): DisassembledContract { |
20 | 22 | if (source.startsWith('0x')) { |
21 | 23 | return this.disassembleContract(source) |
22 | 24 | } |
23 | | - const compileJson = this.generateCompileObject(contractName, source, path) |
24 | | - const compiledContract = JSON.parse(solc.compileStandardWrapper(JSON.stringify(compileJson))) |
25 | | - const contractWithExt = `${contractName}.sol` |
26 | | - const contract = compiledContract.contracts[contractWithExt][contractName] |
27 | | - if (!contract) { |
28 | | - throw new Error('Bad source code') |
29 | | - } |
| 25 | + |
| 26 | + const contract = this.contractService.compileContract(contractName, source, path) |
| 27 | + |
| 28 | + |
30 | 29 | const bytecode = contract.evm.bytecode.object |
31 | | - const runtimeBytecode = compiledContract.contracts[contractWithExt][contractName].evm.deployedBytecode.object |
32 | | - const contractAssembly = compiledContract.contracts[contractWithExt][contractName].evm.legacyAssembly |
| 30 | + const runtimeBytecode = contract.evm.deployedBytecode.object |
| 31 | + const contractAssembly = contract.evm.legacyAssembly |
33 | 32 | if (!contractAssembly) { |
34 | | - logger.error(JSON.stringify(compiledContract)) |
| 33 | + logger.error(JSON.stringify(contract)) |
35 | 34 | throw new Error(`No code found in contract ${contractName}`) |
36 | 35 | } |
37 | 36 | const asmRuntime = contractAssembly['.data'][0]['.code'].filter(elem => elem.name !== 'tag') |
38 | | - const asmConstructor = compiledContract.contracts[contractWithExt][contractName].evm.legacyAssembly['.code'].filter( |
| 37 | + const asmConstructor = contract.evm.legacyAssembly['.code'].filter( |
39 | 38 | elem => elem.name !== 'tag' |
40 | 39 | ) |
41 | 40 | const disassembledCode: DisassembledContract = this.disassembleContract(bytecode) |
@@ -164,75 +163,7 @@ export class EVMDisassembler implements Disassembler { |
164 | 163 | } as Operation |
165 | 164 | } |
166 | 165 |
|
167 | | - private findImports(sources: any, content: string, path: string, filesChecked: string[], initialPath: string) { |
168 | | - const regexp = /import "(.*)"|import '(.*)'/g |
169 | | - const match = content.match(regexp) |
170 | | - if (!match) { |
171 | | - return |
172 | | - } |
173 | | - const matches = match.map(imp => { |
174 | | - const splittedImp = imp.split('"') |
175 | | - if (splittedImp.length < 2) { |
176 | | - return imp.split("'")[1] |
177 | | - } else { |
178 | | - return splittedImp[1] |
179 | | - } |
180 | | - }) |
181 | | - |
182 | | - for (const imp of matches) { |
183 | | - let importFilePath = path |
184 | | - if (!importFilePath.endsWith(nodePath.sep)) { |
185 | | - importFilePath = importFilePath + nodePath.sep |
186 | | - } |
187 | | - importFilePath = nodePath.normalize(importFilePath + imp) |
188 | | - const importPathRelative = nodePath |
189 | | - .relative(initialPath, importFilePath) |
190 | | - .replace('./', '') |
191 | | - .replace('../', '') |
192 | | - .replace(/^\./, '') |
193 | | - |
194 | | - const importContent = fs.readFileSync(importFilePath).toString() |
195 | | - let sourceFileName = imp.replace('./', '').replace('../', '') |
196 | | - if (sourceFileName.startsWith('.')) { |
197 | | - sourceFileName = sourceFileName.substr(1, sourceFileName.length) |
198 | | - } |
199 | | - if (filesChecked.includes(importPathRelative)) { |
200 | | - continue |
201 | | - } |
202 | | - filesChecked.push(importPathRelative) |
203 | | - sources[importPathRelative] = { |
204 | | - content: importContent |
205 | | - } |
206 | | - this.findImports( |
207 | | - sources, |
208 | | - importContent, |
209 | | - nodePath.normalize(nodePath.dirname(importFilePath)), |
210 | | - filesChecked, |
211 | | - initialPath |
212 | | - ) |
213 | | - } |
214 | | - } |
215 | 166 |
|
216 | | - private generateCompileObject(contractName: string, content: string, path: string) { |
217 | | - const sources = {} |
218 | | - sources[`${contractName}.sol`] = { |
219 | | - content: content |
220 | | - } |
221 | | - const filesChecked = [] |
222 | | - this.findImports(sources, content, path, filesChecked, path) |
223 | | - const compileJson = { |
224 | | - language: 'Solidity', |
225 | | - sources, |
226 | | - settings: { |
227 | | - outputSelection: { |
228 | | - '*': { |
229 | | - '*': ['evm.bytecode', 'evm.legacyAssembly', 'evm.deployedBytecode'] |
230 | | - } |
231 | | - } |
232 | | - } |
233 | | - } |
234 | | - return compileJson |
235 | | - } |
236 | 167 |
|
237 | 168 | private isPush(opcode: Opcode): boolean { |
238 | 169 | return opcode.name.startsWith('PUSH') |
|
0 commit comments