-
Notifications
You must be signed in to change notification settings - Fork 8
/
instrumentSolidity.js
63 lines (53 loc) · 2.17 KB
/
instrumentSolidity.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
const SolidityParser = require('solidity-parser');
const preprocessor = require('./preprocessor');
const injector = require('./injector');
const parse = require('./parse');
// var solparse = require("solparse");
const path = require('path');
module.exports = function instrumentSolidity(contractSource, fileName) {
const contract = {};
contract.source = contractSource;
contract.instrumented = contractSource;
contract.runnableLines = [];
contract.fnMap = {};
contract.fnId = 0;
contract.branchMap = {};
contract.branchId = 0;
contract.statementMap = {};
contract.statementId = 0;
contract.injectionPoints = {};
// First, we run over the original contract to get the source mapping.
let ast = SolidityParser.parse(contract.source);
parse[ast.type](contract, ast);
const retValue = JSON.parse(JSON.stringify(contract));
// Now, we reset almost everything and use the preprocessor first to increase our effectiveness.
contract.runnableLines = [];
contract.fnMap = {};
contract.fnId = 0;
contract.branchMap = {};
contract.branchId = 0;
contract.statementMap = {};
contract.statementId = 0;
contract.injectionPoints = {};
contract.preprocessed = preprocessor.run(contract.source);
contract.instrumented = contract.preprocessed;
ast = SolidityParser.parse(contract.preprocessed);
parse[ast.type](contract, ast);
// var result = solparse.parse(contract);
// We have to iterate through these injection points in descending order to not mess up
// the injection process.
const sortedPoints = Object.keys(contract.injectionPoints).sort((a, b) => b - a);
sortedPoints.forEach(injectionPoint => {
// Line instrumentation has to happen first
contract.injectionPoints[injectionPoint].sort((a, b) => {
const eventTypes = ['openParen', 'callBranchEvent', 'callEmptyBranchEvent', 'callEvent'];
return eventTypes.indexOf(b.type) - eventTypes.indexOf(a.type);
});
contract.injectionPoints[injectionPoint].forEach(injection => {
injector[injection.type](contract, fileName, injectionPoint, injection);
});
});
retValue.runnableLines = contract.runnableLines;
retValue.contract = contract.instrumented;
return retValue;
};