1
+ /**
2
+ * @author github.com/tintinweb
3
+ * @license MIT
4
+ * */
5
+
6
+ const { BaseRule } = require ( "./builtin" ) ;
7
+ const utils = require ( '../utils' ) ;
8
+ const { AstHashedContractSync, HASH_MODES } = require ( "solidity-doppelganger" ) ;
9
+
10
+ //["AST_EXACT", "AST_STRUCTURE"];
11
+
12
+ class DupeFinder extends BaseRule {
13
+ constructor ( solgrep , selectedModes ) {
14
+ super ( solgrep ) ;
15
+ this . selectedModes = selectedModes || HASH_MODES ;
16
+ this . dupeDb = { } ; // {hash: [file, file, ...]}
17
+ this . selectedModes . forEach ( mode => this . dupeDb [ mode ] = { } ) ;
18
+ }
19
+
20
+ onProcess ( sourceUnit ) {
21
+ Object . values ( sourceUnit . contracts ) . forEach ( contract => {
22
+ HASH_MODES . forEach ( mode => {
23
+ let hashAst = new AstHashedContractSync ( { mode :mode } , sourceUnit . filePath ) . fromAst ( contract . ast )
24
+ if ( ! this . dupeDb [ mode ] [ hashAst . hash ] || ! Array . isArray ( this . dupeDb [ mode ] [ hashAst . hash ] ) ) {
25
+ this . dupeDb [ mode ] [ hashAst . hash ] = [ ] ;
26
+ }
27
+ this . dupeDb [ mode ] [ hashAst . hash ] . push ( `${ sourceUnit . filePath } ::${ contract . name } ` )
28
+ } )
29
+
30
+ } ) ;
31
+ }
32
+
33
+ onDirAnalyzed ( ) {
34
+ this . solgrep . report ( undefined , this , "DUPES" , this . dupeDb ) ;
35
+ }
36
+ onClose ( ) {
37
+ var uniqueContracts = { } ;
38
+
39
+ this . selectedModes . forEach ( mode => {
40
+ if ( typeof uniqueContracts [ mode ] === "undefined" ) {
41
+ uniqueContracts [ mode ] = 0 ;
42
+ }
43
+ uniqueContracts [ mode ] += Object . values ( this . dupeDb [ mode ] ) . filter ( v => v . length == 1 ) . length ; //number of contracts with unique hashes
44
+ this . dupeDb [ mode ] = utils . filterObjByValue ( utils . sortObjByArrayLength ( this . dupeDb [ mode ] ) , ( v ) => v . length > 1 ) ;
45
+ } )
46
+ console . log ( "" )
47
+ console . log ( "ℹ️ Duplicate Contracts (Hash => SourceUnits):" )
48
+ console . log ( this . dupeDb )
49
+ console . log ( "" )
50
+ console . log ( "ℹ️ Number of Unique Contracts per matching method:" )
51
+ console . log ( uniqueContracts )
52
+ }
53
+ }
54
+ DupeFinder . description = "Find Duplicate Contracts! Either 'similar' (AST fuzzy matching) or exact (AST structure) matches." ;
55
+
56
+ module . exports = {
57
+ DupeFinder
58
+ }
0 commit comments