├── Analysis Result.txt.zip ├── ContractDefects.csv ├── DefectChecker ├── DefectChecker.iml ├── out │ └── production │ │ └── DefectChecker │ │ ├── BasicBlock.class │ │ ├── BinaryAnalyzer.class │ │ ├── DefectChecker.class │ │ ├── EVMSimulator.class │ │ ├── Main.class │ │ ├── Pair.class │ │ ├── Utils$1.class │ │ └── Utils.class ├── src │ ├── BasicBlock.java │ ├── BinaryAnalyzer.java │ ├── DefectChecker.java │ ├── EVMSimulator.java │ ├── Main.java │ ├── Pair.java │ └── Utils.java └── test.sol └── ReadMe /Analysis Result.txt.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jiachi-Chen/DefectChecker/e9cab0a43586f2da518df2f385aff14f9491197d/Analysis Result.txt.zip -------------------------------------------------------------------------------- /ContractDefects.csv: -------------------------------------------------------------------------------- 1 | ,Uncheck External Calls,Strict Balance Equality,Transaction State Dependency,Block Info Dependency,Greedy Contract,DoS Under External Influence,Nest Call,Reentrancy 2 | dd5a3aeef473401c23f24c4c6b9cd1b0808fbb36,0,0,0,0,0,0,0,0 3 | 338649003ff30194be899100b67a00bbcd62af67,0,0,0,0,0,0,0,0 4 | 723f74668599c9327138bc97bff04eb9ad44a3fa,0,0,0,0,0,0,0,0 5 | E2EC7cF6BBaE29b928238a37A7E66dBc4Dc20794,0,0,0,0,0,0,0,0 6 | f7bc84a0e505cd424ce7706a67046271ace20ec8,0,0,0,0,0,0,0,0 7 | 8BF1E43e3Ca6f5c25C380803154aE687D682Ad32,0,0,0,0,0,0,0,0 8 | 2af47a65da8cd66729b4209c22017d6a5c2d2400,0,0,0,0,0,0,0,0 9 | 27218c41e1054dc0484acd2ad35def0ffd17782a,0,0,0,0,0,0,0,0 10 | 219218f117dc9348b358b8471c55a073e5e0da0b,0,0,0,0,0,0,0,0 11 | 5b36208992284CEFA4de83F2Fb34B33D1A75d4B7,0,0,0,0,0,0,0,0 12 | C16b542ff490e01fcc0DC58a60e1EFdc3e357cA6,0,0,0,0,0,1,1,0 13 | 1d840cb510f084e6154c85d14d98cdc8f7a3b4d5,0,0,0,0,0,0,0,0 14 | 16885883e2785C56D279636b45fB85d8F9B0db23,0,0,0,0,0,0,0,0 15 | 7c21d723af0f4594d4f8821aa16bc27c8ea6cec7,0,0,0,0,0,0,0,0 16 | e7dfDF4b7Dd5e9BD0bb94d59379219B625A6433d,0,0,0,0,0,0,0,0 17 | c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2,0,0,0,0,0,0,0,0 18 | 01d5d0108589f3c52fcce6e65503bb6515e66698,0,1,0,0,0,0,0,0 19 | 19d7a9ad3b49252fd2ef640d0e43dfd651168499,0,0,0,0,0,0,0,0 20 | d3d20f3f0ededb2a1503dc8858c7c6f37c2b22cf,0,0,0,0,0,0,0,0 21 | adb41fcd3df9ff681680203a074271d3b3dae526,0,0,0,0,0,0,0,0 22 | d5abcc4c80fd01d8822f35f379fbcebf7a8b8679,0,0,0,0,0,0,0,0 23 | b00b5f9a21b79901d687d6d952319af767a116ca,0,0,0,0,0,0,0,0 24 | 580f18c090914EB9eDbb3d6A810C9789a91c7ba4,0,0,0,0,0,0,0,0 25 | 14f109d126c58b5bf55cdc51b9bd90b21e6a6de5,0,0,0,0,0,0,0,0 26 | 49fddeae0b521dab8d0c4b77e7161094f971320d,0,0,0,0,0,0,0,0 27 | 8d2AAE6a7EB63Ba89c36e82385f096d41074Cd87,0,0,0,0,0,0,0,0 28 | 53e3a7ec57132173ce615debb9a303fd2cd86789,0,0,0,0,0,0,0,0 29 | B71Cd8f21D5C21edcd113CA2807189ddcAf9DD44,0,0,0,1,0,0,0,0 30 | 3209f7ae16d545c60d8cc9c6a5f02181a94fea52,0,0,0,0,0,0,0,0 31 | f69cD472e4EfB38aa320470422C133Ff546B16CC,0,0,0,0,0,0,0,0 32 | af7aea249098f2c2f50cc11d4000ccf798194373,0,0,0,0,0,0,0,0 33 | fb6916095ca1df60bb79ce92ce3ea74c37c5d359,1,0,0,0,0,0,0,1 34 | ba2184520a1cc49a6159c57e61e1844e085615b6,0,0,0,0,0,0,0,0 35 | cdb7ecfd3403eef3882c65b761ef9b5054890a47,0,0,0,0,0,0,0,0 36 | cafe1a77e84698c83ca8931f54a755176ef75f2c,0,0,0,0,0,0,0,0 37 | a37adde3ba20a396338364e2ddb5e0897d11a91d,0,0,0,0,0,0,0,0 38 | 0b1724cc9fda0186911ef6a75949e9c0d3f0f2f3,0,0,0,0,0,0,0,0 39 | 1de4b791c6c7230dffb6d1ecce8eef1ed7f631f9,0,0,0,0,0,0,0,0 40 | 14a3f4795076c0ae67c2aa9efc10e58427a00dff,0,0,0,0,0,0,0,0 41 | ca6bea8e144b0a6aebbb412e6ad0e7ff1959235e,0,0,0,0,0,0,0,0 42 | 320274f5dd332cc3b617b360e8554d95a0b96978,0,0,0,0,0,0,0,0 43 | b694a9ee2eed5dc6d58599a25874abda504fa60a,0,0,0,0,0,0,0,0 44 | 49516fe7bdc54b29a7f95ff55fdd38d9228e55af,0,0,0,0,0,0,0,0 45 | 225ad9683005ce6fde4eae78c7ed91a499182378,0,0,0,0,0,0,0,0 46 | 52519fd6cb827ec77e961c76c9b326470703d0a8,0,0,0,0,0,0,0,0 47 | 4a412fe6e60949016457897f9170bb00078b89a3,0,0,0,0,0,0,0,0 48 | 12b58582694d1f854ce2a947b27be598569fbc92,0,0,0,0,0,0,0,0 49 | 899f9a0440face1397a1ee1e3f6bf3580a6633d1,0,0,0,0,0,0,0,0 50 | 6c9e70d6682ea36ff340153d574b2c523671b107,0,0,0,0,0,0,0,0 51 | 23a20f8e0b5c79f39a2b4395a610a60fb30bc71d,0,0,0,0,0,0,0,0 52 | 51036b0029e95ecbce4784df0a87987d1092ec7d,0,0,0,0,0,0,0,0 53 | bd6bfb97124bce7cab703e6aa6968706c5f0feea,0,0,0,0,0,0,0,0 54 | 895d55ce51760ca614b5b446a504c4a49e2d26e8,0,0,0,0,0,0,0,0 55 | 491559dd3dfdbca13edc74569e86c8a0d517975b,0,0,0,0,0,0,0,0 56 | 9de550274af9c3d4d3e9713f828bd58bd5686b5a,0,0,0,0,0,0,0,0 57 | 6a92b2804EaeF97f222d003C94F683333e330693,1,0,0,0,0,0,0,0 58 | 23166b7900d968f2A2100829b0A19540aa2f7cf1,0,0,0,1,0,0,0,0 59 | 53570f9db0d81af09d9ef418e37e025668eed05f,0,0,0,0,0,0,0,0 60 | 6e0ae69d262420b8ccd7ecdc11f12bb8b38104fc,0,0,0,0,0,0,0,0 61 | bd2ed3e85faa3433c068c7b3f9c8c7d839ce88d7,0,0,0,0,0,0,0,0 62 | 1e143b2588705dfea63a17f2032ca123df995ce0,1,0,0,0,0,0,0,0 63 | 575cb87ab3c2329a0248c7d70e0ead8e57f3e3f7,0,0,0,0,0,0,0,0 64 | 8cd8baa410e9172b949f2c4433d3b5905f8606ff,0,0,0,0,0,0,0,0 65 | 3aaa175924a77ee4b40606f714b727331e430ece,0,0,0,0,0,0,0,0 66 | 4f232a41b26bf07c37240f0cb3bde5727074a0f6,0,0,0,0,0,0,0,0 67 | c00061de5d47f802daaf0de1498c9680732861c3,0,0,0,0,0,0,0,0 68 | 48d8f22d45e40F34cB7C10799F31246F134E9B7f,0,0,0,0,0,0,0,0 69 | 13ce614e9d7ce609dedba1b42ba2163426ba5ace,0,0,0,0,1,0,0,0 70 | a42004629c80aa5f56186379c1185fbec0f65bf7,0,0,0,0,0,0,0,0 71 | e7dc501cb9ca414cf9211af214d5065ca3a30768,0,0,0,0,0,0,0,0 72 | d9e21e7fbbc85d05165b9691abc279249de1a658,0,0,0,0,0,0,0,0 73 | ce6c1005bf05b370af93c1f70d7798aa08c0b6d6,0,0,0,0,0,0,0,0 74 | E05CeDD2838E4e1d99B539D8C768D6EF2a10F729,0,0,0,0,0,0,0,0 75 | c5cdcd5470aef35fc33bddff3f8ecec027f95b1d,0,0,0,0,0,0,0,0 76 | E5a04D98538231b0fAb9ABa60cd73cE4fF3039DF,0,0,0,0,0,0,0,0 77 | 995020804986274763df9deb0296b754f2659ca1,0,0,0,1,0,0,0,0 78 | eA13644b32E570C95B767849011B48Bbb0E6bBB9,0,0,0,0,0,0,0,0 79 | 215b4a7cd7f4ad4594867bbcc91cac08c83ab507,0,0,0,0,0,0,0,0 80 | 755cdba6ae4f479f7164792b318b2a06c759833b,0,0,0,0,0,0,0,0 81 | 0f598112679b78e17a4a9febc83703710d33489c,0,0,0,0,0,0,0,0 82 | 9EA80e204045329Ba752D03C395F82A12799f13d,0,0,0,0,0,0,0,0 83 | a35e3e419ae0031460af1e7a1386cb8f0d7d0efb,0,0,0,0,0,0,0,0 84 | 103c2c150a2dbcc277ee084c59881978060c8c22,0,0,0,1,0,0,0,0 85 | 2c6c596cfd4c2c3b039db90fd3c8acb564e13251,0,0,0,1,0,0,0,0 86 | 635783f8dc5e941fc142235ea44cc3529c17695d,0,0,0,0,0,0,0,0 87 | 8ff920020c8ad673661c8117f2855c384758c572,0,0,0,0,0,0,0,0 88 | 286e052bc8250250566683424001ee5224867d91,0,0,0,0,0,0,0,0 89 | 29b77fa51f36991f99bbeb702471b7227510d05a,0,0,0,0,0,0,0,0 90 | 5bd4b6ab074ede76baa2aec49dcf9edb89a90dcf,0,0,0,0,0,0,0,0 91 | fea61dbc3b9882efcd139a5e28b32234b9c76aea,0,0,1,0,0,0,0,0 92 | c68d1fc21e05d135eaf640aae84a2a9dada69672,0,0,0,0,0,0,0,0 93 | 8be901d10d3d6328bd00c8c9fd19d321bb3277c0,0,0,0,0,0,0,0,0 94 | ab7c74abC0C4d48d1bdad5DCB26153FC8780f83E,1,0,0,0,0,0,0,0 95 | 759981e5af7661836d305f71779690808c1de51f,0,0,0,0,0,0,0,0 96 | 1a8cc57f1155d7df4626978401e203e00da097f7,0,0,0,0,0,0,0,0 97 | 0b6bc31fe6839ec3b8cfc98819cec7fa64158a8f,0,0,0,0,0,0,0,1 98 | DD9aE24a9E442Fd7af6Cd321400Cc8243458924F,0,0,0,0,0,0,0,0 99 | bad9b65cfb0c2e89bc9543b86849780baa52c605,0,0,0,0,0,0,0,0 100 | 7acbc0b5c51027dc659a19f257bb3e462309b626,0,0,0,0,0,0,0,0 101 | eb6e4fad04c68a2dd22c0a6acb1010c763c5ced8,0,0,0,0,0,0,0,0 102 | 05d379b48A8622ae4018309E116420Db4a38A225,0,0,0,0,0,0,0,0 103 | 31e13882c45c1023d9b16c3794c1a780bb6cb88d,1,0,0,0,0,0,1,0 104 | 3c7767011C443EfeF2187cf1F2a4c02062da3998,0,0,0,0,0,0,0,0 105 | 7bb187351421c3affda57c7a5132e304f73167c8,0,0,0,0,0,0,0,0 106 | b3aac808b10eb65b74b59deb4f1998b52327bd1a,0,0,0,0,0,0,0,0 107 | 92cB5F1FbabbcbDd891B9Cbd8E9a056c8c1eEbEF,0,0,0,0,0,0,0,0 108 | 39df5af51c47256e5c63b3dae1a21f3da4a58e89,0,0,0,0,0,0,0,0 109 | 833ede3050c27d88e5da6922a312e3fdc15be29b,0,0,0,0,0,0,0,0 110 | 35792029777427920ce7aDecccE9e645465e9C72,0,0,0,0,0,0,0,0 111 | a48a875ca65b2f70a41929c060fc245def4ccd88,0,0,0,0,0,0,0,0 112 | 1f88888732d0943bb49f7573a8848814ff0a4090,0,0,0,0,0,0,0,0 113 | 34f940a0311f6f6015fee8ddc1e2eb7985202690,0,0,0,0,0,0,0,0 114 | 06Ee3390532f493B4C3a41aA6E396ec750C038d7,0,0,0,0,0,0,0,0 115 | 65b6b495730371a807915441ed337f09d039bc66,0,0,0,0,0,0,0,0 116 | 3bb62bada8f9921dcf0b1be5d2c972d69c064d84,0,0,0,0,0,0,0,0 117 | 631b4cea5064e2577cdb73c37ed2de00c30ee14a,0,0,0,0,0,0,0,0 118 | ae42990ad29747c9Ab0C16098b8c5393E53C6Abe,0,0,0,0,0,0,0,0 119 | 48EB12C0DDc5163E8693F3029A14440442Df2710,0,0,0,0,0,0,0,0 120 | b5F4651540ae4AD3a5c2a89B0D14eB06df886745,0,0,0,0,0,0,0,0 121 | e163f74937c8c3065518486e58d655504da0d4db,0,0,0,0,0,0,0,0 122 | 08fca9bfaed36c29ee3435206158f13dedf4a859,0,0,0,0,0,0,0,0 123 | 311d745582a97be5d7abbce48855ecec72737c5d,0,0,0,0,0,0,0,0 124 | da4a4626d3e16e094de3225a751aab7128e96526,1,0,0,0,0,0,0,0 125 | 6f4e647f553397dc999382ad3a9c5336c5de27aa,0,0,0,1,0,0,0,0 126 | 30cc0e266cf33b8eac6a99cbd98e39b890cfd69b,0,0,0,0,0,0,0,0 127 | 6822aaf4ab22e6cca8352a927b9ae0a8fdb58d9d,0,0,0,1,0,1,1,0 128 | dD1AcE2f45962e4C1297c784009478865e3B13bE,0,0,0,1,0,0,0,0 129 | 1fc7bd85293f3982f40d52698df8d26be89360d6,0,0,0,0,0,0,0,0 130 | 14b233a46cd4bdfdb7ca29aa0fd2406f667f8ff6,0,0,0,0,0,0,0,0 131 | c4d3abd6007e7475655a463f8aa01d4cca033991,0,0,0,0,0,0,0,0 132 | 40a05d4ce308bf600cb275d7a3e9113518f59c54,0,0,0,0,0,0,0,0 133 | 14cf6193935b17fc72649ba420fdd5bfdf1f0001,0,0,0,0,0,0,0,1 134 | 62451d37ca2ec1f0499996bc3c7e2baf258e9729,0,0,0,0,0,0,0,0 135 | a578acc0cb7875781b7880903f4594d13cfa8b98,0,0,0,0,0,0,0,0 136 | 155E7e9ab193Aa37c87D22f66002e3dB64C9E0Ce,0,0,0,0,0,0,0,0 137 | 9b6BAA7DE8751328E8e0a8b872Ff8d36539b313D,0,0,0,0,0,0,0,0 138 | db2Ae021F1EEa3c9ad25cd49aDDe23bB788D3D9D,0,0,0,0,0,0,0,0 139 | 8fdebcf5c93dc128de40fefee00f581fd80a1e92,0,0,0,0,0,0,0,0 140 | 7a8bbfcccb6b80579d5965aa8d4a4b2294ac166e,0,0,0,0,0,0,0,0 141 | c70afb5612b16d36d2204052f81932064fd084c5,0,0,0,0,0,0,0,0 142 | e74be15ae490c348fd75615ceff8657f30ac074c,0,0,0,0,0,0,0,0 143 | 3339ec512996fcdfacae2fbe941b6820f2c4e8b2,0,0,0,0,0,0,0,0 144 | d7784ddb103479ee3094c7816dd7918e1ae3997f,0,0,0,0,0,0,0,0 145 | 10e32d84d8bd44b68e99c6fe147ef2ba63e6ae22,0,0,0,0,0,0,0,0 146 | 6DE3cC59152e19f108378984f45E20a34C9f6338,0,0,0,0,0,0,0,0 147 | faaad14ff8d00e28959094dd8cf90b6dcd7f5a3e,0,0,0,0,0,0,0,0 148 | e642b6f79041c60d8447679b3a499f18d8b03b81,0,0,0,0,0,0,0,0 149 | e752483412490481d193194d293db5cd0ed054a8,0,0,0,0,1,0,0,0 150 | 9AcA6aBFe63A5ae0Dc6258cefB65207eC990Aa4D,0,0,0,0,0,0,0,0 151 | f300cc72613d575a4567405c2a07d2aaf182aebf,0,0,0,0,0,0,0,0 152 | 6ff323e36bfdb20502b23780695f4e77e36cde95,0,0,0,0,0,0,0,0 153 | c6e095f5fB53339D8F4C7f576ccD37bE05E5B67E,0,0,0,0,0,0,0,0 154 | daab8a09aed3b98df4fffef85e78cd6f513de7d0,0,0,0,0,0,0,0,0 155 | baaffc2f4074863bf0ced1dc61e5410fad075cec,0,0,0,0,1,0,0,0 156 | 129acbb3ad1a3ad13fec0fc7ca26811a487e14c9,0,0,0,0,0,0,0,0 157 | 29aa20fB9b23421E310BDB8a7cfB81d7fbB4a1b3,0,0,0,0,0,0,0,0 158 | fcc5b18f1f51956e0abb411e7b86c76586ab4ef9,0,0,0,0,0,0,0,0 159 | d566fa4a696eac66f749f7fe999d6673fee2026c,0,0,0,1,0,0,0,0 160 | DfC328c19C8De45ac0117f836646378c10e0CdA3,0,0,0,0,0,0,0,0 161 | 3bcc57726166dd1b391e4abc34fa41aee1457843,0,0,0,0,0,0,0,0 162 | ed1a5a5a71859c5eab160d4c9e1eb0d185f925e3,0,0,0,0,0,0,0,0 163 | 58e41735fa157a69ae9abf96321e890fb45f3dff,0,0,0,0,0,0,0,0 164 | b59a226a2b8a2f2b0512baa35cc348b6b213b671,0,0,0,0,0,0,0,0 165 | 97282A7a15f9bEaDC854E8793AAe43B089F14b4e,0,0,0,0,0,0,0,0 166 | 00430f32b8e77a456d0ab7e6f1dc1b84f4ae62e0,0,0,0,0,0,0,0,0 167 | 26d08b9d227933a85e855656dc46ab889e183c88,0,0,0,0,0,0,0,0 168 | 580c1e3caca14826976b5820947f7ad486ac174d,0,0,0,0,0,0,0,0 169 | 2128ed30ffef264f70f2d6237108f8aa02fb3b64,0,0,0,0,0,0,0,0 170 | c83355ef25a104938275b46cffd94bf9917d0691,0,0,0,0,0,0,0,0 171 | ae53aaff39f07cb48386ef33bc5fc72cc55d6f1c,0,0,0,0,0,0,0,0 172 | c3ef562cc403c8f9edf7c3826655fbf50f4ddde8,0,0,0,0,0,0,0,0 173 | 01bd70a0cc118bca4c70624286488e8f3d78a10f,0,0,0,0,0,0,0,0 174 | 967081d634f01003b2c5b3d8ea5aa2c55000722e,0,0,0,0,0,0,0,0 175 | 37a5bb09f4d7613803f6bdd52d261c01ec2a7540,0,0,0,0,0,0,0,0 176 | 0b9e9c56ec900fbea85546444458d3c31ab60572,0,0,0,0,0,0,0,0 177 | 606af0bd4501855914b50e2672c5926b896737ef,0,0,0,0,0,0,0,0 178 | e2e5d0e1422e927abab19ad2067f802ad07fb364,0,0,0,0,0,0,0,0 179 | e9ef26c4e9761e2305f455a0e0d4cd286e2d13a1,0,0,0,0,0,0,0,0 180 | 4290563C2D7c255B5EEC87f2D3bD10389f991d68,0,0,0,1,0,0,0,0 181 | 05580ac8bdcdecee70c39592cd07c303992d58b8,0,0,0,0,0,0,0,0 182 | 45d147c800d401350b24fc1cd5fbc98040b177c8,0,0,0,1,0,0,0,1 183 | 2956356cd2a2bf3202f771f50d3d14a367b48070,0,0,0,0,0,0,0,0 184 | c330c1a3c7db9c75f60aed0a9b7c0fc5fa22d5a2,0,0,0,0,0,0,0,0 185 | 787C2fFFB74F559219836a77FAd6181f808b6F73,0,0,0,0,0,0,0,0 186 | 3b5F11dBaC1476af17957C6e5991F21c826743dd,0,0,0,0,0,0,0,0 187 | a549ef3164556b3fdba16680798032b993c2325b,0,0,0,0,0,0,0,0 188 | 8eb24319393716668d768dcec29356ae9cffe285,0,0,0,0,0,0,0,0 189 | e6517b766e6ee07f91b517435ed855926bcb1aae,0,0,0,0,0,0,0,0 190 | A97fF44CFf7101FaC76aF172F088f400F28cb4E9,0,0,0,0,0,0,0,0 191 | 2097175d0abb8258f2468e3487f8db776e29d076,0,0,0,0,0,0,0,0 192 | 8c959f04ea4a9111a49dc34df9de59ca8e23037c,0,0,0,0,0,0,0,0 193 | 5882D49d3511E09096CBbaB7E19fBFb82f65f28D,0,0,0,0,0,0,0,0 194 | 73dd069c299a5d691e9836243bcaec9c8c1d8734,0,0,0,1,0,0,0,0 195 | B47aD434C6e401473F1d3442001Ac69cda1dcFDd,0,0,0,0,0,0,0,0 196 | b3b33f59174f2ef62167770e4c9cabaa3879eb5d,0,0,0,1,0,0,0,0 197 | 11524a168d1b888df781a87a6b4511f199b543ad,0,0,0,0,0,0,0,0 198 | cd6608b1291d4307652592c29bff7d51f1ad83d7,0,0,0,0,0,0,0,0 199 | 0b8d56c26d8cf16fe1bddf4967753503d974de06,0,0,0,0,0,0,0,0 200 | b0bef286a13457b963c710fa7765961d09a27c63,0,0,0,0,0,0,0,0 201 | e758421818E3FC974730292C0704F7b77DaA791c,0,0,0,0,0,0,0,0 202 | 709c7134053510fce03b464982eab6e3d89728a5,0,0,0,0,0,0,0,0 203 | D0B56cbCD938AEAfb41915C09594eE88F3c5C41b,0,0,0,0,0,0,0,0 204 | 8d12a197cb00d4747a1fe03395095ce2a5cc6819,0,0,0,1,0,0,0,0 205 | 8f1e7E18c96C4B75D12CBcA93613Dfebd16eb0E1,0,0,0,0,0,0,0,0 206 | f39C702594792B91aec6d881C9e6ebD2022A2271,0,0,0,0,0,0,0,0 207 | 93d812bf90a575d628e246b0966505a9e466f534,0,0,0,0,0,0,0,0 208 | f1ed1fdb9f35ec6758262b4f0683d60f799bf8b6,0,0,0,0,0,0,0,0 209 | 5b7ea49f9fa4cc48f6737b72bd36bb4b9732bb7d,0,0,0,0,0,0,0,0 210 | 06012c8cf97bead5deae237070f9587f8e7a266d,1,0,0,1,0,0,0,0 211 | e2d82dc7da0e6f882e96846451f4fabcc8f90528,0,0,0,0,0,0,0,0 212 | 2c3cc0f8dede2eccae43380ecf29b61fa6d10dca,0,0,0,0,0,0,0,1 213 | b104df39250112eda59b27f5db7013c7ee132d50,0,0,0,0,0,0,0,0 214 | 3868eaf38f1319c70c4557c2234cd3e89947c633,0,0,0,0,0,0,0,0 215 | 35a69642857083ba2f30bfab735dacc7f0bac969,0,0,0,0,0,0,0,0 216 | 60a76ea79eBC7264F2897EE7FE4f33F31ef25A74,0,0,0,0,0,0,0,0 217 | 3744942C42451c2B42F43a51eE9bB6c6ad0FDc86,0,0,0,0,0,0,0,0 218 | df6164efd12678bf6a7d5a1ddf73c831493f6574,0,0,0,0,0,0,0,0 219 | 761d0ca58b3b34ccf4f66438f9d6378e2f063dce,0,0,0,0,0,0,0,0 220 | fc5c6c8015962e7035f3bdc5fe7ec94bedc77833,0,0,0,0,0,0,0,0 221 | 15f2e85efb82c61ba4963b67aa1e89cf72cd0c37,0,0,0,0,0,1,0,0 222 | 8a8ca863f73992fcc43dd64c7261ba9dcc8e2181,0,0,0,0,0,0,0,0 223 | f0300337E920aE843040A71584f870aE719bf5eD,0,0,0,0,0,0,0,0 224 | e64d5f33e28387855d33980719f27f0d579392af,0,0,0,0,0,0,0,0 225 | 8f199d74d89b977d3f0684f0572bc66b16120ed8,0,0,0,0,0,0,0,0 226 | ad1ff4873633c9248130fbfe28d17e1bd5467cc4,0,0,0,0,0,0,0,0 227 | 99892ac6da1b3851167cb959fe945926bca89f09,0,0,0,0,0,0,0,0 228 | d7e4ad7c318ffbafbf602e32e089e7e2326a2581,0,0,0,0,0,0,0,0 229 | 402b92b00552409ed1ad83a74ff037ce1a3d7276,0,0,0,0,0,0,0,0 230 | 18a672e11d637fffadccc99b152f4895da069601,0,0,0,1,0,0,0,0 231 | a723606e907bf84215d5785ea7f6cd93a0fbd121,0,0,0,0,0,0,0,0 232 | d780ae2bf04cd96e577d3d014762f831d97129d0,0,0,0,1,0,0,0,0 233 | 3076d20cef23cf934fc6f857eb97e2baa63fc9fb,0,0,0,0,0,0,0,0 234 | 30407ece7f4252a7e2d786207831561b33ec3f13,0,0,0,0,0,0,0,0 235 | 55D5B8fE471cc4e19D7f0fc17D7a98c0C72A5688,0,0,0,0,0,0,0,0 236 | bF35fAA9C265bAf50C9CFF8c389C363B05753275,1,0,0,0,0,0,0,0 237 | 89c0afcd1bdbb91675b9fca14519738d5286b61e,0,0,0,0,0,0,0,0 238 | a87c3ec87eb802aad080df0adb331e504d327e5d,0,0,0,0,0,0,0,0 239 | bbc5d510bab53b2199fb17fe1d896eb78911e103,0,0,0,0,0,0,0,0 240 | 30758B708a2A31C3ab7dE6B8637adBed725e33aE,0,0,0,0,0,0,0,0 241 | 94add786881a945e68f3dfd1478f586ba36769b5,0,0,0,0,0,0,0,0 242 | d6A755BCe1844Ad6b7681118b18f54D63E5C13F9,0,0,0,0,0,0,0,0 243 | 476c331d7f6569dc4bd16ef6673f7a89cd6f37c3,0,0,0,0,0,0,0,0 244 | 7ee41a4c66e92fe28abd5bde30ad644a2dc8b15f,0,0,0,0,0,0,0,0 245 | b28a3dd24036151c819c6d401f7a222d9aa3671b,0,0,0,0,0,0,0,0 246 | e1df194ae7366876e91a0999e29530719452e558,0,0,0,0,0,0,0,0 247 | 2873b3659847cf9a069041fe4f5e48786afcb632,0,0,0,0,0,0,0,0 248 | 5019066b46ae4b8673085b609be366400f53871b,0,0,0,1,0,0,0,0 249 | bca230c0b76993bc21b67640d420fe9d8bc931aa,0,0,0,0,0,0,0,0 250 | d32c26B14030c724c0118576308Ea2fB3300D10f,0,0,0,0,0,0,0,0 251 | 9b0f6a5a667cb92af0cd15dbe90e764e32f69e77,1,0,0,0,0,0,0,0 252 | 9e46a38f5daabe8683e10793b06749eef7d733d1,0,0,0,0,0,0,0,0 253 | 7A46C781b593068d5e987b191e9c2f7413E22aEE,0,0,0,0,0,0,0,0 254 | ed574d920a0c152ca136717c79a352b83f3bb058,0,0,0,0,0,0,0,0 255 | 446D1696a5527018453cdA3d67aa4C2cd189b9f6,1,0,0,0,0,0,1,0 256 | 040d11c850fb167cddb1e4d308fe9062fddaebd1,0,0,0,0,0,0,0,0 257 | 373c55c277b866a69dc047cad488154ab9759466,0,0,0,1,0,0,0,0 258 | 8eee81d817c9548615d69c485074b55df487ab95,0,0,0,0,0,0,0,0 259 | 0905a9844f41d1be68f99dd4bd51be6838892010,0,0,0,0,0,0,0,0 260 | 00674045bb7c17f0aa1cde34780d6c51af548728,0,0,0,0,0,0,0,0 261 | 173fc908b21b861facf54c65c10002b1e2f9c323,0,0,0,0,0,0,0,0 262 | 8d3bd2940bbc5ed724d138934374e4c0ad3c0027,0,0,0,0,0,0,0,0 263 | c23f76aea00b775aadc8504ccb22468f4fd2261a,0,0,0,1,0,0,0,0 264 | 728781e75735dc0962df3a51d7ef47e798a7107e,0,0,0,1,0,0,0,1 265 | 3726cc0cdb26106bfb297ee6697da2a8687f385b,0,0,0,1,0,0,0,0 266 | dad697274f95f909ad12437c516626d65263ce47,0,0,0,0,0,0,0,0 267 | 9a4ee79ab5ef423162873d3df22047b392492e58,0,0,0,0,0,0,0,0 268 | 04c62019ab478bff5874e7b7d9bc84fcf7e30025,0,0,0,0,0,0,0,0 269 | 9e4ad79049282f942c1b4c9b418f0357a0637017,0,0,0,0,0,0,0,0 270 | 0F4a28085713c1a5DEdc5D6f471c79AFe2d9321e,0,0,0,0,0,0,0,0 271 | 22a97c80d7e0a9ae616737e3b8b531248f4ef91d,0,0,0,1,0,0,0,0 272 | a1c957c0210397d2d0296341627b74411756d476,0,0,0,0,0,0,0,0 273 | ace518c4cb2b823c2ab2b12c709e71e11cfb8896,0,0,0,0,0,0,0,0 274 | 0ccb03cb1a89808209eaebbcb059ed05e44cb9cf,0,0,0,0,0,0,0,0 275 | 6f6deb5db0c4994a8283a01d6cfeeb27fc3bbe9c,0,0,0,1,0,0,0,0 276 | b47e3cd837dDF8e4c57F05d70Ab865de6e193BBB,0,0,0,0,0,0,0,0 277 | 075a5d77E17502ABa0388746aA229BB33682f521,0,0,0,0,0,0,0,0 278 | 6b609d9095d069c805650234ab67595b3a6ab934,0,0,1,0,0,0,0,0 279 | 62c8b4ac2aef3ed13b929ca9fb20cacb222e3fa6,0,0,0,0,0,0,0,0 280 | 66385555FC121D18Dc95eC3A8ECd51AB2B660dE5,0,0,0,0,0,0,0,0 281 | d58297b5e0ad69f6ba949fdde9da0f2b978f00a0,0,0,0,0,0,0,0,0 282 | 365267181bc0ef38bbb8d8ca9b330dc0c3ac01d1,0,0,0,0,0,1,1,0 283 | 10b7d09dca7f9c6d33a9aeef5bf2bb5ce3ec1550,0,0,0,0,0,0,0,0 284 | 7352cb77c2478a59d21230a8d65146e04b59f58c,0,0,0,0,0,0,0,1 285 | 615ed6779507f223d04722d43ccc0cd871964e2a,0,0,0,0,0,0,0,0 286 | 8b7d07b6ffB9364e97B89cEA8b84F94249bE459F,0,0,0,0,0,0,0,0 287 | 901f47957338bf52b6a45ef67a3de09346c3fa29,0,0,0,0,0,0,0,0 288 | a646e29877d52b9e2de457eca09c724ff16d0a2b,0,0,0,0,0,0,0,0 289 | 1b8f71e4eec8df98598bbc3093cafeb57c7109ae,0,0,0,0,0,0,0,0 290 | b375d24ffc46885c3bdd5ed275a248efe76a25c9,0,0,0,0,0,0,0,0 291 | 3f0a24a07b2d729a02640deb1d27cd00da72b799,0,0,0,0,0,0,0,0 292 | 16a0772b17ae004e6645e0e95bf50ad69498a34e,0,0,0,0,0,0,0,0 293 | f0a924661b0263e5ce12756d07f45b8668c53380,0,0,0,0,0,0,0,0 294 | 41ff0796a6c7a201476bff53c4cb2c48b084e5e0,0,0,0,0,0,0,0,0 295 | d96e8733dfd61fd37936450ea17176288c09a2a9,0,0,0,0,0,0,0,0 296 | c0829421c1d260bd3cb3e0f06cfe2d52db2ce315,0,0,0,0,0,0,0,0 297 | 7f0c38d5e951c47d96d3ec96e3127c73ed4b278e,0,0,0,0,0,0,0,0 298 | 0F4caFDCE3737601C598BcFD4Bbd69F75786bA40,0,0,0,0,0,0,0,0 299 | 15dbdB25f870f21eaf9105e68e249E0426DaE916,0,0,0,0,0,0,0,0 300 | 035a401972f228b58dcae76bf318b54ed036d680,0,0,0,0,0,0,0,0 301 | d77fc35cc9007557dcd18bfe26fe66f1ea3a0e7f,0,0,0,0,0,0,0,0 302 | fd26d4fedea09da1bb2c4e410c747dda72fdb506,0,0,0,0,0,0,0,0 303 | aac8253a42c213b6a9cdf4f25cd5de29d09b96f9,0,0,0,0,0,0,0,0 304 | 83e82cea898b1ed1785bc3beac86034913831e60,0,0,0,0,0,0,0,0 305 | 9b8c435196c8398ff021f375535cf04e3459b15c,0,0,0,0,0,0,0,0 306 | b53613FA4ad09f00e41A91B7dFdfa3E98c76F4c0,0,0,0,0,0,0,0,0 307 | 5d356ebdaed2798547889ffa12fc587347e5ad89,0,0,0,0,0,0,0,0 308 | 4490f9807965c49a2471bd7b121a80f0b3861e5c,0,0,0,0,0,0,0,0 309 | 519c5dcaa311ca31009a3fcc7e03f7b24a55ff42,0,0,0,0,0,0,0,0 310 | 97ec9bfb0f6672c358620615a1e4de0348aea05c,0,1,0,0,0,0,0,0 311 | 388a037ab169b128e70cf67e1228ecd03f0400f2,0,0,0,0,0,0,0,0 312 | 1cE7AE555139c5EF5A57CC8d814a867ee6Ee33D8,0,0,0,1,0,0,0,0 313 | 957b9dc190c4391a1e07352df34e1ec02077f1ec,0,0,0,0,0,0,0,0 314 | 7782b0e4e4644ad4583efb13dd9b28e2bac68286,0,0,0,0,0,0,0,0 315 | f92ff59c63240770cd7d49ffaa852bf95f391984,0,0,0,0,0,0,0,0 316 | a9ad24633c93ee78f4c2bf9b3e9128cbc0269717,0,0,0,0,0,0,0,0 317 | e23266201b2ad708cf9916240783ebe0405b3881,0,0,0,0,0,0,0,0 318 | B62EF4c58F3997424B0CCeaB28811633201706Bc,0,0,0,0,0,0,0,0 319 | cfaafdd4ec90985108c3f4847b14e7c733eaf575,0,0,0,0,0,0,0,0 320 | 836175e10c294d76fb44135d666b3eb76a62e0f0,0,0,0,0,0,0,0,0 321 | 8f951903c9360345b4e1b536c7f5ae8f88a64e79,0,0,0,0,0,0,0,0 322 | adaac4cb430f4f4aa0d60741bc263f3dfec0790a,0,0,0,1,0,0,0,0 323 | 1e2fbe6be9eb39fc894d38be976111f332172d83,0,0,0,0,0,0,0,0 324 | dd98b423dc61a756e1070de151b1485425505954,0,0,0,0,0,0,0,0 325 | e477292f1b3268687a29376116b0ed27a9c76170,0,0,0,1,0,0,0,0 326 | 8d80de8a78198396329dfa769ad54d24bf90e7aa,0,0,0,0,0,0,0,0 327 | fd743691ac893000f29c893ba21ed46f465c4de4,0,0,0,0,0,0,0,0 328 | 83b7EEb4D6eC1289578186f1da64A876DC71FCbb,0,0,0,0,0,0,0,0 329 | 8b34fbc553db3462ad4909f2e5577cc22f63c216,0,0,0,0,0,0,0,0 330 | bf4ed7b27f1d666546e30d74d50d173d20bca754,1,0,0,0,0,0,0,0 331 | 2ce4f2b9b3261cd95229d80dfc785d2edb4cfd1a,0,0,0,0,0,0,0,0 332 | c6b330df38d6ef288c953f1f2835723531073ce2,0,0,0,0,0,0,0,0 333 | 282eaF0C93b535731c1A2Ef26A568e6131980c4A,0,0,0,0,0,0,0,0 334 | 5da6f5621c6f5c8b8f09e2a6d62a9ed544cbe37c,0,0,0,0,0,0,0,0 335 | 27ba31d1f1219ba326a30c9fb9e17fb4d6a364a7,0,0,0,0,0,0,0,0 336 | 6abf810730a342add1374e11f3e97500ee774d1f,0,0,0,0,0,0,0,0 337 | 7b9e81ec3591b570aa2c9fbec77f7dda76ac4f6d,0,0,0,0,0,0,0,0 338 | 3774cc78af0bda8eacbdac6be5fb23261b8efaa7,0,0,0,0,0,0,0,0 339 | 9ce6a4dbf61c13e23edf47b41e7a2ba9e525d765,0,0,0,0,0,0,0,0 340 | Ba69e7C96E9541863f009E713CaF26d4Ad2241a0,1,0,0,0,0,0,1,0 341 | 6f5C1Ed62A4fA41CFC332D81FAFd3CD38aaCBD85,0,1,0,0,0,0,0,0 342 | b1690c08e213a35ed9bab7b318de14420fb57d8c,1,0,0,0,0,0,0,0 343 | a01d9BAfA60fbd1967bacF74B76c7e464d0F7c92,0,0,0,0,0,0,0,0 344 | 35d82234a9f2cfe1dc2fb7665c785e1755cfd559,0,0,0,0,0,0,0,0 345 | 0214d7faA8145bDdb0fb4977980cE26AA1f95cEE,0,0,0,0,0,0,0,0 346 | e8a51be86ad96447d45ddeddc55013f25157688c,0,0,0,0,0,0,0,0 347 | d8e396e67650e72eefa281efc86738eb3e2c7400,0,0,0,0,0,0,0,0 348 | 58ca3065c0f24c7c96aee8d6056b5b5decf9c2f8,0,0,0,0,0,0,0,0 349 | 2550d5989f10f1a732c9ffe48f97fe2b178ec2df,0,0,0,0,0,0,0,0 350 | c56b13ebbcffa67cfb7979b900b736b3fb480d78,0,0,0,0,0,0,0,0 351 | 5fafe57bd692d07c4db048558752632210ccddf6,0,0,0,0,0,0,0,0 352 | 9DA53246714bf10010Aee31ffDb9cf8caB8c6813,0,0,0,0,0,0,0,0 353 | e4fb506f5e6d8c68e71cb9f7cc2fde4c059d3925,0,0,0,0,0,0,0,0 354 | 9122e2cfab13d30237ebeef0c0521d64bf0b06dc,0,0,0,0,0,0,0,0 355 | 3da71558a40f63b960196cc0679847ff50fad22b,0,0,0,0,0,0,0,0 356 | b8bf73550f251562d308882e032225a700a7b9bc,0,0,0,0,0,0,0,0 357 | a8a4ff10d75a82aa8cd1055d30a66c925dc5b2fe,0,0,0,0,0,0,0,0 358 | aa3918d28c0e75dab344889694bce21a69598f6b,0,0,0,0,0,0,0,0 359 | 1e025340d6f75a2a4ef81139049cfbf976782eeb,1,0,0,0,0,0,0,0 360 | 7f30b108768dae75bfe036c94b207dc53f12ca6f,0,0,0,1,0,0,0,0 361 | 371715dda4cf2b4ca22c5995da8a86bc7c21837e,0,0,0,0,0,0,0,0 362 | 3cfc5c7fa8db91de8efd633998097f8e96eff043,0,0,0,0,0,0,0,0 363 | 7da82c7ab4771ff031b66538d2fb9b0b047f6cf9,0,0,0,0,0,0,0,0 364 | 39139b54e733d01fd0b46fdb32cf45e08696541c,0,0,0,0,0,0,0,0 365 | 336db6c1ead9cc4d5b0a33ac03c057e20640126a,0,0,0,0,0,0,0,0 366 | 5ab14c104ba2771fd2a6ec6f616da1ad41d5b8a7,0,0,0,0,0,0,0,0 367 | 01617196358c14628d032f9c5f7188f2fbcafd78,0,0,0,0,0,0,0,0 368 | 5e3862f37778C9Ea56843724148dB7056b78c24d,0,0,0,0,0,0,0,0 369 | 0dE2aD05856f8F5bfD8284D540a5d8C3AEc4dC9A,0,0,0,0,0,0,0,0 370 | 943e99d9efd4b44d808f6c83373a9a2c1e15e0f8,0,0,0,1,0,0,0,0 371 | 2eefe55e7fd4546ce3451430aa4fdced0c4efe85,0,0,0,0,0,0,0,0 372 | f31619a15518dce0613a514e6672d1f84f6e7fe7,0,0,0,0,0,0,1,0 373 | 525aEEf9Af9ae896179EE287e024a40cF5FC7655,0,0,0,0,0,0,0,0 374 | 851b7f3ab81bd8df354f0d7640efcd7288553419,0,0,0,0,0,0,0,0 375 | ed7da010027967365e0a7c370c1dde2f9fe4477f,0,0,0,0,0,0,0,0 376 | e386B139Ed3715Ca4B18Fd52671bDcea1cdFE4b1,0,0,0,0,0,0,0,1 377 | 53a54c442583d2e844733f179d142c32f3c004b7,0,0,0,0,0,0,0,1 378 | 39173925e7c7a07dc7a6afbf1dffd0179de18c27,0,0,0,0,0,0,0,0 379 | 11d4ec0991951b5ea20a1f3bf0c9e36e054b1e55,0,0,0,0,0,0,0,0 380 | ce2095197142a6972256d70fe4ba024f2c7a7d96,0,0,0,0,0,0,0,0 381 | c67c1f88f31e724b137a057292e55cb42a5f3241,0,0,0,0,0,0,0,0 382 | E691b7FF3c9fdDB8C2437412208EE4816ABa7258,0,0,0,0,0,0,0,0 383 | a62bdee2f277c2e2c0f46cba96879b263796ee1c,0,0,0,0,0,0,0,0 384 | 0f5d2fb29fb7d3cfee444a200298f468908cc942,0,0,0,0,0,0,0,0 385 | 1f31d1168efe4bd22d00d31fc425e5bcb54c75e7,0,0,0,1,0,0,0,0 386 | 1e2ca24d0d32580f6f514aaf01763b78cb7001cd,0,0,0,0,0,0,0,0 387 | 4e646a576917a6a47d5b0896c3e207693870869d,0,0,0,0,0,0,0,0 388 | 535ab96be208f115302facee73ae976e9174ac0b,0,0,0,0,0,0,0,0 389 | e531642e9bb5d027e9c20e03284287b97919a9a5,0,0,0,0,0,0,0,0 390 | 26e75307fc0c021472feb8f727839531f112f317,0,0,1,1,0,0,0,0 391 | e43f953a39a4681ac36f72977ec6998adc3d9f6a,0,0,0,0,0,0,0,0 392 | b9fca7a07f3e2ac4c113e2783ac5014c2a0252a2,0,0,0,0,0,0,0,0 393 | fb2a61c6da801aca637e0a8fb459ce22f5c241f9,0,0,0,0,0,0,0,0 394 | e1f243a9abfeef646be6bef7b8c2018276574294,0,0,0,0,0,0,0,0 395 | 78a73B6CBc5D183CE56e786f6e905CaDEC63547B,0,0,0,0,0,0,0,0 396 | bc1aB7F58a95cf307Ba5Ee18CF06b7eD0120da7a,0,0,0,0,0,0,0,0 397 | 942ffef843d37805c59f30fabb99b46aad135288,0,0,0,0,0,0,0,0 398 | f5056ed34e0c233f5a37b830533610a853296388,0,0,0,0,0,0,0,0 399 | cc5f26bf69b259b495a15427384e7f9668917d56,0,0,0,0,0,0,0,0 400 | a1877c74562821ff59ffc0bc999e6a2e164f4d87,0,0,0,0,0,0,0,0 401 | b0f94Af0cfCCC76113BB5bA2C2d89D56221B18A5,0,0,0,0,0,0,0,0 402 | D79B4C6791784184e2755B2fC1659eaaB0f80456,1,0,0,1,0,0,0,0 403 | 45699e1b4d79a63ef6fb39545a8eea713be714db,0,0,0,0,0,0,0,0 404 | 5fc6de61258e63706543bb57619b99cc0e5a5a1f,0,0,0,0,0,0,0,0 405 | 33a22bcafd6ef4e4a5e322f9a3910298a3c043a8,0,0,0,0,0,0,0,1 406 | 1748255382157bc5d4ed7e70c56afc5c97bddf07,0,0,0,0,0,0,0,0 407 | 8c79ec3f260b067157b0a7db0bb465f90b87f8f1,0,1,0,1,0,0,0,0 408 | 47d47c1f174bf9e7322974998e62968cec96257c,0,0,0,1,0,0,0,0 409 | ea3be67a30325e665a86ea4149c781b20a81e07f,0,0,0,0,0,0,0,0 410 | 611710ba93faf6d2964a94656771f76e6d05d5f0,0,0,0,0,0,0,0,0 411 | 1de2bfa2dfbca3af3848bfd9089ff84f447366f4,0,0,0,0,0,0,0,0 412 | 49edf201c1e139282643d5e7c6fb0c7219ad1db7,0,0,0,0,0,0,0,0 413 | 827d41446a2cb012d3011b94f525d6c46b32866d,0,0,0,0,0,0,0,0 414 | e0efd668c950e6d286bc1c5b9304f31632708656,0,0,0,0,0,0,0,0 415 | dc448e8a2a92a5ce799b197e982d773c605318a4,0,0,0,0,0,0,0,0 416 | 6d5cac36c1ae39f41d52393b7a425d0a610ad9f2,0,0,0,0,0,0,0,0 417 | a7fa7588cd7ebf3d0e128f07da7406dd74e241df,0,0,0,1,0,0,0,0 418 | ace62f87abe9f4ee9fd6e115d91548df24ca0943,0,0,0,0,0,0,0,0 419 | caef67f72114b4d2b4f43e7407455285b7de8de5,0,0,0,0,0,0,0,0 420 | 62e66080900fe39cd52bf5c0f8385b1339bedae5,0,0,0,0,0,0,0,0 421 | 357f07ac89ee6329a70ca837d6bfc16b0275015f,0,0,0,1,0,1,1,0 422 | 5311724c476327db0d5d1fc41cc58a466f3974bd,0,0,0,0,0,0,0,0 423 | f603c4161c388b77249486f9cb6f1741abda6a9b,0,0,0,0,0,0,0,0 424 | 32bacc8b241fb172fee18bda32527126c6f3c5f7,1,0,0,0,0,0,0,0 425 | 7e6614722614e434c4df9901bab31e466ba12fa4,0,0,0,0,0,0,0,0 426 | 7cb244b63ffa22d192c94d375e096f174e0faad2,0,0,0,0,0,0,0,0 427 | 7c32DB0645A259FaE61353c1f891151A2e7f8c1e,0,0,0,0,0,0,0,0 428 | c03281af336e2c25b41ff893a0e6ce1a932b23af,0,0,0,0,0,0,0,0 429 | f9a5e0436c01cc15708449e480fa5f2d6a5b55ca,0,0,0,0,0,0,0,0 430 | 3eb21f4678b352fcd8facf06b642c6720e04961b,0,0,0,0,0,0,0,0 431 | 007d42b9192b8C087b0D3E6ef73AAE48E74b41c1,1,0,0,0,0,0,1,0 432 | a9e4E3b1DA2462752AeA980698c335E70E9AB26C,1,0,0,0,0,0,1,0 433 | 89064da61e06c0e2035b5c8601c759ba60acb94d,0,0,0,0,0,0,0,0 434 | b49e984a83d7a638e7f2889fc8328952ba951abe,0,0,0,0,0,0,0,0 435 | fe211f86be5de898c9ebffe2c2b1d49ee8460b7f,0,0,0,0,0,0,0,0 436 | 8c628caaff01b61140f5576292bf57154e119b0b,0,0,0,0,0,0,0,0 437 | 6a3120d8a66fe96eb260cce4b6da02e7835b8426,0,0,0,0,0,0,0,0 438 | a6a180ce6432a356fb15ede85f63e1e6ffd7afeb,0,0,0,0,0,0,0,0 439 | 0348b55abd6e1a99c6ebc972a6a4582ec0bceb5c,0,0,0,0,0,0,1,0 440 | 54186df214506ff5613196170d1bd576895193ab,0,0,0,0,1,0,0,0 441 | 60ee1f74b96274a60b3dd5b92b35a49f86cfce80,0,0,0,0,0,0,0,0 442 | cce9fd6aea9fc618b98198b13599d2a0419534bb,0,0,0,0,0,0,0,0 443 | e495bcacaf29a0eb00fb67b86e9cd2a994dd55d8,0,0,0,0,0,0,0,0 444 | cff84054b8e0db57043376afdbfd2461a9965ce9,0,0,0,0,0,0,0,0 445 | 45aaf948ca47329f0059facb78806f1c63a3d197,0,0,0,0,0,0,0,0 446 | cd806502ad2f9aeb32e23f8d647341d4b568201d,0,0,0,0,0,0,0,0 447 | ea450e48e8d0da4332516a12c63c2232450caf6a,0,0,0,0,0,0,0,0 448 | 71703a8af6109a1613ae1181268b58d5333a90db,0,0,0,0,0,0,0,0 449 | 3b95e7496f55ecfd4d6db009879e3a8ce684940b,0,0,0,0,0,0,0,0 450 | b3775fb83f7d12a36e0475abdd1fca35c091efbe,0,0,0,0,0,0,0,0 451 | 828bE8eA7bbbe246216e7017b35057F64cf6449a,0,0,0,0,0,0,0,0 452 | 2c68efdd296f8a4f83ee46b12152a66dbe74b686,0,0,0,0,0,0,0,0 453 | ea88C23690b9F12ac6941E8a229aa4f94C72B8Db,0,0,0,0,0,0,0,1 454 | 558c62533def5e9d77a7e555490c0E2889EaCF3A,0,0,0,0,0,0,0,0 455 | d9489f5a7c4420e814f6216505b6754ebd4213f7,0,0,0,0,0,0,0,0 456 | c35dce7925cb3a33406abda3158a336f0a59cc0a,0,0,0,0,0,0,0,0 457 | 218aa06eabc62f2668b0a1e1307d9f7ec47d29a2,0,0,0,0,0,0,0,0 458 | c8d464c9906eb7a81a62f5ff658d7e4e68a8486b,0,0,0,0,0,0,0,0 459 | 1bb28e79f2482df6bf60efc7a33365703bcf1536,0,0,0,0,0,0,0,0 460 | 4aea7cf559f67cedcad07e12ae6bc00f07e8cf65,0,0,0,1,0,0,0,0 461 | a11cad54917fe2466dda7e20d2d335b10647ac86,0,0,0,0,0,0,0,0 462 | fc668AE14b0F7702c04b105448fE733D96C558DF,0,0,0,1,0,0,0,0 463 | 1c02ce498dc6d0d6ef05a253e021258b07eeba91,0,0,0,0,0,0,0,0 464 | 33a275B9cd129b34e5f0693D82d6d3Db26B0C3a0,0,0,0,0,0,0,0,0 465 | 4ddaf983302f451a5a6dc95af102335bf280d9a7,0,0,0,0,0,0,0,0 466 | 090fC358FA1a992C083590c7dd33Ad5208A02e9d,0,0,0,0,0,0,0,0 467 | 7da90089a73edd14c75b0c827cb54f4248d47ecc,0,0,0,0,0,0,1,0 468 | d0a6e6c54dbc68db5db3a091b171a77407ff7ccf,0,0,0,0,0,0,0,0 469 | ef82b51cd11b2cd198e7d9f7c75a486dd072194c,0,0,0,0,0,0,0,0 470 | D9BaBaf28e492F90dC900506B28834316eDed9e6,0,0,0,0,0,0,0,0 471 | a7f598984f6a77da416efaaf6ff18f5f7b9eeab2,0,0,0,0,0,0,0,0 472 | 09678741bd50c3e74301f38fbd0136307099ae5d,0,0,0,0,0,0,0,0 473 | bF29685856FAE1e228878DFB35B280C0adCC3B05,0,0,0,1,0,0,0,0 474 | e782146478f5d9f3ecc77a77c429f2941dced0f3,0,0,0,0,0,0,0,0 475 | b5fbae0361855617c58ef95a186889f0122e6642,0,0,0,0,0,0,0,0 476 | f0160428a8552ac9bb7e050d90eeade4ddd52843,0,0,1,0,0,0,0,0 477 | f1a35ded3f2f48d2a036f4ef586b725ceb0dddeb,0,0,0,0,0,0,0,0 478 | e25156d2c8d9ada4b02b4fd4b4190c003d0d781f,0,0,0,0,0,0,0,0 479 | F05EbadcF22b4dfd49d7f3AB59fd22C9fC49AF6F,0,0,0,0,0,0,0,0 480 | 815bde5591933ad1b025b6a34462d7ec02c71710,0,0,0,0,0,0,0,0 481 | 30cefbcb5c26a5b19a019092ab8d09f8739c904f,0,1,0,0,0,0,0,0 482 | 286bda1413a2df81731d4930ce2f862a35a609fe,0,0,0,0,0,0,0,0 483 | 75009ba0e084973d9c42fa81862d7076fae4500d,0,0,0,0,0,0,0,0 484 | 0E915b35cC269b2DfC8BbD8E4A88Ed4884a53EfC,0,0,0,0,0,0,0,0 485 | 878d7ed5c194349f37b18688964e8db1eb0fcca1,0,0,0,0,0,0,0,0 486 | 3ad158c1d0ba24eb86e4bc49a7944f08941ca7bc,0,0,0,0,0,0,0,0 487 | e4ba27aebaa3d09b2ac68b0c070a4d37ccc65cb7,0,0,0,0,0,0,0,0 488 | 4c1603e0834871ec3bab21d8db26de88db36bf9e,0,0,0,0,0,0,0,0 489 | 52e34238bacb8730d4804637891c87656b5407d5,0,0,0,0,0,0,0,0 490 | 50fcf0396874f1d4a4d243e8bb4c370c97f119bf,0,0,0,0,0,0,0,0 491 | d76b5c2a23ef78368d8e34288b5b65d616b746ae,0,0,0,0,0,0,0,0 492 | 7c8b63c4cf7a6009e06dc78d9a8352cd0541556f,1,0,0,0,0,0,0,0 493 | cadB1B36299FeD994c966107573D78b2872Ba490,0,0,0,0,0,0,0,0 494 | 5A5eFF38DA95b0D58b6C616f2699168B480953C9,0,0,0,0,0,0,0,0 495 | 9b2e81b42907e2bbd2bd76e36ba8ce1911db537e,0,0,0,0,0,0,0,0 496 | c3142db870ce470122f7d2d4d8d76ae5dda51dda,0,0,0,0,0,0,0,0 497 | cb6ab9c6fbbc955e25f916f66d5d807a2181bdf9,0,0,0,0,0,0,0,0 498 | 22164e957ac4c0cb0f19c49b05e627675436dfe1,0,0,0,0,0,0,0,0 499 | a33c4a314faa9684eeffa6ba334688001ea99bbc,0,0,0,0,0,0,0,0 500 | 904764ffe5A90F12282995b5674055c15093AEeA,0,0,0,0,0,0,0,0 501 | 2a0c0dbecc7e4d658f48e01e3fa353f44050c208,0,0,0,0,0,0,0,0 502 | 9c099997100fe55041b2028332A027ad7004AAc4,0,0,0,0,0,0,0,0 503 | 83c54a35e72ae07c46fc8f8f172a13ba19ac3bed,0,0,0,0,0,0,0,0 504 | ed667323cf62f4bbb62ec22038e34ed27e02a360,0,0,0,0,0,0,0,0 505 | 93519cc1a51ac56cf2daa8aaafcd4073f49a19d8,0,0,0,0,0,0,0,0 506 | 5783af06b94192a3f5f6610ecef477d033b70c74,0,0,0,0,0,0,0,0 507 | f48d72e5a2419c0c6f5822854b7bb7bf135d1623,0,0,0,0,0,0,0,0 508 | 4d09c5e758ca68be27240f29fb681e5a5341ca98,0,0,0,0,1,0,0,0 509 | 3cd4351f3c962f871024efef2922ae39896e4761,0,0,0,0,0,0,0,0 510 | 1bb7804d12fa4f70ab63d0bbe8cb0b1992694338,0,0,0,0,0,0,0,0 511 | a2eb247c2bebbd233b455a6c798ceba81e3aa320,0,0,0,0,0,0,0,0 512 | 6c5208924c5b302f756a79776a8b2918a041ad4d,0,0,0,0,0,0,0,0 513 | c2de2ce66f1f16c09e6a2c9595ac878db4113a88,0,0,0,0,0,0,0,0 514 | 6cD0Df6798Eb5C38408B772B39cED57F7C3A47b2,0,0,0,0,0,0,0,0 515 | 5535a72556727c221c567e0fc4208c5a99dba1cc,0,0,0,0,0,0,0,0 516 | 91BD62e48282eA188998D04570eD8a3e237d3A6A,0,0,0,0,0,0,0,0 517 | aa6e94908c4b2d020ef5f92bca529db958df106f,0,0,0,0,0,0,0,0 518 | 8d44d6b4ea99c865df1545a2dcb3aa445ba484bc,0,0,0,0,0,0,0,0 519 | 5052787b0B9cEC67442E2FF43D2176693377Bc5A,0,0,0,0,0,0,0,0 520 | c7d784274aaa0010f0c3dedd10eb66d49b7e4098,0,0,0,0,0,0,0,0 521 | a14c275277b788c20534066335e8bd3de77ffde4,0,0,0,0,0,0,0,0 522 | 66df48ba23c5e6cd5deb75f91bcc99030e2bf115,0,0,0,0,0,0,0,0 523 | 98f62d8ad5a884c8bbcf262591dff55dab263b80,0,0,0,0,0,0,0,0 524 | cc89405e3cfd38412093840a3ac2f851dd395dfb,0,0,0,1,0,0,0,0 525 | 91a57b2f6fa86b373bce5716eb26c81cbb004223,0,0,0,1,0,0,0,0 526 | 0dcfdb9f5496ed7f62dd0ac019c7daf184a66aef,0,0,0,0,0,0,0,0 527 | a94c128a138504e1f81d727cc21bcb9ae6581015,0,0,0,0,0,0,0,0 528 | 33a4b06a3ecc62062ecf3646eff39f952c8fffc9,0,0,0,0,0,0,0,0 529 | 3efb2bbdf798c5f9fe0dd932846fa1b031eac1fe,0,0,0,0,0,0,0,0 530 | 60e6b603b34b39ed22e95c10f360afde8a88d1e9,0,0,0,0,0,0,0,0 531 | 9ae98746EB8a0aeEe5fF2b6B15875313a986f103,0,0,0,0,0,0,0,0 532 | d20e5bab91720217637847365bf5932fe85f6fd3,0,0,0,0,0,0,0,0 533 | 1cf6949F4B661018B3195f3FF98effe12f587263,0,0,0,0,0,0,0,0 534 | 87d1ccf428832015d6108520d6d0909013753a62,0,0,0,0,0,0,0,0 535 | 3fd9aba22521d9ee3202a43bb132816a17973d43,0,0,0,0,0,0,0,0 536 | 177b63c7caf85a360074bcb095952aa8e929ae03,0,0,0,0,0,0,0,0 537 | feac34425a3ba2fafbbeedb367ac5f4b4bb701d2,0,0,0,1,0,0,0,0 538 | fdfe8b7ab6cf1bd1e3d14538ef40686296c42052,0,0,0,0,0,0,0,0 539 | fb950d858dab0594f4cffb77201215ee46d8b304,0,0,0,0,0,0,0,0 540 | Ad1aA68300588Aa5842751DDCAb2AFd4a69e9016,1,0,1,0,0,0,0,0 541 | 276f5da0f6c7b55129570ac7195e6e65122a4cd0,0,0,0,0,0,0,0,0 542 | c39d73fca64d4ffe2c78fb17e61b9c8489f7c5fb,0,0,0,0,0,0,0,0 543 | 060e1e5ca588561431822e296aeab1fdecc893dc,0,0,0,0,0,0,0,0 544 | 655C072286A8ab7B33B16Aa6908CFECDe39E57a1,0,0,0,0,0,0,0,0 545 | 092d3374f942bb4a99ce64f37fa7e661fdd1e74c,0,0,0,0,0,0,0,0 546 | fD2487cc0e5dCe97F08BE1Bc8eF1DCE8D5988B4D,1,0,0,0,0,0,0,0 547 | 14c6c5b52827b9fffef52e08ee2479498e5c9cf3,0,0,0,0,0,0,0,0 548 | 8015302bc5163b9fdaf03c1c952cbe5d21dc6d4b,0,0,0,0,0,0,0,0 549 | 90420B8aef42F856a0AFB4FFBfaA57405FB190f3,0,0,0,0,0,0,0,0 550 | 55648de19836338549130b1af587f16bea46f66b,0,0,0,0,0,0,0,0 551 | 8f548f0ceb23ddc9ee76e126b29fae94c607c3bc,0,0,0,0,0,0,0,0 552 | f665069a0ee102ceadbd80690814473dbdd56ac8,0,0,0,0,0,0,0,0 553 | 141766882733cafa9033e8707548fdcac908db22,0,0,0,0,0,0,0,0 554 | A5d1e58ECe1fC438d64E65769d2ab730143a4Caf,0,0,0,0,0,0,0,0 555 | 47f9c2af8111c76a64355433f116920bfa8bd1e1,0,0,0,0,0,0,0,0 556 | ACbfB851D69EF8Eca1453d82f38B590268ca46B1,0,0,0,0,0,0,0,0 557 | 9f00f10e226ec430e888d6311e3f65e62093a9ac,0,0,0,0,0,0,0,0 558 | 9Ea7BA960A2668Df52eE0389C4617D48853b7006,0,0,0,0,0,0,0,0 559 | 9bbb9387c9e2477a6b5d81afece00255875c48ce,0,0,0,0,0,0,0,1 560 | ccf09a5a9449b8d39e27f7fcffbb1a30ec29c8db,0,0,0,0,0,0,0,0 561 | 747616c4a19bd9bf1e2b6c8a77d206ea1f9c6018,0,0,0,0,0,0,0,0 562 | b77fd7187f7d4ba1f90a924c9d4264d4c458e5b3,0,0,0,0,0,0,0,0 563 | 2e2e617e4625c6a30a3290dde5b689212ff061e8,0,0,0,0,0,0,0,0 564 | eb51df201213a067227115662ec3787b92956890,0,0,0,0,0,0,0,0 565 | 6425c6BE902d692AE2db752B3c268AFAdb099D3b,0,0,0,0,0,0,0,0 566 | 13ea82d5e1a811f55bda9c86fdd6195a6bd23aed,0,0,0,0,0,0,0,0 567 | 2c1180e2818069e5a9f911e636fb8f3db5106a9f,0,0,0,0,1,0,0,0 568 | 44633fb7593c31339abfa5f9d2d85bf516b201f6,0,0,0,0,0,0,0,0 569 | 9BD8f4736877567E267ee445209a0b2aAFc01402,0,0,0,0,0,0,0,0 570 | d7bc93f391e94557fa621711699d1a5fd38d5ad5,0,0,0,0,0,0,0,0 571 | 472b76c61aa0eb8134a8eb1220c2598f33ce6b67,0,0,0,0,0,0,0,0 572 | 9cb8921aa376219950ba134c15d8f5ee2769c599,0,0,0,0,0,0,0,0 573 | 84e8a50ca43e8f26094799ba60705475cf2b9832,1,0,0,0,0,0,0,0 574 | fdf4411669fc6e8951a6ae987307d7582fda7a05,0,0,0,0,0,0,0,0 575 | e0b7927c4af23765cb51314a0e0521a9645f0e2a,0,0,0,0,0,0,0,0 576 | 9a41c88972a5e65d7a61aa7cf07cde6898feffeb,0,0,0,0,0,0,0,0 577 | 2ebdfaa028d682472f4e084fcf7c624098b776e1,0,0,0,0,0,0,0,0 578 | 208d6ed75f6aacdb9c71099c0943736fddbf5989,0,0,0,0,0,0,0,0 579 | 1e02f2293a67bc57700c542d7ca135394193c038,0,0,0,0,0,1,1,0 580 | ddf0d0b9914d530e0b743808249d9af901f1bd01,0,0,0,0,0,0,0,0 581 | ,22,5,5,42,6,6,13,12 -------------------------------------------------------------------------------- /DefectChecker/DefectChecker.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /DefectChecker/out/production/DefectChecker/BasicBlock.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jiachi-Chen/DefectChecker/e9cab0a43586f2da518df2f385aff14f9491197d/DefectChecker/out/production/DefectChecker/BasicBlock.class -------------------------------------------------------------------------------- /DefectChecker/out/production/DefectChecker/BinaryAnalyzer.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jiachi-Chen/DefectChecker/e9cab0a43586f2da518df2f385aff14f9491197d/DefectChecker/out/production/DefectChecker/BinaryAnalyzer.class -------------------------------------------------------------------------------- /DefectChecker/out/production/DefectChecker/DefectChecker.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jiachi-Chen/DefectChecker/e9cab0a43586f2da518df2f385aff14f9491197d/DefectChecker/out/production/DefectChecker/DefectChecker.class -------------------------------------------------------------------------------- /DefectChecker/out/production/DefectChecker/EVMSimulator.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jiachi-Chen/DefectChecker/e9cab0a43586f2da518df2f385aff14f9491197d/DefectChecker/out/production/DefectChecker/EVMSimulator.class -------------------------------------------------------------------------------- /DefectChecker/out/production/DefectChecker/Main.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jiachi-Chen/DefectChecker/e9cab0a43586f2da518df2f385aff14f9491197d/DefectChecker/out/production/DefectChecker/Main.class -------------------------------------------------------------------------------- /DefectChecker/out/production/DefectChecker/Pair.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jiachi-Chen/DefectChecker/e9cab0a43586f2da518df2f385aff14f9491197d/DefectChecker/out/production/DefectChecker/Pair.class -------------------------------------------------------------------------------- /DefectChecker/out/production/DefectChecker/Utils$1.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jiachi-Chen/DefectChecker/e9cab0a43586f2da518df2f385aff14f9491197d/DefectChecker/out/production/DefectChecker/Utils$1.class -------------------------------------------------------------------------------- /DefectChecker/out/production/DefectChecker/Utils.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jiachi-Chen/DefectChecker/e9cab0a43586f2da518df2f385aff14f9491197d/DefectChecker/out/production/DefectChecker/Utils.class -------------------------------------------------------------------------------- /DefectChecker/src/BasicBlock.java: -------------------------------------------------------------------------------- 1 | import java.util.ArrayList; 2 | import java.util.LinkedList; 3 | 4 | public class BasicBlock { 5 | public static final int CONDITIONAL = 1; 6 | public static final int UNCONDITIONAL = 2; 7 | public static final int FALL = 3; 8 | public static final int TERMINAL = 4; 9 | 10 | public int startBlockPos = -1; 11 | public int endBlockPos = -1; 12 | public ArrayList>> instrList = null; 13 | public LinkedList evm_stack = null; 14 | public StringBuilder instrString = null; 15 | 16 | public int fallPos = -1; 17 | public int conditionalJumpPos = -1; 18 | public String conditionalJumpExpression = ""; 19 | public int unconditionalJumpPos = -1; 20 | public int jumpType = 3; //1: conditional 2: unconditional 3: fall 4: terminal 21 | public boolean isCircle = false; 22 | public boolean isCircleStart = false; 23 | public boolean moneyCall = false; 24 | 25 | public BasicBlock(){ 26 | evm_stack = new LinkedList<>(); 27 | instrList = new ArrayList<>(); 28 | instrString = new StringBuilder(); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /DefectChecker/src/BinaryAnalyzer.java: -------------------------------------------------------------------------------- 1 | import java.util.*; 2 | 3 | public class BinaryAnalyzer { 4 | 5 | public TreeMap pos2BlockMap = new TreeMap<>(); 6 | public ArrayList publicFunctionStartList = new ArrayList<>(); //all the functions that can be called by others. Fallback function is not included 7 | public ArrayList stackEvents = new ArrayList<>(); 8 | public HashSet allInstrs = new HashSet<>(); 9 | public ArrayList startPosList = new ArrayList<>(); 10 | public ArrayList>> disasm = null; 11 | public String disasmCode = null; 12 | public boolean versionGap = false; 13 | public boolean legalContract = true; 14 | public double codeCoverage = 0; 15 | public Integer fallbackPos = -1; 16 | public boolean misRecognizedJump = false; 17 | public int cyclomatic_complexity = 0; 18 | public int numInster = 0; 19 | private HashSet visitBlock = null; 20 | private HashSet totalEdge = null; 21 | 22 | public ArrayList> allCallPath = null; 23 | public HashMap allCirclePath2StartPos = null; 24 | 25 | private ArrayList> allCirclePath = null; 26 | public BinaryAnalyzer(String bytecode){ 27 | if(init(bytecode)){ 28 | getBasicBlock(); 29 | addFallEdges(); 30 | buildCFG(); 31 | detectBlockFeatures(); 32 | } 33 | } 34 | 35 | private boolean init(String bytecode){ 36 | String disasmCode = Utils.getDisasmCode(bytecode); 37 | if(disasmCode == null || disasmCode.length() < 1 || !disasmCode.contains("STOP")){ 38 | legalContract = false; 39 | System.out.println("Disasm Failed"); 40 | return false; 41 | } 42 | // System.out.println(disasmCode); 43 | this.disasmCode = disasmCode; 44 | this.disasm = Utils.disasmParser(disasmCode); 45 | this.allCallPath = new ArrayList<>(); 46 | this.allCirclePath2StartPos = new HashMap<>(); 47 | this.allCirclePath = new ArrayList<>(); 48 | this.visitBlock = new HashSet(); 49 | this.totalEdge = new HashSet<>(); 50 | return true; 51 | } 52 | 53 | private void getBasicBlock() { 54 | BasicBlock block = null; 55 | boolean start = true; 56 | int lastPos = -1; 57 | for (int i = 0; i < this.disasm.size(); i++) { 58 | Pair> instr_pair = disasm.get(i); 59 | int pos = instr_pair.getFirst(); 60 | String instr = instr_pair.getSecond().getFirst(); 61 | allInstrs.add(instr); 62 | if (start || instr.equals("JUMPDEST")) { 63 | if (i != 0) { 64 | block.endBlockPos = lastPos; 65 | this.pos2BlockMap.put(block.startBlockPos, block); 66 | } 67 | block = new BasicBlock(); 68 | block.startBlockPos = pos; 69 | this.startPosList.add(pos); 70 | start = false; 71 | } 72 | 73 | else if (instr.equals("JUMPI")) { 74 | start = true; 75 | block.jumpType = BasicBlock.CONDITIONAL; 76 | 77 | } 78 | 79 | else if (instr.equals("JUMP")) { 80 | start = true; 81 | block.jumpType = BasicBlock.UNCONDITIONAL; 82 | } 83 | 84 | //some blocks may only have one instr, so we use if rathar than else if 85 | if (instr.equals("STOP") || instr.equals("RETURN") || instr.equals("REVERT") 86 | || instr.equals("SELFDESTRUCT") || instr.equals("ASSERTFAIL")) { 87 | start = true; 88 | block.jumpType = BasicBlock.TERMINAL; 89 | } 90 | 91 | block.instrList.add(instr_pair); 92 | block.instrString.append(instr).append(" "); 93 | 94 | lastPos = pos; 95 | if(i == this.disasm.size() - 1){ 96 | block.endBlockPos = lastPos; 97 | this.pos2BlockMap.put(block.startBlockPos, block); 98 | } 99 | } 100 | } 101 | 102 | private void addFallEdges(){ 103 | //Edges of fall to 104 | for(int i = 0; i < this.startPosList.size()-1; i++){ 105 | int startPos = startPosList.get(i); 106 | BasicBlock block = this.pos2BlockMap.get(startPos); 107 | if(block.jumpType == BasicBlock.FALL || block.jumpType == BasicBlock.CONDITIONAL){ 108 | block.fallPos = startPosList.get(i+1); 109 | } 110 | } 111 | } 112 | 113 | private void buildCFG(){ 114 | EVMSimulator simulator = new EVMSimulator(this.pos2BlockMap); 115 | this.pos2BlockMap = simulator.pos2BlockMap; 116 | this.stackEvents = simulator.stackEvents; 117 | this.versionGap = simulator.versionGap; 118 | this.misRecognizedJump = simulator.misRecognizedJump; 119 | if(versionGap){ 120 | System.out.println("Bytecode version may not support. The default Solidity version is 0.4.25; "); 121 | } 122 | } 123 | 124 | private void flagLoop(ArrayList totalPath, int startLoopPos){ 125 | 126 | BasicBlock startLoopBlock = this.pos2BlockMap.get(startLoopPos); 127 | startLoopBlock.isCircleStart = true; 128 | boolean start = false; 129 | ArrayList circlePath = new ArrayList<>(); 130 | for(int i = 0;i < totalPath.size(); i++){ 131 | int pos = totalPath.get(i); 132 | if(pos == startLoopPos) 133 | start = true; 134 | if(start){ 135 | BasicBlock block = this.pos2BlockMap.get(pos); 136 | block.isCircle = true; 137 | circlePath.add(block.startBlockPos); 138 | if(i < totalPath.size() - 1){ 139 | String path = String.valueOf(pos) + "_" + String.valueOf(totalPath.get(i+1)); 140 | this.allCirclePath2StartPos.put(path, startLoopPos); 141 | } 142 | else if(i == totalPath.size()-1){ 143 | String path = String.valueOf(pos) + "_" + String.valueOf(startLoopPos); 144 | this.allCirclePath2StartPos.put(path, startLoopPos); 145 | } 146 | } 147 | } 148 | this.allCirclePath.add(circlePath); 149 | } 150 | 151 | private void printPath(ArrayList currentPath){ 152 | String path = ""; 153 | for(Integer pos : currentPath) 154 | path += String.valueOf(pos) + " "; 155 | System.out.println("Length: " + currentPath.size() + " ==> " + path); 156 | 157 | } 158 | private void findCallPathAndLoops(ArrayList currentPath, BasicBlock block, HashSet visited){ 159 | // printPath(currentPath); 160 | this.visitBlock.add(block.startBlockPos); 161 | if(block.instrString.toString().contains("CALL ")){ 162 | this.allCallPath.add(currentPath); 163 | } 164 | 165 | if(block.jumpType == BasicBlock.CONDITIONAL){ 166 | int left_branch = block.conditionalJumpPos; 167 | String path = String.valueOf(block.startBlockPos) + "_" + String.valueOf(left_branch); 168 | this.totalEdge.add(path); 169 | 170 | if(!visited.contains(path) && left_branch > 0) { 171 | visited.add(path); 172 | ArrayList newPath = (ArrayList) currentPath.clone(); 173 | newPath.add(left_branch); 174 | 175 | findCallPathAndLoops(newPath, this.pos2BlockMap.get(left_branch), visited); 176 | } 177 | 178 | else if(this.allCirclePath2StartPos.containsKey(path)){ 179 | flagLoop(currentPath, this.allCirclePath2StartPos.get(path)); 180 | } 181 | 182 | else if(currentPath.contains(left_branch) && left_branch > 0){ 183 | flagLoop(currentPath, block.startBlockPos); 184 | } 185 | 186 | 187 | int right_branch = block.fallPos; 188 | path = String.valueOf(block.startBlockPos) + "_" + String.valueOf(right_branch); 189 | this.totalEdge.add(path); 190 | if(!visited.contains(path) && right_branch > 0) { 191 | visited.add(path); 192 | ArrayList newPath = (ArrayList) currentPath.clone(); 193 | newPath.add(right_branch); 194 | findCallPathAndLoops(newPath, this.pos2BlockMap.get(right_branch), visited); 195 | } 196 | else if(this.allCirclePath2StartPos.containsKey(path)){ 197 | flagLoop(currentPath, this.allCirclePath2StartPos.get(path)); 198 | } 199 | else if(currentPath.contains(right_branch) && right_branch > 0){ 200 | flagLoop(currentPath, block.startBlockPos); 201 | } 202 | 203 | } 204 | 205 | else if(block.jumpType == BasicBlock.UNCONDITIONAL){ 206 | int jumpPos = block.unconditionalJumpPos; 207 | String path = String.valueOf(block.startBlockPos) + "_" + String.valueOf(jumpPos); 208 | this.totalEdge.add(path); 209 | if(!visited.contains(path) && jumpPos > 0) { 210 | visited.add(path); 211 | ArrayList newPath = (ArrayList) currentPath.clone(); 212 | newPath.add(jumpPos); 213 | findCallPathAndLoops(newPath, this.pos2BlockMap.get(jumpPos), visited); 214 | } 215 | else if(this.allCirclePath2StartPos.containsKey(path)){ 216 | flagLoop(currentPath, this.allCirclePath2StartPos.get(path)); 217 | } 218 | else if(currentPath.contains(jumpPos) && jumpPos > 0){ 219 | flagLoop(currentPath, block.startBlockPos); 220 | } 221 | 222 | } 223 | 224 | else if(block.jumpType == BasicBlock.FALL){ 225 | int jumpPos = block.fallPos; 226 | String path = String.valueOf(block.startBlockPos) + "_" + String.valueOf(jumpPos); 227 | this.totalEdge.add(path); 228 | if(!visited.contains(path)) { 229 | visited.add(path); 230 | ArrayList newPath = (ArrayList) currentPath.clone(); 231 | newPath.add(jumpPos); 232 | findCallPathAndLoops(newPath, this.pos2BlockMap.get(jumpPos), visited); 233 | } 234 | 235 | } 236 | 237 | 238 | 239 | } 240 | 241 | 242 | private void detectBlockFeatures(){ 243 | BasicBlock block = this.pos2BlockMap.get(0); 244 | 245 | //Detect public functions' positions 246 | while(block.fallPos != -1){ 247 | if(block.instrList.get(0).getSecond().getFirst().equals("JUMPDEST")) 248 | break; 249 | if(block.conditionalJumpPos != -1 && block.conditionalJumpExpression.startsWith("EQ")){ 250 | publicFunctionStartList.add(block.conditionalJumpPos); 251 | } 252 | else 253 | this.fallbackPos = block.conditionalJumpPos; 254 | block = this.pos2BlockMap.get(block.fallPos); 255 | } 256 | if(this.pos2BlockMap.size() <= 4 && this.pos2BlockMap.get(0).instrString.toString().contains("CALLVALUE")) 257 | this.fallbackPos = 0; 258 | 259 | //Detect falback function's position 260 | //fallback function's position == this.pos2BlockMap.get(0).conditionalJumpPos; 261 | 262 | 263 | findCallPathAndLoops(new ArrayList<>(), this.pos2BlockMap.get(0), new HashSet<>()); 264 | 265 | int visitedInstr = 0; 266 | int totalInstr = 0; 267 | for(Map.Entry entry : this.pos2BlockMap.entrySet()){ 268 | BasicBlock tmp = entry.getValue(); 269 | int instrNum = tmp.instrList.size(); 270 | if(this.visitBlock.contains(tmp.startBlockPos)){ 271 | visitedInstr += instrNum; 272 | } 273 | totalInstr += instrNum; 274 | } 275 | this.codeCoverage = (double)visitedInstr / totalInstr; 276 | this.cyclomatic_complexity = this.totalEdge.size() - visitBlock.size() + 2; 277 | this.numInster = this.disasm.size(); 278 | // System.out.println("Start Detecting code smells"); 279 | 280 | } 281 | 282 | } 283 | -------------------------------------------------------------------------------- /DefectChecker/src/DefectChecker.java: -------------------------------------------------------------------------------- 1 | import java.lang.reflect.Array; 2 | import java.util.*; 3 | import java.util.regex.Matcher; 4 | import java.util.regex.Pattern; 5 | 6 | public class DefectChecker { 7 | public boolean hasUnchechedExternalCalls = false; 8 | public boolean hasStrictBalanceEquality = false; 9 | public boolean hasTransactionStateDependency = false; 10 | public boolean hasBlockInfoDependency = false; 11 | public boolean hasGreedyContract = false; 12 | public boolean hasDoSUnderExternalInfluence = false; 13 | public boolean hasNestCall = false; 14 | public boolean hasReentrancy = false; 15 | 16 | public BinaryAnalyzer binaryAnalyzer = null; 17 | public DefectChecker(BinaryAnalyzer binaryAnalyzer){ 18 | this.binaryAnalyzer = binaryAnalyzer; 19 | } 20 | 21 | public void detectAllSmells(){ 22 | 23 | this.hasUnchechedExternalCalls = detectUnchechedExternalCalls(); 24 | this.hasStrictBalanceEquality = detectStrictBalanceEquality(); 25 | this.hasTransactionStateDependency = detectTransactionStateDependency(); 26 | this.hasBlockInfoDependency = detectBlockInfoDependency(); 27 | this.hasGreedyContract = detectGreedyContract(); 28 | this.hasDoSUnderExternalInfluence = detectDoSUnderExternalInfluence(); 29 | this.hasNestCall = detectNestCall(); 30 | this.hasReentrancy = detectReentrancy(); 31 | } 32 | 33 | 34 | public boolean detectUnchechedExternalCalls(){ 35 | if(!binaryAnalyzer.allInstrs.contains("CALL")) 36 | return false; 37 | boolean res = false; 38 | boolean start = false; 39 | String callPC = ""; 40 | for(String event : binaryAnalyzer.stackEvents){ 41 | String eventLog = event.split(" ==> ")[2]; 42 | if(eventLog.startsWith("CALL_")){ 43 | start = true; 44 | callPC = eventLog.split(" ")[0]; 45 | continue; 46 | } 47 | if(start){ 48 | //CALL instr does not checked by ISZERO 49 | if(!eventLog.contains(callPC)){ 50 | res = true; 51 | break; 52 | } 53 | if(eventLog.startsWith("ISZERO_")){ 54 | String top = eventLog.split(" ")[0]; 55 | //if CALL instr is checked by ISZERO, it means it's a legal CALL 56 | if(top.contains(callPC)){ 57 | callPC = ""; 58 | start = false; 59 | } 60 | } 61 | } 62 | } 63 | return res; 64 | } 65 | 66 | public boolean detectStrictBalanceEquality(){ 67 | if(!binaryAnalyzer.allInstrs.contains("BALANCE")) 68 | return false; 69 | boolean res = false; 70 | boolean startBalance = false; 71 | boolean startEQ = false; 72 | String balancePC = ""; 73 | String eqPC = ""; 74 | for(String event : binaryAnalyzer.stackEvents){ 75 | String eventLog = event.split(" ==> ")[2].split(" ")[0]; 76 | if(eventLog.startsWith("BALANCE_")){ 77 | startBalance = true; 78 | balancePC = eventLog.split(" ")[0]; 79 | continue; 80 | } 81 | if(startBalance){ 82 | 83 | if(!eventLog.contains(balancePC)){ 84 | startBalance = false; 85 | startEQ = false; 86 | balancePC = ""; 87 | eqPC = ""; 88 | continue; 89 | } 90 | 91 | if(startEQ){ 92 | if(!eventLog.contains(eqPC)){ 93 | startBalance = false; 94 | startEQ = false; 95 | balancePC = ""; 96 | eqPC = ""; 97 | continue; 98 | } 99 | //Balance && EQ && ISZERO ==> has code smell. 100 | if(eventLog.startsWith("ISZERO_")){ 101 | String top = eventLog.split(" ")[0]; 102 | 103 | //may be there contrains other eq, so we should check it. 104 | if(top.contains(eqPC)){ 105 | res = true; 106 | break; 107 | } 108 | } 109 | } 110 | 111 | if(eventLog.startsWith("EQ_")){ 112 | startEQ = true; 113 | eqPC = eventLog.split(" ")[0]; 114 | } 115 | } 116 | } 117 | return res; 118 | } 119 | 120 | public boolean detectTransactionStateDependency(){ 121 | if(!binaryAnalyzer.allInstrs.contains("ORIGIN")) 122 | return false; 123 | boolean res = false; 124 | boolean start = false; 125 | String originPC = ""; 126 | for(String event : binaryAnalyzer.stackEvents){ 127 | String eventLog = event.split(" ==> ")[2]; 128 | if(eventLog.startsWith("ORIGIN_")){ 129 | start = true; 130 | originPC = eventLog.split(" ")[0]; 131 | continue; 132 | } 133 | 134 | if(start){ 135 | if(!eventLog.contains(originPC)){ 136 | start = false; 137 | originPC = ""; 138 | continue; 139 | } 140 | if(eventLog.startsWith("EQ_")){ 141 | String top = eventLog.split(" ")[0]; 142 | if(top.contains(originPC)){ 143 | res = true; 144 | break; 145 | //EXAMPLE: EQ_1210(AND_1209(PUSH20_1188,ORIGIN_1187),AND_1186(PUSH20_1165,AND_1164(PUSH20_1143,DIV_1142(SLOAD_1135(0_1131),1_1140)))) 146 | // Pair splitedInstr = Utils.splitInstr2(top); 147 | // String address = ""; 148 | // if(splitedInstr.getFirst().contains(originPC)) 149 | // address = splitedInstr.getSecond(); 150 | // else if(splitedInstr.getSecond().contains(originPC)) 151 | // address = splitedInstr.getFirst(); 152 | // if(address.startsWith("AND_")){ 153 | // Pair splitedAddr = Utils.splitInstr2(address); 154 | // if((splitedAddr.getFirst().contains("PUSH20_") && splitedAddr.getSecond().contains("SLOAD_")) || 155 | // (splitedAddr.getSecond().contains("PUSH20_") && splitedAddr.getFirst().contains("SLOAD_"))) 156 | // { 157 | // res = true; 158 | // break; 159 | // } 160 | // } 161 | } 162 | 163 | } 164 | } 165 | } 166 | return res; 167 | } 168 | 169 | public boolean detectBlockInfoDependency(){ 170 | String[] blockInstr = new String[]{"BLOCKHASH", "COINBASE", "NUMBER", "DIFFICULTY", "GASLIMIT"}; 171 | boolean res = false; 172 | for(Map.Entry entry : this.binaryAnalyzer.pos2BlockMap.entrySet()){ 173 | BasicBlock block = entry.getValue(); 174 | if(block.conditionalJumpExpression.length() > 1){ 175 | for(String instr : blockInstr){ 176 | if(block.conditionalJumpExpression.contains(instr)){ 177 | res = true; 178 | break; 179 | } 180 | } 181 | } 182 | } 183 | return res; 184 | } 185 | 186 | public boolean isPayable(Integer startPos){ 187 | if(startPos == -1) 188 | return false; 189 | boolean payable = true; 190 | BasicBlock block = this.binaryAnalyzer.pos2BlockMap.get(startPos); 191 | BasicBlock fall = this.binaryAnalyzer.pos2BlockMap.get(block.fallPos); 192 | String conditionalJumpExpression = block.conditionalJumpExpression; 193 | if(conditionalJumpExpression.contains("CALLVALUE")){ 194 | if(Pattern.matches("ISZERO_[0-9]+?\\(CALLVALUE_[0-9]+?\\)", conditionalJumpExpression)){ 195 | if(fall.jumpType == BasicBlock.TERMINAL){ 196 | payable = false; 197 | } 198 | } 199 | } 200 | if(conditionalJumpExpression.equals("") && block.jumpType == BasicBlock.TERMINAL) 201 | payable = false; 202 | return payable; 203 | 204 | } 205 | 206 | public boolean detectGreedyContract(){ 207 | //if a contract can receive money(contains payable function), but cannot send ETH(do not contains CALL/SELFDESTRUCT) 208 | 209 | if(this.binaryAnalyzer.allInstrs.contains("SELFDESTRUCT")) 210 | return false; 211 | boolean payable = false; 212 | boolean canSentMoney = false; 213 | if(isPayable(this.binaryAnalyzer.fallbackPos)) 214 | payable = true; 215 | for(Integer pos : this.binaryAnalyzer.publicFunctionStartList){ 216 | if(isPayable(pos)) 217 | payable = true; 218 | } 219 | for(Map.Entry entry : this.binaryAnalyzer.pos2BlockMap.entrySet()){ 220 | BasicBlock block = entry.getValue(); 221 | // if(block.moneyCall) 222 | if(block.instrString.toString().contains("CALL ")) 223 | canSentMoney = true; 224 | } 225 | if(payable && !canSentMoney) 226 | return true; 227 | return false; 228 | } 229 | 230 | public boolean detectDoSUnderExternalInfluence(){ 231 | for(Map.Entry entry : this.binaryAnalyzer.pos2BlockMap.entrySet()){ 232 | BasicBlock block = entry.getValue(); 233 | if(block.isCircle){ 234 | 235 | if(block.jumpType == BasicBlock.CONDITIONAL && block.moneyCall){ 236 | BasicBlock fall = this.binaryAnalyzer.pos2BlockMap.get(block.fallPos); 237 | if(fall.jumpType == BasicBlock.TERMINAL) 238 | return true; 239 | } 240 | } 241 | } 242 | return false; 243 | } 244 | 245 | public boolean detectNestCall(){ 246 | if(!this.binaryAnalyzer.allInstrs.contains("CALL")) 247 | return false; 248 | if(!this.binaryAnalyzer.allInstrs.contains("SLOAD")) 249 | return false; 250 | int slotID = -1; 251 | boolean slotSizeLimit = false; //if do not limit slot size && have CALL ==> Nest Call 252 | boolean hasCall = false; 253 | for(Map.Entry entry : this.binaryAnalyzer.pos2BlockMap.entrySet()){ 254 | BasicBlock block = entry.getValue(); 255 | if(block.isCircleStart){ 256 | String condition = block.conditionalJumpExpression; 257 | if(!condition.contains("SLOAD")) 258 | continue; 259 | slotID = Utils.getSlotID(condition); 260 | if(slotID == -1) 261 | continue; 262 | 263 | //BFS-travel to circle body and detect whether a jumpCondition contains slotID. 264 | Queue que = new LinkedList<>(); 265 | HashSet visited = new HashSet<>(); 266 | visited.add(block.startBlockPos); 267 | que.offer(this.binaryAnalyzer.pos2BlockMap.get(block.conditionalJumpPos)); 268 | que.offer(this.binaryAnalyzer.pos2BlockMap.get(block.fallPos)); 269 | while(!que.isEmpty()){ 270 | BasicBlock topBlock = que.poll(); 271 | if(topBlock.conditionalJumpExpression.length() > 0){ 272 | if(topBlock.conditionalJumpExpression.contains("SLOAD_") 273 | && (topBlock.conditionalJumpExpression.contains("LT") || 274 | topBlock.conditionalJumpExpression.contains("GT"))){ 275 | int id = Utils.getSlotID(topBlock.conditionalJumpExpression); 276 | if(id == slotID) { 277 | String[] tmp = topBlock.instrString.toString().split(" "); 278 | int idx = 0; 279 | for(idx = 0;idx < tmp.length;idx++){ 280 | if(tmp[idx].equals("SLOAD")) 281 | break; 282 | } 283 | if(idx > 2){ 284 | if(tmp[idx-1].startsWith("DUP") && tmp[idx-2].startsWith("PUSH")){ 285 | slotSizeLimit = true; 286 | break; 287 | } 288 | } 289 | } 290 | } 291 | } 292 | // if(topBlock.instrString.toString().contains("CALL ")){ 293 | if(topBlock.moneyCall){ 294 | hasCall = true; 295 | } 296 | 297 | if(topBlock.jumpType == BasicBlock.CONDITIONAL){ 298 | if(topBlock.conditionalJumpPos > 0){ 299 | BasicBlock child1 = this.binaryAnalyzer.pos2BlockMap.get(topBlock.conditionalJumpPos); 300 | if(child1.isCircle && !visited.contains(child1.startBlockPos)) 301 | que.offer(child1); 302 | visited.add(child1.startBlockPos); 303 | } 304 | BasicBlock child2 = this.binaryAnalyzer.pos2BlockMap.get(topBlock.fallPos); 305 | if(child2.isCircle && !visited.contains(child2.startBlockPos)) 306 | que.offer(child2); 307 | visited.add(child2.startBlockPos); 308 | } 309 | else if(topBlock.jumpType == BasicBlock.UNCONDITIONAL){ 310 | if(topBlock.unconditionalJumpPos > 0){ 311 | BasicBlock child = this.binaryAnalyzer.pos2BlockMap.get(topBlock.unconditionalJumpPos); 312 | if(child.isCircle && !visited.contains(child.startBlockPos)) 313 | que.offer(child); 314 | visited.add(child.startBlockPos); 315 | } 316 | } 317 | else if(topBlock.jumpType == BasicBlock.FALL){ 318 | BasicBlock child = this.binaryAnalyzer.pos2BlockMap.get(topBlock.fallPos); 319 | if(child.isCircle && !visited.contains(child.startBlockPos)) 320 | que.offer(child); 321 | visited.add(child.startBlockPos); 322 | } 323 | } 324 | 325 | if(slotSizeLimit) 326 | return false; 327 | } 328 | } 329 | 330 | if(hasCall) 331 | return true; 332 | return false; 333 | } 334 | 335 | 336 | // public void findCallPath(ArrayList currentPath, BasicBlock block, HashSet visited){ 337 | // visited.add(block.startBlockPos); 338 | // if(block.instrString.toString().contains("CALL ")){ 339 | // this.binaryAnalyzer.allCallPath.add(currentPath); 340 | //// return; 341 | // } 342 | // if(block.jumpType == BasicBlock.CONDITIONAL){ 343 | // int left_branch = block.conditionalJumpPos; 344 | // if(!visited.contains(left_branch) && left_branch > 0) { 345 | // ArrayList newPath = (ArrayList) currentPath.clone(); 346 | // newPath.add(left_branch); 347 | // findCallPath(newPath, this.binaryAnalyzer.pos2BlockMap.get(left_branch), visited); 348 | // } 349 | // 350 | // int right_branch = block.fallPos; 351 | // if(!visited.contains(right_branch)) { 352 | // ArrayList newPath = (ArrayList) currentPath.clone(); 353 | // newPath.add(right_branch); 354 | // findCallPath(newPath, this.binaryAnalyzer.pos2BlockMap.get(right_branch), visited); 355 | // } 356 | // 357 | // } 358 | // 359 | // else if(block.jumpType == BasicBlock.UNCONDITIONAL){ 360 | // int jumpPos = block.unconditionalJumpPos; 361 | // if(!visited.contains(jumpPos) && jumpPos > 0) { 362 | // ArrayList newPath = (ArrayList) currentPath.clone(); 363 | // newPath.add(jumpPos); 364 | // findCallPath(newPath, this.binaryAnalyzer.pos2BlockMap.get(jumpPos), visited); 365 | // } 366 | // } 367 | // 368 | // else if(block.jumpType == BasicBlock.FALL){ 369 | // int jumpPos = block.fallPos; 370 | // if(!visited.contains(jumpPos)) { 371 | // ArrayList newPath = (ArrayList) currentPath.clone(); 372 | // newPath.add(jumpPos); 373 | // findCallPath(newPath, this.binaryAnalyzer.pos2BlockMap.get(jumpPos), visited); 374 | // } 375 | // 376 | // } 377 | // 378 | // } 379 | 380 | public boolean detectReentrancy(){ 381 | //TODO: multiple CALL or SLOAD in one path 382 | //Currently, we can only detect one SLOAD, SSTORE, CALL in one path 383 | if(!this.binaryAnalyzer.allInstrs.contains("CALL")) 384 | return false; 385 | if(!this.binaryAnalyzer.allInstrs.contains("SLOAD")) 386 | return false; 387 | //Step1: travel all paths and select paths with "CALL" instr 388 | //Step2: obtain all path conditions on the selected paths 389 | //Step3: if a condition contains "SLOAD", then obtain its address. 390 | //Step4: detect whether the address is modified before the "CALL" instr.(SSTORE_PC && CALL_PC) 391 | 392 | // findCallPath(new ArrayList<>(), this.binaryAnalyzer.pos2BlockMap.get(0), new HashSet<>()); 393 | for(ArrayList path : this.binaryAnalyzer.allCallPath){ 394 | String address = ""; 395 | int callPC = -1; 396 | int sstorePC = -1; 397 | int sloadPC = -1; 398 | boolean gasLimited = false; 399 | boolean legalTransferAmount = true; 400 | ArrayList> legalRange = new ArrayList<>(); 401 | 402 | //get SLOAD address 403 | for(Integer blockID : path){ 404 | BasicBlock block = this.binaryAnalyzer.pos2BlockMap.get(blockID); 405 | legalRange.add(new Pair<>(block.startBlockPos, block.endBlockPos)); 406 | if(block.conditionalJumpExpression.length() > 1) { 407 | if(block.conditionalJumpExpression.contains("SLOAD")){ 408 | address = Utils.getSlotAddress(block.conditionalJumpExpression); 409 | for(Pair> instr : block.instrList){ 410 | if(instr.getSecond().getFirst().equals("SLOAD")) 411 | sloadPC = instr.getFirst(); 412 | } 413 | } 414 | } 415 | } 416 | 417 | //this path does not read from storage ==> this path does not have reentrancy bug 418 | if(sloadPC == -1) 419 | continue; 420 | 421 | for(int i = 0; i < this.binaryAnalyzer.stackEvents.size()-1; i++) { 422 | String[] eventLog = this.binaryAnalyzer.stackEvents.get(i).split(" ==> "); 423 | 424 | //get SSTORE PC; 425 | if(eventLog[0].equals("SSTORE")){ 426 | int pc = Integer.valueOf(eventLog[1]); 427 | 428 | //this SSTORE is in current range 429 | if(Utils.legalRange(pc, legalRange)){ 430 | String[] tmp = this.binaryAnalyzer.stackEvents.get(i-1).split(" ==> "); 431 | String top = tmp[2].split(" ")[0]; 432 | if(top.length() > 0){ 433 | top = top.replaceAll("_[0-9]+", ""); 434 | //SSTORE read the same address with SLOAD, if sstorePC < CallPC ==> do not have reentrancy 435 | if(top.length() > 0 && top.equals(address)){ 436 | sstorePC = Integer.valueOf(eventLog[1]); 437 | } 438 | } 439 | } 440 | } 441 | 442 | if(eventLog[0].equals("CALL")){ 443 | int pc = Integer.valueOf(eventLog[1]); 444 | 445 | //detect whether this CALL belongs to current path 446 | if(Utils.legalRange(pc, legalRange)){ 447 | String[] tmp = this.binaryAnalyzer.stackEvents.get(i-1).split(" ==> "); 448 | String top = tmp[2].split(" ")[0]; 449 | if(top.length() > 0){ 450 | //detect gas limitation, if CALL is created by send or transfer, then it will limit gas to 2300 451 | if(top.contains("2300_")) 452 | gasLimited = true; 453 | else if(Utils.getType(top) == Utils.DIGITAL){ 454 | Long limitNum = Long.valueOf(top.split("_")[0]); 455 | if(limitNum <= 2300) 456 | gasLimited = true; 457 | } 458 | 459 | else{ 460 | callPC = pc; 461 | gasLimited = false; //false is the default value 462 | } 463 | } 464 | 465 | String transfer_amount = tmp[2].split(" ")[2]; 466 | if(Utils.getType(transfer_amount) == Utils.DIGITAL){ 467 | Long amount = Long.valueOf(transfer_amount.split("_")[0]); 468 | if(amount == 0) 469 | legalTransferAmount = false; 470 | else 471 | legalTransferAmount = true; 472 | } 473 | else{ 474 | legalTransferAmount = true; 475 | } 476 | } 477 | } 478 | 479 | } 480 | 481 | 482 | if(!gasLimited && (sstorePC == -1 || sstorePC > callPC) && (callPC > sloadPC) && legalTransferAmount){ 483 | return true; 484 | } 485 | } 486 | 487 | return false; 488 | } 489 | 490 | 491 | public String printAllDetectResult(){ 492 | String res = ""; 493 | res += "Uncheck External Calls: " + this.hasUnchechedExternalCalls + "\n"; 494 | res += "Strict Balance Equality: " + this.hasStrictBalanceEquality + "\n"; 495 | res += "Transaction State Dependency: " + this.hasTransactionStateDependency + "\n"; 496 | res += "Block Info Dependency: " + this.hasBlockInfoDependency + "\n"; 497 | res += "Greedy Contract: " + this.hasGreedyContract + "\n"; 498 | res += "DoS Under External Influence: " + this.hasDoSUnderExternalInfluence + "\n"; 499 | res += "Nest Call: " + this.hasNestCall + "\n"; 500 | res += "Reentrancy: " + this.hasReentrancy + "\n"; 501 | res += "Code Coverage:" + this.binaryAnalyzer.codeCoverage + "\n"; 502 | res += "Miss recognized Jump: " + this.binaryAnalyzer.misRecognizedJump + "\n"; 503 | res += "Cyclomatic Complexity: " + this.binaryAnalyzer.cyclomatic_complexity + "\n"; 504 | res += "Number of Instructions: " + this.binaryAnalyzer.numInster + "\n"; 505 | return res; 506 | } 507 | } 508 | -------------------------------------------------------------------------------- /DefectChecker/src/EVMSimulator.java: -------------------------------------------------------------------------------- 1 | import sun.rmi.runtime.Log; 2 | 3 | import java.util.*; 4 | 5 | public class EVMSimulator { 6 | 7 | private static final int LOOP_LIMITED = 3; 8 | private HashMap edgeVisTimes = null; 9 | public TreeMap pos2BlockMap = null; 10 | public ArrayList stackEvents = new ArrayList<>(); 11 | public boolean versionGap = false; 12 | public boolean misRecognizedJump = false; 13 | 14 | public EVMSimulator(TreeMap pos2BlockMap){ 15 | this.pos2BlockMap = pos2BlockMap; 16 | this.edgeVisTimes = new HashMap<>(); 17 | BasicBlock start = pos2BlockMap.get(0); 18 | dfs_exe_block(start, (LinkedList) start.evm_stack.clone()); 19 | } 20 | 21 | private boolean flagVisEdge(int currentBlockID, int jumpPos){ 22 | String edgeVis = currentBlockID + "_" + jumpPos; 23 | int visTimes = 0; 24 | if(edgeVisTimes.containsKey(edgeVis)){ 25 | visTimes =edgeVisTimes.get(edgeVis); 26 | } 27 | 28 | if(visTimes == LOOP_LIMITED ) { 29 | return false; 30 | } 31 | 32 | visTimes += 1; 33 | edgeVisTimes.put(edgeVis, visTimes); 34 | return true; 35 | } 36 | 37 | private void dfs_exe_block(BasicBlock block, LinkedList father_evm_stack){ 38 | block.evm_stack = (LinkedList)father_evm_stack.clone(); 39 | for(Pair> instr : block.instrList){ 40 | exe_instr(block, instr, block.evm_stack); 41 | } 42 | 43 | if(block.jumpType == BasicBlock.CONDITIONAL){ 44 | int left_branch = block.conditionalJumpPos; 45 | if(left_branch == -1) 46 | return; 47 | if(flagVisEdge(block.startBlockPos, left_branch)) { 48 | dfs_exe_block(pos2BlockMap.get(left_branch), block.evm_stack); 49 | } 50 | 51 | int right_branch = block.fallPos; 52 | if(flagVisEdge(block.startBlockPos, right_branch)) { 53 | dfs_exe_block(pos2BlockMap.get(right_branch), block.evm_stack); 54 | } 55 | 56 | } 57 | 58 | else if(block.jumpType == BasicBlock.UNCONDITIONAL){ 59 | int jumpPos = block.unconditionalJumpPos; 60 | if(jumpPos == -1) 61 | return; 62 | if(flagVisEdge(block.startBlockPos, jumpPos)) { 63 | dfs_exe_block(pos2BlockMap.get(jumpPos), block.evm_stack); 64 | } 65 | } 66 | 67 | else if(block.jumpType == BasicBlock.FALL){ 68 | int jumpPos = block.fallPos; 69 | if(flagVisEdge(block.startBlockPos, jumpPos)) { 70 | dfs_exe_block(pos2BlockMap.get(jumpPos), block.evm_stack); 71 | } 72 | 73 | } 74 | 75 | else if(block.jumpType == BasicBlock.TERMINAL){ 76 | ; 77 | } 78 | 79 | } 80 | 81 | 82 | private String printStack(String instr, int current_PC, LinkedList evm_stack){ 83 | String res = ""; 84 | for(String tmp : evm_stack){ 85 | res += tmp + " "; 86 | } 87 | if(res.length() == 0) 88 | res = "NULL"; 89 | return instr + " ==> " + current_PC + " ==> " +res; 90 | } 91 | 92 | private void exe_instr(BasicBlock currentBlock, Pair> instr_pair, LinkedList evm_stack){ 93 | int currentBlockID = currentBlock.startBlockPos; 94 | String instr = instr_pair.getSecond().getFirst(); 95 | int current_PC = instr_pair.getFirst(); 96 | 97 | boolean legalInstr = true; 98 | //each instr is pushed into evm_stack with the format "instrName_currentPC" 99 | if(instr.equals("JUMP")){ 100 | if(evm_stack.size() >= 1) { 101 | String address = evm_stack.pop(); 102 | boolean legalJump = false; 103 | if(Utils.getType(address) == Utils.DIGITAL){ 104 | int jumpPos = Integer.valueOf(address.split("_")[0]); 105 | if(jumpPos == 0 || !this.pos2BlockMap.containsKey(jumpPos)){ 106 | this.pos2BlockMap.get(currentBlockID).unconditionalJumpPos = -1; 107 | legalJump = true; 108 | versionGap = true; 109 | } 110 | else if(this.pos2BlockMap.get(jumpPos).instrList.get(0).getSecond().getFirst().equals("JUMPDEST")) { 111 | this.pos2BlockMap.get(currentBlockID).unconditionalJumpPos = jumpPos; 112 | legalJump = true; 113 | } 114 | } 115 | if(!legalJump){ 116 | System.out.println("Cannot Recognize Jump Pos \"" + address + "\" on PC: " + current_PC); 117 | this.misRecognizedJump = true; 118 | } 119 | } 120 | else{ 121 | legalInstr = false; 122 | } 123 | } 124 | 125 | else if(instr.equals("JUMPI")){ 126 | if(evm_stack.size() >= 2){ 127 | String address = evm_stack.pop(); 128 | String condition = evm_stack.pop(); 129 | boolean legalJump = false; 130 | if(Utils.getType(address) == Utils.DIGITAL){ 131 | int jumpPos = Integer.valueOf(address.split("_")[0]); 132 | if(jumpPos == 0 || !this.pos2BlockMap.containsKey(jumpPos)){ 133 | this.pos2BlockMap.get(currentBlockID).conditionalJumpPos = -1; 134 | this.pos2BlockMap.get(currentBlockID).conditionalJumpExpression = condition; 135 | legalJump = true; 136 | versionGap = true; 137 | 138 | } 139 | 140 | else if(this.pos2BlockMap.get(jumpPos).instrList.get(0).getSecond().getFirst().equals("JUMPDEST")){ 141 | this.pos2BlockMap.get(currentBlockID).conditionalJumpPos = jumpPos; 142 | this.pos2BlockMap.get(currentBlockID).conditionalJumpExpression = condition; 143 | legalJump = true; 144 | } 145 | 146 | } 147 | if(!legalJump){ 148 | System.out.println("Error JUMPI on: " + current_PC); 149 | this.misRecognizedJump = true; 150 | } 151 | } 152 | else{ 153 | legalInstr = false; 154 | } 155 | } 156 | 157 | else if(instr.equals("STOP")){ 158 | ; 159 | } 160 | 161 | else if(instr.equals("ADD")){ 162 | if(evm_stack.size() >= 2) { 163 | String first = evm_stack.pop(); 164 | String second = evm_stack.pop(); 165 | if(Utils.getType(first) == Utils.DIGITAL && Utils.getType(second) == Utils.DIGITAL){ 166 | Long res = Long.valueOf(first.split("_")[0]) + Long.valueOf(second.split("_")[0]); 167 | evm_stack.push(res + "_" + current_PC); 168 | } 169 | else{ 170 | String res = "ADD_" + current_PC + "(" + first + "," + second + ")"; 171 | evm_stack.push(res); 172 | } 173 | } 174 | else{ 175 | legalInstr = false; 176 | } 177 | } 178 | 179 | else if(instr.equals("MUL")){ 180 | if(evm_stack.size() >= 2) { 181 | String first = evm_stack.pop(); 182 | String second = evm_stack.pop(); 183 | if(Utils.getType(first) == Utils.DIGITAL && Utils.getType(second) == Utils.DIGITAL){ 184 | Long res = Long.valueOf(first.split("_")[0]) * Long.valueOf(second.split("_")[0]); 185 | evm_stack.push(res + "_" + current_PC); 186 | } 187 | else{ 188 | String res = "MUL_" + current_PC + "(" + first + "," + second + ")"; 189 | evm_stack.push(res); 190 | } 191 | } 192 | else{ 193 | legalInstr = false; 194 | } 195 | } 196 | 197 | else if(instr.equals("SUB")){ 198 | if(evm_stack.size() >= 2) { 199 | String first = evm_stack.pop(); 200 | String second = evm_stack.pop(); 201 | if(Utils.getType(first) == Utils.DIGITAL && Utils.getType(second) == Utils.DIGITAL){ 202 | Long res = Long.valueOf(first.split("_")[0]) - Long.valueOf(second.split("_")[0]); 203 | evm_stack.push(res + "_" + current_PC); 204 | } 205 | else{ 206 | String res = "SUB_" + current_PC + "(" + first + "," + second + ")"; 207 | evm_stack.push(res); 208 | } 209 | } 210 | else{ 211 | legalInstr = false; 212 | } 213 | } 214 | 215 | else if(instr.equals("DIV")){ 216 | if(evm_stack.size() >= 2) { 217 | String first = evm_stack.pop(); 218 | String second = evm_stack.pop(); 219 | if(Utils.getType(first) == Utils.DIGITAL && Utils.getType(second) == Utils.DIGITAL){ 220 | Long res = -1L; 221 | if(Long.valueOf(second.split("_")[0]) == 0) 222 | res = 0L; 223 | else{ 224 | res = Long.valueOf(first.split("_")[0]) / Long.valueOf(second.split("_")[0]); 225 | } 226 | evm_stack.push(res + "_" + current_PC); 227 | } 228 | else{ 229 | String res = "DIV_" + current_PC + "(" + first + "," + second + ")"; 230 | evm_stack.push(res); 231 | } 232 | } 233 | else{ 234 | legalInstr = false; 235 | } 236 | } 237 | 238 | else if(instr.equals("SDIV")){ 239 | if(evm_stack.size() >= 2) { 240 | String first = evm_stack.pop(); 241 | String second = evm_stack.pop(); 242 | if(Utils.getType(first) == Utils.DIGITAL && Utils.getType(second) == Utils.DIGITAL){ 243 | Long res = -1L; 244 | if(Long.valueOf(second.split("_")[0]) == 0) 245 | res = 0L; 246 | else{ 247 | int tmp = 1; 248 | if(Long.valueOf(first.split("_")[0]) / Long.valueOf(second.split("_")[0]) < 0) 249 | tmp = -1; 250 | res = tmp * Math.abs(Long.valueOf(first.split("_")[0]) / Long.valueOf(second.split("_")[0])); 251 | } 252 | evm_stack.push(res + "_" + current_PC); 253 | } 254 | // else if(second.contains("-ffffffffffffffffffff")){ 255 | // evm_stack.push("-ffffffffffffffffffff" + "_" + current_PC); 256 | // } 257 | else{ 258 | String res = "SDIV_" + current_PC + "(" + first + "," + second + ")"; 259 | evm_stack.push(res); 260 | } 261 | } 262 | else{ 263 | legalInstr = false; 264 | } 265 | } 266 | 267 | else if(instr.equals("MOD")){ 268 | if(evm_stack.size() >= 2) { 269 | String first = evm_stack.pop(); 270 | String second = evm_stack.pop(); 271 | if(Utils.getType(first) == Utils.DIGITAL && Utils.getType(second) == Utils.DIGITAL){ 272 | Long res = -1L; 273 | if(Integer.valueOf(second.split("_")[0]) == 0) 274 | res = 0L; 275 | else{ 276 | res = Long.valueOf(first.split("_")[0]) % Long.valueOf(second.split("_")[0]); 277 | } 278 | evm_stack.push(res + "_" + current_PC); 279 | } 280 | else{ 281 | String res = "MOD_" + current_PC + "(" + first + "," + second + ")"; 282 | evm_stack.push(res); 283 | } 284 | } 285 | else{ 286 | legalInstr = false; 287 | } 288 | } 289 | 290 | else if(instr.equals("SMOD")){ 291 | if(evm_stack.size() >= 2) { 292 | String first = evm_stack.pop(); 293 | String second = evm_stack.pop(); 294 | if(Utils.getType(first) == Utils.DIGITAL && Utils.getType(second) == Utils.DIGITAL){ 295 | Long res = -1L; 296 | if(Integer.valueOf(second.split("_")[0]) == 0) 297 | res = 0L; 298 | else{ 299 | res = Long.valueOf(first.split("_")[0]) % Long.valueOf(second.split("_")[0]); 300 | if(res * Integer.valueOf(first.split("_")[0]) < 0) 301 | res *= -1; 302 | } 303 | evm_stack.push(res + "_" + current_PC); 304 | } 305 | else{ 306 | String res = "SMOD_" + current_PC + "(" + first + "," + second + ")"; 307 | evm_stack.push(res); 308 | } 309 | } 310 | else{ 311 | legalInstr = false; 312 | } 313 | } 314 | 315 | else if(instr.equals("ADDMOD")){ 316 | if(evm_stack.size() >= 3) { 317 | String first = evm_stack.pop(); 318 | String second = evm_stack.pop(); 319 | String third = evm_stack.pop(); 320 | if(Utils.getType(first) == Utils.DIGITAL && Utils.getType(second) == Utils.DIGITAL && Utils.getType(third) == Utils.DIGITAL){ 321 | Long res = -1L; 322 | if(Integer.valueOf(third.split("_")[0]) == 0) 323 | res = 0L; 324 | else{ 325 | res = (Long.valueOf(first.split("_")[0]) + Long.valueOf(second.split("_")[0])) 326 | % Long.valueOf(third.split("_")[0]); 327 | } 328 | evm_stack.push(res + "_" + current_PC); 329 | } 330 | else{ 331 | String res = "ADDMOD_" + current_PC + "(" + first + "," + second + ")"; 332 | evm_stack.push(res); 333 | } 334 | } 335 | else{ 336 | legalInstr = false; 337 | } 338 | } 339 | 340 | else if(instr.equals("MULMOD")){ 341 | if(evm_stack.size() >= 3) { 342 | String first = evm_stack.pop(); 343 | String second = evm_stack.pop(); 344 | String third = evm_stack.pop(); 345 | if(Utils.getType(first) == Utils.DIGITAL && Utils.getType(second) == Utils.DIGITAL && Utils.getType(third) == Utils.DIGITAL){ 346 | 347 | Long res = (Long.valueOf(first.split("_")[0]) * Long.valueOf(second.split("_")[0])) 348 | % Long.valueOf(third.split("_")[0]); 349 | 350 | evm_stack.push(res + "_" + current_PC); 351 | } 352 | else{ 353 | String res = "MULMOD_" + current_PC + "(" + first + "," + second + ")"; 354 | evm_stack.push(res); 355 | } 356 | } 357 | else{ 358 | legalInstr = false; 359 | } 360 | } 361 | 362 | else if(instr.equals("EXP")){ 363 | if(evm_stack.size() >= 2) { 364 | String first = evm_stack.pop(); 365 | String second = evm_stack.pop(); 366 | if(Utils.getType(first) == Utils.DIGITAL && Utils.getType(second) == Utils.DIGITAL){ 367 | Long res = new Double(Math.pow(Long.valueOf(first.split("_")[0]), 368 | Long.valueOf(second.split("_")[0]))).longValue(); 369 | evm_stack.push( res+ "_" + current_PC); 370 | } 371 | else{ 372 | String res = "EXP_" + current_PC + "(" + first + "," + second + ")"; 373 | evm_stack.push(res); 374 | } 375 | } 376 | else{ 377 | legalInstr = false; 378 | } 379 | } 380 | 381 | else if(instr.equals("SIGNEXTEND")){ 382 | if(evm_stack.size() >= 2) { 383 | String first = evm_stack.pop(); 384 | String second = evm_stack.pop(); 385 | if(Utils.getType(first) == Utils.DIGITAL && Utils.getType(second) == Utils.DIGITAL){ 386 | Long f = Long.valueOf(first.split("_")[0]); 387 | Long s = Long.valueOf(first.split("_")[0]); 388 | Long res = 0L; 389 | if(f >= 32 || f < 0) 390 | res = s; 391 | else{ 392 | Long tmp = 8*f+7; 393 | if((s & (1 << tmp)) == 1){ 394 | res = s | (new Double(Math.pow(2,256) - (1 << tmp)).intValue()); 395 | } 396 | else{ 397 | res = s & ((1 << tmp) - 1); 398 | } 399 | } 400 | evm_stack.push( res+ "_" + current_PC); 401 | } 402 | else{ 403 | String res = "SIGNEXTEND_" + current_PC + "(" + first + "," + second + ")"; 404 | evm_stack.push(res); 405 | } 406 | } 407 | else{ 408 | legalInstr = false; 409 | } 410 | } 411 | 412 | else if(instr.equals("LT") || instr.equals("SLT")){ 413 | if(evm_stack.size() >= 2) { 414 | String first = evm_stack.pop(); 415 | String second = evm_stack.pop(); 416 | if(Utils.getType(first) == Utils.DIGITAL && Utils.getType(second) == Utils.DIGITAL){ 417 | if(Long.valueOf(first.split("_")[0]) < Long.valueOf(second.split("_")[0])){ 418 | evm_stack.push( 1+ "_" + current_PC); 419 | } 420 | else{ 421 | evm_stack.push( 0+ "_" + current_PC); 422 | } 423 | } 424 | else{ 425 | String res = "LT_" + current_PC + "(" + first + "," + second + ")"; 426 | evm_stack.push(res); 427 | } 428 | } 429 | else{ 430 | legalInstr = false; 431 | } 432 | } 433 | 434 | else if(instr.equals("GT") || instr.equals("SGT")){ 435 | if(evm_stack.size() >= 2) { 436 | String first = evm_stack.pop(); 437 | String second = evm_stack.pop(); 438 | if(Utils.getType(first) == Utils.DIGITAL && Utils.getType(second) == Utils.DIGITAL){ 439 | if(Long.valueOf(first.split("_")[0]) > Long.valueOf(second.split("_")[0])){ 440 | evm_stack.push( 1+ "_" + current_PC); 441 | } 442 | else{ 443 | evm_stack.push( 0+ "_" + current_PC); 444 | } 445 | } 446 | else{ 447 | String res = "GT_" + current_PC + "(" + first + "," + second + ")"; 448 | evm_stack.push(res); 449 | } 450 | } 451 | else{ 452 | legalInstr = false; 453 | } 454 | } 455 | 456 | else if(instr.equals("EQ")){ 457 | if(evm_stack.size() >= 2) { 458 | String first = evm_stack.pop(); 459 | String second = evm_stack.pop(); 460 | if(Utils.getType(first) == Utils.DIGITAL && Utils.getType(second) == Utils.DIGITAL){ 461 | if(Long.valueOf(first.split("_")[0]).equals(Long.valueOf(second.split("_")[0]))){ 462 | evm_stack.push( 1+ "_" + current_PC); 463 | } 464 | else{ 465 | evm_stack.push( 0+ "_" + current_PC); 466 | } 467 | } 468 | else{ 469 | if(first.replaceAll("_[0-9]+?", "").equals(second.replaceAll("_[0-9]+?", ""))){ 470 | evm_stack.push( 1+ "_" + current_PC); 471 | } 472 | else{ 473 | String res = "EQ_" + current_PC + "(" + first + "," + second + ")"; 474 | evm_stack.push(res); 475 | } 476 | } 477 | } 478 | else{ 479 | legalInstr = false; 480 | } 481 | } 482 | 483 | else if(instr.equals("ISZERO")){ 484 | if(evm_stack.size() >= 1) { 485 | String first = evm_stack.pop(); 486 | if(Utils.getType(first) == Utils.DIGITAL){ 487 | if(Long.valueOf(first.split("_")[0]) == 0){ 488 | evm_stack.push( 1+ "_" + current_PC); 489 | } 490 | else{ 491 | evm_stack.push( 0+ "_" + current_PC); 492 | } 493 | } 494 | else{ 495 | String res = "ISZERO_" + current_PC + "(" + first + ")"; 496 | evm_stack.push(res); 497 | } 498 | } 499 | else{ 500 | legalInstr = false; 501 | } 502 | } 503 | 504 | else if(instr.equals("AND")){ 505 | if(evm_stack.size() >= 2) { 506 | String first = evm_stack.pop(); 507 | String second = evm_stack.pop(); 508 | if(Utils.getType(first) == Utils.DIGITAL && Utils.getType(second) == Utils.DIGITAL){ 509 | Long res = Long.valueOf(first.split("_")[0]) & Long.valueOf(second.split("_")[0]); 510 | evm_stack.push(res + "_" + current_PC); 511 | } 512 | else{ 513 | String res = "AND_" + current_PC + "(" + first + "," + second + ")"; 514 | evm_stack.push(res); 515 | } 516 | } 517 | else{ 518 | legalInstr = false; 519 | } 520 | } 521 | 522 | else if(instr.equals("OR")){ 523 | if(evm_stack.size() >= 2) { 524 | String first = evm_stack.pop(); 525 | String second = evm_stack.pop(); 526 | if(Utils.getType(first) == Utils.DIGITAL && Utils.getType(second) == Utils.DIGITAL){ 527 | Long res = Long.valueOf(first.split("_")[0]) | Long.valueOf(second.split("_")[0]); 528 | evm_stack.push(res + "_" + current_PC); 529 | } 530 | else{ 531 | String res = "OR_" + current_PC + "(" + first + "," + second + ")"; 532 | evm_stack.push(res); 533 | } 534 | } 535 | else{ 536 | legalInstr = false; 537 | } 538 | } 539 | 540 | else if(instr.equals("XOR")){ 541 | if(evm_stack.size() >= 2) { 542 | String first = evm_stack.pop(); 543 | String second = evm_stack.pop(); 544 | if(Utils.getType(first) == Utils.DIGITAL && Utils.getType(second) == Utils.DIGITAL){ 545 | Long res = Long.valueOf(first.split("_")[0]) ^ Long.valueOf(second.split("_")[0]); 546 | evm_stack.push(res + "_" + current_PC); 547 | } 548 | else{ 549 | String res = "XOR_" + current_PC + "(" + first + "," + second + ")"; 550 | evm_stack.push(res); 551 | } 552 | } 553 | else{ 554 | legalInstr = false; 555 | } 556 | } 557 | 558 | else if(instr.equals("NOT")){ 559 | if(evm_stack.size() >= 1) { 560 | String first = evm_stack.pop(); 561 | if(Utils.getType(first) == Utils.DIGITAL){ 562 | Long res = ~Long.valueOf(first.split("_")[0]); 563 | evm_stack.push(res + "_" + current_PC); 564 | } 565 | else{ 566 | String res = "NOT_" + current_PC + "(" + first + ")"; 567 | evm_stack.push(res); 568 | } 569 | } 570 | else{ 571 | legalInstr = false; 572 | } 573 | } 574 | 575 | else if(instr.equals("BYTE")){ 576 | if(evm_stack.size() >= 2) { 577 | String first = evm_stack.pop(); 578 | String second = evm_stack.pop(); 579 | if(Utils.getType(first) == Utils.DIGITAL && Utils.getType(second) == Utils.DIGITAL){ 580 | Long f = Long.valueOf(first.split("_")[0]); 581 | Long s = Long.valueOf(second.split("_")[0]); 582 | Long byte_idx = 32 - f -1; 583 | Long res = -1L; 584 | if(f >= 32 || f < 0){ 585 | res = 0L; 586 | } 587 | else{ 588 | res = s & (255 << (8 * byte_idx)); 589 | res = res >> (8 * byte_idx); 590 | } 591 | evm_stack.push(res + "_" + current_PC); 592 | } 593 | else{ 594 | String res = "BYTE_" + current_PC + "(" + first + "," + second + ")"; 595 | evm_stack.push(res); 596 | } 597 | } 598 | else{ 599 | legalInstr = false; 600 | } 601 | } 602 | 603 | else if(instr.equals("SHA3")){ 604 | if(evm_stack.size() >= 2) { 605 | String top1 = evm_stack.pop(); 606 | String top2 = evm_stack.pop(); 607 | String result = "SHA3_" + current_PC + "(" + top1 + "," + top2 + ")"; 608 | evm_stack.push(result); 609 | } 610 | else{ 611 | legalInstr = false; 612 | } 613 | } 614 | 615 | else if(instr.equals("ADDRESS")){ 616 | String result = "ADDRESS_" + current_PC; 617 | evm_stack.push(result); 618 | } 619 | 620 | else if(instr.equals("BALANCE")){ 621 | if(evm_stack.size() >= 1) { 622 | String top1 = evm_stack.pop(); 623 | String result = "BALANCE_" + current_PC + "(" + top1 + ")"; 624 | evm_stack.push(result); 625 | } 626 | else{ 627 | legalInstr = false; 628 | } 629 | } 630 | 631 | else if(instr.equals("ORIGIN")){ 632 | String result = "ORIGIN_" + current_PC; 633 | evm_stack.push(result); 634 | } 635 | 636 | else if(instr.equals("CALLER")){ 637 | String result = "CALLER_" + current_PC; 638 | evm_stack.push(result); 639 | } 640 | 641 | else if(instr.equals("CALLVALUE")){ 642 | String result = "CALLVALUE_" + current_PC; 643 | evm_stack.push(result); 644 | } 645 | 646 | else if(instr.equals("CALLDATALOAD")){ 647 | if(evm_stack.size() >= 1) { 648 | String top1 = evm_stack.pop(); 649 | String result = "CALLDATALOAD_" + current_PC + "(" + top1 + ")"; 650 | evm_stack.push(result); 651 | } 652 | else{ 653 | legalInstr = false; 654 | } 655 | } 656 | 657 | else if(instr.equals("CALLDATASIZE")){ 658 | String result = "CALLDATASIZE_" + current_PC; 659 | evm_stack.push(result); 660 | } 661 | 662 | 663 | else if(instr.equals("CALLDATACOPY")){ 664 | if(evm_stack.size() >= 3) { 665 | String top1 = evm_stack.pop(); 666 | String top2 = evm_stack.pop(); 667 | String top3 = evm_stack.pop(); 668 | } 669 | else{ 670 | legalInstr = false; 671 | } 672 | } 673 | 674 | else if(instr.equals("CODESIZE")){ 675 | String result = "CODESIZE_" + current_PC; 676 | evm_stack.push(result); 677 | } 678 | 679 | else if(instr.equals("CODECOPY")){ 680 | if(evm_stack.size() >= 3) { 681 | String top1 = evm_stack.pop(); 682 | String top2 = evm_stack.pop(); 683 | String top3 = evm_stack.pop(); 684 | } 685 | else{ 686 | legalInstr = false; 687 | } 688 | } 689 | 690 | else if(instr.equals("GASPRICE")){ 691 | String result = "GASPRICE_" + current_PC; 692 | evm_stack.push(result); 693 | } 694 | 695 | 696 | else if(instr.equals("EXTCODESIZE")){ 697 | if(evm_stack.size() >= 1) { 698 | String top1 = evm_stack.pop(); 699 | String result = "EXTCODESIZE_" + current_PC + "(" + top1 + ")"; 700 | evm_stack.push(result); 701 | } 702 | else{ 703 | legalInstr = false; 704 | } 705 | } 706 | 707 | else if(instr.equals("EXTCODECOPY")){ 708 | if(evm_stack.size() >= 4) { 709 | String top1 = evm_stack.pop(); 710 | String top2 = evm_stack.pop(); 711 | String top3 = evm_stack.pop(); 712 | String top4 = evm_stack.pop(); 713 | } 714 | else{ 715 | legalInstr = false; 716 | } 717 | } 718 | 719 | else if(instr.equals("RETURNDATASIZE")){ 720 | String result = "RETURNDATASIZE_" + current_PC; 721 | evm_stack.push(result); 722 | } 723 | 724 | else if(instr.equals("RETURNDATACOPY")){ 725 | if(evm_stack.size() >= 3) { 726 | String top1 = evm_stack.pop(); 727 | String top2 = evm_stack.pop(); 728 | String top3 = evm_stack.pop(); 729 | } 730 | else{ 731 | legalInstr = false; 732 | } 733 | } 734 | 735 | else if(instr.equals("BLOCKHASH")){ 736 | if(evm_stack.size() >= 1) { 737 | String top1 = evm_stack.pop(); 738 | String result = "BLOCKHASH_" + current_PC + "(" + top1 + ")"; 739 | evm_stack.push(result); 740 | } 741 | else{ 742 | legalInstr = false; 743 | } 744 | } 745 | 746 | else if(instr.equals("COINBASE")){ 747 | String result = "COINBASE_" + current_PC; 748 | evm_stack.push(result); 749 | } 750 | 751 | else if(instr.equals("TIMESTAMP")){ 752 | String result = "TIMESTAMP_" + current_PC; 753 | evm_stack.push(result); 754 | } 755 | 756 | else if(instr.equals("NUMBER")){ 757 | String result = "NUMBER_" + current_PC; 758 | evm_stack.push(result); 759 | } 760 | 761 | else if(instr.equals("DIFFICULTY")){ 762 | String result = "DIFFICULTY_" + current_PC; 763 | evm_stack.push(result); 764 | } 765 | 766 | else if(instr.equals("GASLIMIT")){ 767 | String result = "GASLIMIT_" + current_PC; 768 | evm_stack.push(result); 769 | } 770 | 771 | else if(instr.equals("POP")){ 772 | if(evm_stack.size() >= 1) { 773 | evm_stack.pop(); 774 | } 775 | else{ 776 | legalInstr = false; 777 | } 778 | } 779 | 780 | else if(instr.equals("MLOAD")){ 781 | if(evm_stack.size() >= 1) { 782 | String address = evm_stack.pop(); 783 | String result = "MLOAD_" + current_PC + "(" + address + ")"; 784 | evm_stack.push(result); 785 | } 786 | else{ 787 | legalInstr = false; 788 | } 789 | } 790 | 791 | else if(instr.equals("MSTORE") || instr.equals("MSTORE8")){ 792 | if(evm_stack.size() >= 2) { 793 | String address = evm_stack.pop(); 794 | String value = evm_stack.pop(); 795 | } 796 | else{ 797 | legalInstr = false; 798 | } 799 | } 800 | 801 | else if(instr.equals("SSTORE")){ 802 | if(evm_stack.size() >= 2) { 803 | String address = evm_stack.pop(); 804 | String value = evm_stack.pop(); 805 | } 806 | else{ 807 | legalInstr = false; 808 | } 809 | } 810 | 811 | else if(instr.equals("SLOAD")){ 812 | if(evm_stack.size() >= 1) { 813 | String top1 = evm_stack.pop(); 814 | String result = "SLOAD_" + current_PC + "(" + top1 + ")"; 815 | evm_stack.push(result); 816 | } 817 | else{ 818 | legalInstr = false; 819 | } 820 | } 821 | 822 | 823 | else if(instr.equals("PC")){ 824 | String result = "PC_" + current_PC; 825 | evm_stack.push(result); 826 | } 827 | 828 | else if(instr.equals("MSIZE")){ 829 | String result = "MSIZE_" + current_PC; 830 | evm_stack.push(result); 831 | } 832 | 833 | else if(instr.equals("GAS")){ 834 | String result = "GAS_" + current_PC; 835 | evm_stack.push(result); 836 | } 837 | 838 | else if(instr.equals("JUMPDEST")){ 839 | ; 840 | } 841 | 842 | else if(instr.startsWith("PUSH")){ 843 | String pushedValue = instr_pair.getSecond().getSecond(); 844 | if(pushedValue.startsWith("0")) 845 | pushedValue = pushedValue.replaceFirst("0+", ""); 846 | if(pushedValue.length() == 0) 847 | pushedValue = "0"; 848 | if(pushedValue.length() <= 10) { 849 | Long pushvalue = Utils.Hex2Long(pushedValue); 850 | evm_stack.push(pushvalue + "_" + current_PC); 851 | } 852 | else{ 853 | evm_stack.push(instr + "_" + String.valueOf(current_PC)); 854 | } 855 | } 856 | 857 | else if(instr.startsWith("DUP")){ 858 | String dp = instr.replace("DUP", ""); 859 | int dupPos = Integer.valueOf(dp); 860 | if(evm_stack.size() >= dupPos) { 861 | ArrayList tmp = new ArrayList<>(); 862 | for(int i = 0;i < dupPos;i++){ 863 | tmp.add(evm_stack.pop()); 864 | } 865 | String dupValue = tmp.get(dupPos-1); 866 | for(int i = dupPos-1; i>=0; i--) 867 | evm_stack.push(tmp.get(i)); 868 | evm_stack.push(String.valueOf(dupValue)); 869 | } 870 | else{ 871 | legalInstr = false; 872 | } 873 | } 874 | 875 | else if(instr.startsWith("SWAP")){ 876 | String sp = instr.replace("SWAP", ""); 877 | int swapPos = Integer.valueOf(sp); 878 | if(evm_stack.size() > swapPos) { 879 | ArrayList tmp = new ArrayList<>(); 880 | for(int i = 0;i < swapPos+1;i++){ 881 | tmp.add(evm_stack.pop()); 882 | } 883 | evm_stack.push(tmp.get(0)); 884 | for(int i = tmp.size()-2; i > 0; i--) 885 | evm_stack.push(tmp.get(i)); 886 | evm_stack.push(tmp.get(tmp.size()-1)); 887 | } 888 | else{ 889 | legalInstr = false; 890 | } 891 | } 892 | 893 | else if(instr.startsWith("LOG")){ 894 | String lp = instr.replace("LOG", ""); 895 | int LogPos = Integer.valueOf(lp); 896 | if(evm_stack.size() >= LogPos+2) { 897 | for(int i = 0; i < LogPos+2; i++) 898 | evm_stack.pop(); 899 | } 900 | else{ 901 | legalInstr = false; 902 | } 903 | 904 | } 905 | 906 | else if(instr.equals("CREATE")){ 907 | if(evm_stack.size() >= 3) { 908 | String top1 = evm_stack.pop(); 909 | String top2 = evm_stack.pop(); 910 | String top3 = evm_stack.pop(); 911 | String result = "CREATE_" + current_PC; 912 | evm_stack.push(result); 913 | } 914 | else{ 915 | legalInstr = false; 916 | } 917 | } 918 | 919 | 920 | else if(instr.equals("CALL")){ 921 | if(evm_stack.size() >= 7) { 922 | String outgas = evm_stack.pop(); 923 | String recipient = evm_stack.pop(); 924 | String transfer_amount = evm_stack.pop(); 925 | String start_data_input = evm_stack.pop(); 926 | String size_data_input = evm_stack.pop(); 927 | String start_data_output = evm_stack.pop(); 928 | String size_data_ouput = evm_stack.pop(); 929 | String result = "CALL_" + current_PC; 930 | evm_stack.push(result); 931 | currentBlock.moneyCall = true; 932 | if(Utils.getType(transfer_amount) == Utils.DIGITAL){ 933 | Long amount = Long.valueOf(transfer_amount.split("_")[0]); 934 | if(amount == 0) 935 | currentBlock.moneyCall = false; 936 | } 937 | } 938 | else{ 939 | legalInstr = false; 940 | } 941 | } 942 | 943 | else if(instr.equals("CALLCODE")){ 944 | if(evm_stack.size() >= 7) { 945 | for(int i = 0;i < 7;i++) 946 | evm_stack.pop(); 947 | String result = "CALLCODE_" + current_PC; 948 | evm_stack.push(result); 949 | } 950 | else{ 951 | legalInstr = false; 952 | } 953 | } 954 | 955 | else if(instr.equals("RETURN") || instr.equals("REVERT")){ 956 | if(evm_stack.size() >= 2) { 957 | evm_stack.pop(); 958 | evm_stack.pop(); 959 | } 960 | else{ 961 | legalInstr = false; 962 | } 963 | } 964 | 965 | else if(instr.equals("DELEGATECALL")){ 966 | if(evm_stack.size() >= 6) { 967 | for(int i = 0;i < 6;i++) 968 | evm_stack.pop(); 969 | String result = "DELEGATECALL_" + current_PC; 970 | evm_stack.push(result); 971 | } 972 | else{ 973 | legalInstr = false; 974 | } 975 | } 976 | 977 | else if(instr.equals("STATICCALL")){ 978 | if(evm_stack.size() >= 6) { 979 | for(int i = 0;i < 6;i++) 980 | evm_stack.pop(); 981 | String result = "STATICCALL_" + current_PC; 982 | evm_stack.push(result); 983 | } 984 | else{ 985 | legalInstr = false; 986 | } 987 | } 988 | 989 | else if(instr.equals("SELFDESTRUCT") || instr.equals("REVERT")){ 990 | if(evm_stack.size() >= 1) { 991 | evm_stack.pop(); 992 | return; 993 | } 994 | else{ 995 | legalInstr = false; 996 | } 997 | } 998 | 999 | else if(instr.equals("INVALID") || instr.equals("ASSERTFAIL")){ 1000 | ; 1001 | } 1002 | 1003 | else{ 1004 | 1005 | System.out.println("Cannot recognize instr: " + instr); 1006 | } 1007 | 1008 | if(!legalInstr){ 1009 | System.out.println("Error with instr: " + instr + " - " + String.valueOf(current_PC)); 1010 | } 1011 | stackEvents.add( printStack(instr, current_PC, evm_stack)); 1012 | // System.out.println(printStack(instr, current_PC, evm_stack)); 1013 | } 1014 | 1015 | } 1016 | -------------------------------------------------------------------------------- /DefectChecker/src/Main.java: -------------------------------------------------------------------------------- 1 | import java.io.*; 2 | import java.util.ArrayList; 3 | import java.util.HashMap; 4 | import java.util.HashSet; 5 | 6 | public class Main { 7 | 8 | public static DefectChecker parserFromBytecode(String bytecode){ 9 | if(bytecode.length() < 1) 10 | return null; 11 | bytecode = bytecode.replaceAll("a165627a7a72305820\\S{64}0029$", ""); //remove swarm hash 12 | //we only need runtime bytecode, remove creation bytecode 13 | if(bytecode.contains("f30060806040")){ 14 | bytecode = bytecode.substring(bytecode.indexOf("f30060806040")+4); 15 | } 16 | 17 | BinaryAnalyzer binaryAnalyzer = new BinaryAnalyzer(bytecode); 18 | if(binaryAnalyzer.legalContract){ 19 | try{ 20 | DefectChecker defectChecker = new DefectChecker(binaryAnalyzer); 21 | defectChecker.detectAllSmells(); 22 | return defectChecker; 23 | }catch (Exception e){ 24 | e.printStackTrace(); 25 | return null; 26 | } 27 | 28 | 29 | } 30 | return null; 31 | } 32 | 33 | 34 | public static void parserFromSourceCodeFile(String filePath, String mainContracts){ 35 | String binary = Utils.runCMDWithTimeout(new String[]{"solc-0.4.25", "--bin-runtime", filePath}); 36 | if(binary == null || binary.length() < 1) { 37 | System.out.println("Compile Error: " + filePath); 38 | } 39 | 40 | String[] tmp = binary.split("\n"); 41 | boolean hasUnchechedExternalCalls = false; 42 | boolean hasStrictBalanceEquality = false; 43 | boolean hasTransactionStateDependency = false; 44 | boolean hasBlockInfoDependency = false; 45 | boolean hasDoSUnderExternalInfluence = false; 46 | boolean hasNestCall = false; 47 | boolean hasReentrancy = false; 48 | boolean hasGreedyContract = false; 49 | StringBuilder sb = new StringBuilder(); 50 | for(int i = 0;i < tmp.length-1;i++){ 51 | if(tmp[i].startsWith("Binary")){ 52 | String address = tmp[i-1].replaceAll("=", "").replaceAll(" ", "").replace("\n", ""); 53 | String bytecode = tmp[i+1]; 54 | if(!address.contains(mainContracts)) 55 | continue; 56 | System.out.println(address); 57 | DefectChecker defectChecker = parserFromBytecode(bytecode); 58 | if(defectChecker != null){ 59 | hasUnchechedExternalCalls |= defectChecker.hasUnchechedExternalCalls; 60 | hasStrictBalanceEquality |= defectChecker.hasStrictBalanceEquality; 61 | hasTransactionStateDependency |= defectChecker.hasTransactionStateDependency; 62 | hasBlockInfoDependency |= defectChecker.hasBlockInfoDependency; 63 | hasDoSUnderExternalInfluence |= defectChecker.hasDoSUnderExternalInfluence; 64 | hasNestCall |= defectChecker.hasNestCall; 65 | hasReentrancy |= defectChecker.hasReentrancy; 66 | hasGreedyContract |= defectChecker.hasGreedyContract; 67 | sb.append("Uncheck External Calls: " + hasUnchechedExternalCalls + "\n"); 68 | sb.append("Strict Balance Equality: " + hasStrictBalanceEquality + "\n"); 69 | sb.append("Transaction State Dependency: " + hasTransactionStateDependency + "\n"); 70 | sb.append("Block Info Dependency: " + hasBlockInfoDependency + "\n"); 71 | sb.append("Greedy Contract: " + hasGreedyContract + "\n"); 72 | sb.append("DoS Under External Influence: " + hasDoSUnderExternalInfluence + "\n"); 73 | sb.append("Nest Call: " + hasNestCall + "\n"); 74 | sb.append("Reentrancy: " + hasReentrancy + "\n"); 75 | System.out.println("Uncheck External Calls: " + hasUnchechedExternalCalls); 76 | System.out.println("Strict Balance Equality: " + hasStrictBalanceEquality); 77 | System.out.println("Transaction State Dependency: " + hasTransactionStateDependency); 78 | System.out.println("Block Info Dependency: " + hasBlockInfoDependency); 79 | System.out.println("Greedy Contract: " + hasGreedyContract); 80 | System.out.println("DoS Under External Influence: " + hasDoSUnderExternalInfluence); 81 | System.out.println("Nest Call: " + hasNestCall); 82 | System.out.println("Reentrancy: " + hasReentrancy); 83 | } 84 | 85 | } 86 | } 87 | 88 | 89 | 90 | } 91 | 92 | 93 | public static void main(String[] args) throws Exception{ 94 | long startTime = System.currentTimeMillis(); 95 | /*****Detect From Bytecode*****/ 96 | String bytecode = "60806040526004361061004c576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff1680630103c92b146100515780630fdb1c10146100a8575b600080fd5b34801561005d57600080fd5b50610092600480360381019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506100bf565b6040518082815260200191505060405180910390f35b3480156100b457600080fd5b506100bd6100d7565b005b60006020528060005260406000206000915090505481565b60008060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205490506000811115610195573373ffffffffffffffffffffffffffffffffffffffff168160405160006040518083038185875af1925050505060008060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055505b505600a165627a7a72305820a2a872c11cc01048a3e18a4a62a294aaec42c25f66692b299e285dea78c55d790029"; 97 | DefectChecker byteDefectChecker = parserFromBytecode(bytecode); 98 | System.out.println(byteDefectChecker.printAllDetectResult()); 99 | 100 | /*****Detect From Source Code*****/ 101 | String filePath = "./test.sol"; 102 | parserFromSourceCodeFile(filePath, "Victim"); 103 | 104 | 105 | long endTime = System.currentTimeMillis(); 106 | System.out.println("Running time:" + (endTime - startTime) + "ms"); 107 | } 108 | } 109 | -------------------------------------------------------------------------------- /DefectChecker/src/Pair.java: -------------------------------------------------------------------------------- 1 | public class Pair { 2 | private E first; 3 | private F second; 4 | 5 | public Pair(){ 6 | 7 | } 8 | 9 | public Pair(E first, F second){ 10 | this.first = first; 11 | this.second = second; 12 | } 13 | 14 | public E getFirst() { 15 | return first; 16 | } 17 | public void setFirst(E first) { 18 | this.first = first; 19 | } 20 | public F getSecond() { 21 | return second; 22 | } 23 | public void setSecond(F second) { 24 | this.second = second; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /DefectChecker/src/Utils.java: -------------------------------------------------------------------------------- 1 | import java.io.*; 2 | import java.util.ArrayList; 3 | import java.util.HashMap; 4 | import java.util.concurrent.*; 5 | import java.util.regex.Matcher; 6 | import java.util.regex.Pattern; 7 | 8 | public class Utils { 9 | 10 | public static final int DIGITAL = 1; 11 | public static final int STRING = 2; 12 | 13 | public static String runCMDWithTimeout(String cmd[]){ 14 | 15 | final ExecutorService exec = Executors.newFixedThreadPool(1); 16 | String result = null; 17 | Callable call = new Callable() { 18 | public String call() throws Exception { 19 | String result = ""; 20 | Process pro = Runtime.getRuntime().exec(cmd); 21 | 22 | InputStream in = null; 23 | in = pro.getInputStream(); 24 | 25 | BufferedReader reader = new BufferedReader(new InputStreamReader(in)); 26 | String line = ""; 27 | while((line = reader.readLine()) != null) 28 | result += line + "\n"; 29 | pro.destroy(); 30 | return result; 31 | } 32 | }; 33 | 34 | try { 35 | 36 | Future future = exec.submit(call); 37 | result = future.get(1000 * 10, TimeUnit.MILLISECONDS); 38 | 39 | } catch (TimeoutException e){ 40 | System.out.println(cmd[cmd.length-1] + " ===> time out"); 41 | } catch (Exception e) { 42 | e.printStackTrace(); 43 | } finally { 44 | exec.shutdown(); 45 | } 46 | 47 | return result; 48 | } 49 | 50 | 51 | public static String getDisasmCode(String binary){ 52 | String disasmCode = ""; 53 | if(binary.startsWith("0x")) 54 | binary = binary.substring(2,binary.length()); 55 | File tmp = null; 56 | try{ 57 | tmp = new File("./tmp.txt"); 58 | 59 | BufferedWriter writer = new BufferedWriter(new FileWriter(tmp)); 60 | writer.write(binary); 61 | writer.flush(); 62 | writer.close(); 63 | disasmCode = runCMDWithTimeout(new String[]{"evm-1.8.14" , "disasm", tmp.getAbsolutePath()}); 64 | }catch (Exception e){ 65 | e.printStackTrace(); 66 | }finally { 67 | tmp.delete(); 68 | } 69 | return disasmCode; 70 | } 71 | 72 | public static String replaceInsr(String line){ 73 | line = line.replace("SUICIDE", "SELFDESTRUCT"); 74 | line = line.replace("Missing opcode 0xfd", "REVERT"); 75 | line = line.replace("Missing opcode 0xfe", "ASSERTFAIL"); 76 | line = line.replaceAll("Missing opcode .+?", "INVALID"); 77 | 78 | return line; 79 | } 80 | 81 | public static int Hex2Int(String hex){ 82 | if(hex.length() < 1) 83 | return 0; 84 | int parseInt = Integer.parseInt(hex, 16); 85 | return parseInt; 86 | } 87 | 88 | public static Long Hex2Long(String hex){ 89 | if(hex.length() < 1) 90 | return 0L; 91 | Long parseLong = Long.parseLong(hex, 16); 92 | return parseLong; 93 | } 94 | 95 | public static ArrayList>> disasmParser(String disasmCode){ 96 | ArrayList>> disasm = new ArrayList<>(); 97 | String[] lines = disasmCode.split("\n"); 98 | boolean start = false; 99 | for(String line : lines){ 100 | if(!start){ 101 | start = true; 102 | continue; 103 | } 104 | line = replaceInsr(line); 105 | String[] tmp = line.split(": "); 106 | //this is depends on evm verson 107 | // int lineID = Utils.Hex2Int(tmp[0]); 108 | int lineID = Integer.parseInt(tmp[0]); 109 | String[] tmp2 = tmp[1].split(" "); 110 | String pushID = ""; 111 | if(tmp2.length > 1){ 112 | pushID = tmp2[1].replaceFirst("0x", ""); 113 | } 114 | Pair instr = new Pair(); 115 | instr.setFirst(tmp2[0]); 116 | instr.setSecond(pushID); 117 | 118 | Pair> lineInstr = new Pair>(); 119 | lineInstr.setFirst(lineID); 120 | lineInstr.setSecond(instr); 121 | disasm.add(lineInstr); 122 | } 123 | return disasm; 124 | 125 | } 126 | 127 | public static int getType(String instr){ 128 | //1: integer 2:string Solidity doesn't have double 129 | int result = Utils.DIGITAL; 130 | for(int i = 0;i < instr.length();i++){ 131 | if(Character.isDigit(instr.charAt(i)) || instr.charAt(i) == '_') 132 | continue; 133 | else{ 134 | result = Utils.STRING; 135 | break; 136 | } 137 | } 138 | return result; 139 | } 140 | 141 | public static Pair splitInstr2(String instr){ 142 | instr = instr.replaceAll(" ", ""); 143 | Pair res = new Pair<>(); 144 | //EXAMPLE1: EQ_1210(AND_1186(PUSH20_1165,AND_1164(PUSH20_1143,DIV_1142(SLOAD_1135(0_1131),1_1140))),AND_1209(PUSH20_1188,ORIGIN_1187)) 145 | //EXAMPLE2: EQ_1210(PUSH20_1165,AND_1209(PUSH20_1188,ORIGIN_1187)) 146 | //EXAMPLE3: AND_1209(PUSH20_1188,ORIGIN_1187) 147 | //EXAMPLE4: EQ_1210(AND_1186(PUSH20_1165,AND_1164(PUSH20_1143,DIV_1142(SLOAD_1135(0_1131),1_1140))),PUSH20_1165) 148 | int flag = 0; 149 | int startPos = -1; 150 | int splitPos = -1; 151 | int endPos = -1; 152 | for(int i = 0;i < instr.length(); i++){ 153 | char c = instr.charAt(i); 154 | if(c == '('){ 155 | flag++; 156 | if(flag == 1 && startPos == -1) 157 | startPos = i; 158 | } 159 | else if(c == ')'){ 160 | flag--; 161 | if(flag == 1 && startPos != -1 && splitPos != -1) 162 | endPos = i+1; 163 | else if(flag == 0 && startPos != -1 && splitPos != -1) 164 | endPos = i; 165 | } 166 | else if(c == ','){ 167 | if(flag == 1 && startPos != -1 && splitPos == -1){ 168 | splitPos = i; 169 | } 170 | } 171 | } 172 | res.setFirst(instr.substring(startPos+1, splitPos)); 173 | res.setSecond(instr.substring(splitPos+1, endPos)); 174 | return res; 175 | } 176 | 177 | public static int getSlotID(String condition){ 178 | //SLOAD_382(SHA3_381(0_379,64_378) 179 | //SLOAD_382(0_64) 180 | int slotID = -1; 181 | Pattern p = Pattern.compile("SLOAD_[0-9]+?\\(([0-9]+?)_"); 182 | Matcher m = p.matcher(condition); 183 | if(m.find()){ 184 | if (!(m.group(1) == null || "".equals(m.group(1)))) { 185 | String tmp = m.group(1); 186 | if(Utils.getType(tmp) == Utils.DIGITAL){ 187 | slotID = Integer.valueOf(tmp); 188 | } 189 | } 190 | } 191 | return slotID; 192 | } 193 | 194 | public static String getSlotAddress(String condition){ 195 | //EXAMPLE: ISZERO_389(GT_388(SLOAD_382(SHA3_381(0_379,64_378)),0_385)) 196 | String address = ""; 197 | int start = -1; 198 | int end = -1; 199 | int idx = 0; 200 | for(int i = condition.indexOf("SLOAD_"); i < condition.length(); i++) { 201 | if (condition.charAt(i) == '(') { 202 | idx++; 203 | if(start == -1) 204 | start = i; 205 | } 206 | if (condition.charAt(i) == ')') { 207 | idx--; 208 | } 209 | if (idx == 0 && start > 0) { 210 | end = i; 211 | break; 212 | } 213 | } 214 | if(end > start){ 215 | address = condition.substring(start+1, end); 216 | } 217 | address = address.replaceAll("_[0-9]+", ""); 218 | return address; 219 | } 220 | 221 | public static boolean legalRange(Integer pos, ArrayList> ranges){ 222 | for(Pair range : ranges){ 223 | if(pos >= range.getFirst() && pos <= range.getSecond()) 224 | return true; 225 | } 226 | 227 | return false; 228 | } 229 | 230 | 231 | public static HashMap> getGroundTruth(File file){ 232 | 233 | HashMap> groundTruthList = new HashMap<>(); 234 | try{ 235 | String line = ""; 236 | BufferedReader reader = new BufferedReader(new FileReader(file)); 237 | while((line = reader.readLine()) != null){ 238 | String[] tmp = line.split(","); 239 | ArrayList answerList = new ArrayList<>(); 240 | for(int i =0; i < 8; i++) 241 | answerList.add(false); 242 | if(tmp[1].equals("1")) //1-B: Uncheck External Calls 243 | answerList.set(0, true); 244 | if(tmp[3].equals("1")) //3-D: Strict Balance Equality 245 | answerList.set(1, true); 246 | if(tmp[5].equals("1")) //5-F: Transaction State Dependency 247 | answerList.set(2, true); 248 | if(tmp[8].equals("1")) //8-I: Block Info Dependency 249 | answerList.set(3, true); 250 | if(tmp[18].equals("1")) //18-S: Greedy Contract 251 | answerList.set(4, true); 252 | if(tmp[2].equals("1")) //2-C: DoS Under External Influence 253 | answerList.set(5, true); 254 | if(tmp[9].equals("1")) //9-J: Nest Call 255 | answerList.set(6, true); 256 | if(tmp[6].equals("1")) //6-G: Reentrancy 257 | answerList.set(7, true); 258 | groundTruthList.put(tmp[0].replaceFirst("0x", ""), answerList); 259 | } 260 | }catch (Exception e){ 261 | e.printStackTrace(); 262 | } 263 | return groundTruthList; 264 | } 265 | 266 | public static String getBytecodeFromFile(File file){ 267 | String bytecode = ""; 268 | try{ 269 | 270 | BufferedReader reader = new BufferedReader(new FileReader(file)); 271 | String line = ""; 272 | while((line = reader.readLine()) != null){ 273 | bytecode += line; 274 | } 275 | }catch (Exception e){ 276 | e.printStackTrace(); 277 | } 278 | 279 | return bytecode; 280 | } 281 | 282 | public static void printAnswerCheck(ArrayList groundTruth, DefectChecker defectChecker){ 283 | //0. Uncheck External Calls 1. Strict Balance Equality 2. Transaction State Dependency 3. Block Info Dependency 284 | //4. Greedy Contract 5. DoS Under External Influence 6. Nest Call 7. Reentrancy 285 | if(defectChecker.hasUnchechedExternalCalls != groundTruth.get(0)){ 286 | System.out.println("Uncheck External Calls check fail. The answer is " + groundTruth.get(0)); 287 | } 288 | 289 | if(defectChecker.hasStrictBalanceEquality != groundTruth.get(1)){ 290 | System.out.println("Strict Balance Equality check fail. The answer is " + groundTruth.get(1)); 291 | } 292 | 293 | if(defectChecker.hasTransactionStateDependency != groundTruth.get(2)){ 294 | System.out.println("Transaction State Dependency check fail. The answer is " + groundTruth.get(2)); 295 | } 296 | 297 | if(defectChecker.hasBlockInfoDependency != groundTruth.get(3)){ 298 | System.out.println("Block Info Dependency check fail. The answer is " + groundTruth.get(3)); 299 | } 300 | 301 | if(defectChecker.hasGreedyContract != groundTruth.get(4)){ 302 | System.out.println("Greedy Contract check fail. The answer is " + groundTruth.get(4)); 303 | } 304 | 305 | if(defectChecker.hasDoSUnderExternalInfluence != groundTruth.get(5)){ 306 | System.out.println("DoS Under External Influence check fail. The answer is " + groundTruth.get(5)); 307 | } 308 | 309 | if(defectChecker.hasNestCall != groundTruth.get(6)){ 310 | System.out.println("Nest Call check fail. The answer is " + groundTruth.get(6)); 311 | } 312 | 313 | if(defectChecker.hasReentrancy != groundTruth.get(7)){ 314 | System.out.println("Reentrancy check fail. The answer is " + groundTruth.get(7)); 315 | } 316 | 317 | } 318 | } 319 | -------------------------------------------------------------------------------- /DefectChecker/test.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.4.25; 2 | 3 | contract Victim{ 4 | mapping(address => uint) public userBalance; 5 | function withDraw(uint amount){ 6 | 7 | if(userBalance[msg.sender] > amount){ 8 | //msg.sender.transfer(amount); 9 | //userBalance[msg.sender] -= amount; 10 | msg.sender.call.value(amount)(); 11 | userBalance[msg.sender] -= amount; 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /ReadMe: -------------------------------------------------------------------------------- 1 | Note (DEC-2024): 2 | 3 | This work was initiated at the end of 2017. There have been significant changes in recent years. For example, many defects are now outdated and will appear in recent Solidity versions. Additionally, smart contracts have become much more complicated compared to those in 2017. Thus, this tool may not work on the current smart contracts. 4 | 5 | ---------------------------------------------------------------------------------------------------------------------------------- 6 | There are two kinds of datasets, i.e., bytecode on Ethereum and labeled ground truth(ContractDefect.csv). 7 | You can found byte code at : https://drive.google.com/open?id=19m2ZWXI9HeJk81WSKeoFd0q3cIXEjcLF ; There are two files in this zip; hashcode stores all distince bytecode, which is identified by a hash value. You can find the related contract addresses on hashaddr. 8 | 9 | Analysis Result.txt.zip is the analysis results of the smart contracts on Ethereum. Each distinct bytecode is identified by a hash value. Related contract addresses can be found on our dataset. 10 | 11 | 12 | The environment of DefectChecker: 13 | 1. JDK 1.8 14 | 2. EVM Version: 1.8.14 15 | 3. Solidity version: 0.4.25 16 | To be notice, the command on the L35 of Main.java and L63 of Utils.java might need change according to users' local environment 17 | 18 | 19 | --------------------------------------------------------------------------------