├── .gitattributes ├── .gitignore ├── .idea ├── .name ├── artifacts │ └── EtherSolve_jar.xml ├── compiler.xml ├── jarRepositories.xml ├── jsLibraryMappings.xml ├── misc.xml ├── modules │ ├── Abi │ │ └── EthereumBytecodeTransformer.Abi.iml │ └── EtherSolve.iml ├── runConfigurations.xml ├── vcs.xml └── webContexts.xml ├── Abi ├── build.gradle └── src │ └── main │ └── java │ ├── IRExtractor.java │ ├── MainAbi.java │ ├── Validator.java │ ├── abi │ ├── Abi.java │ ├── AbiFunction.java │ ├── HashDB.java │ └── fields │ │ ├── FunctionType.java │ │ ├── IOElement.java │ │ ├── SolidityType.java │ │ ├── SolidityTypeID.java │ │ └── StateMutability.java │ ├── comparation │ ├── AbiComparator.java │ └── AbiComparison.java │ ├── etherscan │ ├── EtherScanDownloader.java │ └── gson │ │ └── EtherscanResponse.java │ ├── gson │ └── GsonAbi.java │ ├── ir │ └── IRCfg.java │ └── rebuiltabi │ ├── AbiExtractor.java │ ├── RebuiltAbi.java │ ├── RebuiltAbiFunction.java │ └── fields │ ├── RebuiltIOElement.java │ ├── RebuiltSolidityType.java │ └── RebuiltSolidityTypeID.java ├── Core ├── build.gradle └── src │ ├── main │ └── java │ │ ├── Main.java │ │ ├── SolidityInfo │ │ ├── SolidityVersion.java │ │ └── SolidityVersionUnknownException.java │ │ ├── opcodes │ │ ├── ArithmeticOpcode.java │ │ ├── BlockOpcode.java │ │ ├── ControlFlowOpcode.java │ │ ├── EnvironmentalOpcode.java │ │ ├── InvalidOpcode.java │ │ ├── LogOpcode.java │ │ ├── Opcode.java │ │ ├── OpcodeID.java │ │ ├── StackOpcode.java │ │ ├── SystemOpcode.java │ │ ├── arithmeticOpcodes │ │ │ ├── BinaryArithmeticOpcode.java │ │ │ ├── TernaryArithmeticOpcode.java │ │ │ ├── UnaryArithmeticOpcode.java │ │ │ ├── binaryArithmeticOpcodes │ │ │ │ ├── AddOpcode.java │ │ │ │ ├── AndOpcode.java │ │ │ │ ├── ByteOpcode.java │ │ │ │ ├── DivOpcode.java │ │ │ │ ├── EQOpcode.java │ │ │ │ ├── ExpOpcode.java │ │ │ │ ├── GTOpcode.java │ │ │ │ ├── LTOpcode.java │ │ │ │ ├── ModOpcode.java │ │ │ │ ├── MulOpcode.java │ │ │ │ ├── OrOpcode.java │ │ │ │ ├── SAROpcode.java │ │ │ │ ├── SDivOpcode.java │ │ │ │ ├── SGTOpcode.java │ │ │ │ ├── SHA3Opcode.java │ │ │ │ ├── SHLOpcode.java │ │ │ │ ├── SHROpcode.java │ │ │ │ ├── SLTOpcode.java │ │ │ │ ├── SModOpcode.java │ │ │ │ ├── SignExtendOpcode.java │ │ │ │ ├── SubOpcode.java │ │ │ │ └── XorOpcode.java │ │ │ ├── ternaryArithmeticOpcodes │ │ │ │ ├── AddModOpcode.java │ │ │ │ └── MulModOpcode.java │ │ │ └── unaryArithmeticOpcodes │ │ │ │ ├── IsZeroOpcode.java │ │ │ │ └── NotOpcode.java │ │ ├── blockOpcodes │ │ │ ├── BlockHashOpcode.java │ │ │ ├── ChainIdOpcode.java │ │ │ ├── CoinBaseOpcode.java │ │ │ ├── DifficultyOpcode.java │ │ │ ├── GasLimitOpcode.java │ │ │ ├── NumberOpcode.java │ │ │ └── TimeStampOpcode.java │ │ ├── controlFlowOpcodes │ │ │ ├── JumpDestOpcode.java │ │ │ ├── JumpIOpcode.java │ │ │ ├── JumpOpcode.java │ │ │ └── StopOpcode.java │ │ ├── environmentalOpcodes │ │ │ ├── AddressOpcode.java │ │ │ ├── BalanceOpcode.java │ │ │ ├── CallDataCopyOpcode.java │ │ │ ├── CallDataLoadOpcode.java │ │ │ ├── CallDataSizeOpcode.java │ │ │ ├── CallValueOpcode.java │ │ │ ├── CallerOpcode.java │ │ │ ├── CodeCopyOpcode.java │ │ │ ├── CodeSizeOpcode.java │ │ │ ├── ExtCodeCopyOpcode.java │ │ │ ├── ExtCodeHashOpcode.java │ │ │ ├── ExtCodeSizeOpcode.java │ │ │ ├── GasPriceOpcode.java │ │ │ ├── OriginOpcode.java │ │ │ ├── ReturnDataCopyOpcode.java │ │ │ ├── ReturnDataSizeOpcode.java │ │ │ └── SelfBalanceOpcode.java │ │ ├── stackOpcodes │ │ │ ├── DupOpcode.java │ │ │ ├── GasOpcode.java │ │ │ ├── MLoadOpcode.java │ │ │ ├── MSizeOpcode.java │ │ │ ├── MStore8Opcode.java │ │ │ ├── MStoreOpcode.java │ │ │ ├── PCOpcode.java │ │ │ ├── PopOpcode.java │ │ │ ├── PushOpcode.java │ │ │ ├── SLoadOpcode.java │ │ │ ├── SStoreOpcode.java │ │ │ └── SwapOpcode.java │ │ └── systemOpcodes │ │ │ ├── CallCodeOpcode.java │ │ │ ├── CallOpcode.java │ │ │ ├── CreateOpcode.java │ │ │ ├── DelegateCallOpcode.java │ │ │ ├── ReturnOpcode.java │ │ │ ├── RevertOpcode.java │ │ │ ├── SelfDestructOpcode.java │ │ │ └── StaticCallOpcode.java │ │ ├── parseTree │ │ ├── Bytecode.java │ │ ├── BytecodeParser.java │ │ ├── Contract.java │ │ ├── NotSolidityContractException.java │ │ ├── SymbolicExecution │ │ │ ├── StackExceededException.java │ │ │ ├── SymbolicExecutionStack.java │ │ │ └── UnknownStackElementException.java │ │ └── cfg │ │ │ ├── BasicBlock.java │ │ │ ├── BasicBlockType.java │ │ │ ├── Cfg.java │ │ │ ├── CfgBuildReport.java │ │ │ └── CfgBuilder.java │ │ └── utils │ │ ├── JsonExporter.java │ │ ├── Message.java │ │ ├── Pair.java │ │ └── Triplet.java │ └── test │ └── java │ └── parseTree │ └── SymbolicExecutionStackTest.java ├── LICENSE ├── Logo ├── Logo.png ├── Logo.svg └── LogoOpt.svg ├── README.md ├── SecurityAnalysis ├── build.gradle └── src │ └── main │ └── java │ ├── analysers │ ├── StoreAccessAfterUnsafeCall.java │ └── TxOrigin.java │ └── main │ ├── DatasetTester.java │ ├── SecurityAnalyser.java │ ├── SecurityAnalysisReport.java │ ├── SecurityDetection.java │ ├── SecurityVulnerability.java │ └── SnippetsTester.java ├── UI ├── build.gradle └── src │ └── main │ ├── java │ ├── cli │ │ └── MainCLI.java │ └── graphviz │ │ ├── CFGPrinter.java │ │ ├── GVBlock.java │ │ ├── GVEdge.java │ │ ├── GVGraph.java │ │ └── MainGV.java │ └── resources │ └── report-template │ ├── svg-pan-zoom.js │ ├── svg-pan-zoom.min.js │ ├── template-vue.html │ └── template.html ├── WebApp ├── build.gradle └── src │ └── main │ ├── java │ ├── json_utils │ │ ├── PostRequestBody.java │ │ ├── RenderRequestBody.java │ │ └── Response.java │ ├── processing │ │ ├── AddressProcessor.java │ │ ├── BytecodeProcessor.java │ │ ├── GraphvizException.java │ │ └── GraphvizProcessor.java │ └── server │ │ ├── ApiController.java │ │ ├── App.java │ │ ├── GuiController.java │ │ └── RenderController.java │ └── resources │ └── application.yml ├── artifact └── EtherSolve.jar ├── build.gradle ├── doc ├── Main.html ├── MainAbi.html ├── SolidityInfo │ ├── SolidityVersion.html │ ├── SolidityVersionUnknownException.html │ ├── package-summary.html │ └── package-tree.html ├── Validator.html ├── abi │ ├── Abi.html │ ├── AbiFunction.html │ ├── HashDB.html │ ├── fields │ │ ├── FunctionType.html │ │ ├── IOElement.html │ │ ├── SolidityType.html │ │ ├── SolidityTypeID.html │ │ ├── StateMutability.html │ │ ├── package-summary.html │ │ └── package-tree.html │ ├── package-summary.html │ └── package-tree.html ├── allclasses-index.html ├── allclasses.html ├── allpackages-index.html ├── comparation │ ├── AbiComparator.html │ ├── AbiComparison.html │ ├── package-summary.html │ └── package-tree.html ├── constant-values.html ├── deprecated-list.html ├── element-list ├── etherscan │ ├── EtherScanDownloader.html │ ├── gson │ │ ├── EtherscanResponse.html │ │ ├── package-summary.html │ │ └── package-tree.html │ ├── package-summary.html │ └── package-tree.html ├── graphviz │ ├── CFGPrinter.html │ ├── GVBlock.html │ ├── GVEdge.html │ ├── GVGraph.html │ ├── MainGV.html │ ├── package-summary.html │ └── package-tree.html ├── gson │ ├── GsonAbi.html │ ├── package-summary.html │ └── package-tree.html ├── help-doc.html ├── index-files │ ├── index-1.html │ ├── index-10.html │ ├── index-11.html │ ├── index-12.html │ ├── index-13.html │ ├── index-14.html │ ├── index-15.html │ ├── index-16.html │ ├── index-17.html │ ├── index-18.html │ ├── index-19.html │ ├── index-2.html │ ├── index-20.html │ ├── index-21.html │ ├── index-22.html │ ├── index-3.html │ ├── index-4.html │ ├── index-5.html │ ├── index-6.html │ ├── index-7.html │ ├── index-8.html │ └── index-9.html ├── index.html ├── javafx │ ├── BasicBlockCell.html │ ├── CFGPrinter.html │ ├── CfgBackwardEdge.html │ ├── CfgEdge.html │ ├── MainFx.html │ ├── package-summary.html │ └── package-tree.html ├── jquery │ ├── external │ │ └── jquery │ │ │ └── jquery.js │ ├── images │ │ ├── ui-bg_glass_55_fbf9ee_1x400.png │ │ ├── ui-bg_glass_65_dadada_1x400.png │ │ ├── ui-bg_glass_75_dadada_1x400.png │ │ ├── ui-bg_glass_75_e6e6e6_1x400.png │ │ ├── ui-bg_glass_95_fef1ec_1x400.png │ │ ├── ui-bg_highlight-soft_75_cccccc_1x100.png │ │ ├── ui-icons_222222_256x240.png │ │ ├── ui-icons_2e83ff_256x240.png │ │ ├── ui-icons_454545_256x240.png │ │ ├── ui-icons_888888_256x240.png │ │ └── ui-icons_cd0a0a_256x240.png │ ├── jquery-3.3.1.js │ ├── jquery-migrate-3.0.1.js │ ├── jquery-ui.css │ ├── jquery-ui.js │ ├── jquery-ui.min.css │ ├── jquery-ui.min.js │ ├── jquery-ui.structure.css │ ├── jquery-ui.structure.min.css │ ├── jszip-utils │ │ └── dist │ │ │ ├── jszip-utils-ie.js │ │ │ ├── jszip-utils-ie.min.js │ │ │ ├── jszip-utils.js │ │ │ └── jszip-utils.min.js │ └── jszip │ │ └── dist │ │ ├── jszip.js │ │ └── jszip.min.js ├── member-search-index.js ├── opcodes │ ├── ArithmeticOpcode.html │ ├── BlockOpcode.html │ ├── ControlFlowOpcode.html │ ├── EnvironmentalOpcode.html │ ├── InvalidOpcode.html │ ├── LogOpcode.html │ ├── Opcode.html │ ├── OpcodeID.html │ ├── StackOpcode.html │ ├── SystemOpcode.html │ ├── arithmeticOpcodes │ │ ├── BinaryArithmeticOpcode.html │ │ ├── TernaryArithmeticOpcode.html │ │ ├── UnaryArithmeticOpcode.html │ │ ├── binaryArithmeticOpcodes │ │ │ ├── AddOpcode.html │ │ │ ├── AndOpcode.html │ │ │ ├── ByteOpcode.html │ │ │ ├── DivOpcode.html │ │ │ ├── EQOpcode.html │ │ │ ├── ExpOpcode.html │ │ │ ├── GTOpcode.html │ │ │ ├── LTOpcode.html │ │ │ ├── ModOpcode.html │ │ │ ├── MulOpcode.html │ │ │ ├── OrOpcode.html │ │ │ ├── SAROpcode.html │ │ │ ├── SDivOpcode.html │ │ │ ├── SGTOpcode.html │ │ │ ├── SHA3Opcode.html │ │ │ ├── SHLOpcode.html │ │ │ ├── SHROpcode.html │ │ │ ├── SLTOpcode.html │ │ │ ├── SModOpcode.html │ │ │ ├── SignExtendOpcode.html │ │ │ ├── SubOpcode.html │ │ │ ├── XorOpcode.html │ │ │ ├── package-summary.html │ │ │ └── package-tree.html │ │ ├── package-summary.html │ │ ├── package-tree.html │ │ ├── ternaryArithmeticOpcodes │ │ │ ├── AddModOpcode.html │ │ │ ├── MulModOpcode.html │ │ │ ├── package-summary.html │ │ │ └── package-tree.html │ │ └── unaryArithmeticOpcodes │ │ │ ├── IsZeroOpcode.html │ │ │ ├── NotOpcode.html │ │ │ ├── package-summary.html │ │ │ └── package-tree.html │ ├── blockOpcodes │ │ ├── BlockHashOpcode.html │ │ ├── ChainIdOpcode.html │ │ ├── CoinBaseOpcode.html │ │ ├── DifficultyOpcode.html │ │ ├── GasLimitOpcode.html │ │ ├── NumberOpcode.html │ │ ├── TimeStampOpcode.html │ │ ├── package-summary.html │ │ └── package-tree.html │ ├── controlFlowOpcodes │ │ ├── JumpDestOpcode.html │ │ ├── JumpIOpcode.html │ │ ├── JumpOpcode.html │ │ ├── StopOpcode.html │ │ ├── package-summary.html │ │ └── package-tree.html │ ├── environmentalOpcodes │ │ ├── AddressOpcode.html │ │ ├── BalanceOpcode.html │ │ ├── CallDataCopyOpcode.html │ │ ├── CallDataLoadOpcode.html │ │ ├── CallDataSizeOpcode.html │ │ ├── CallValueOpcode.html │ │ ├── CallerOpcode.html │ │ ├── CodeCopyOpcode.html │ │ ├── CodeSizeOpcode.html │ │ ├── ExtCodeCopyOpcode.html │ │ ├── ExtCodeHashOpcode.html │ │ ├── ExtCodeSizeOpcode.html │ │ ├── GasPriceOpcode.html │ │ ├── OriginOpcode.html │ │ ├── ReturnDataCopyOpcode.html │ │ ├── ReturnDataSizeOpcode.html │ │ ├── SelfBalanceOpcode.html │ │ ├── package-summary.html │ │ └── package-tree.html │ ├── package-summary.html │ ├── package-tree.html │ ├── stackOpcodes │ │ ├── DupOpcode.html │ │ ├── GasOpcode.html │ │ ├── MLoadOpcode.html │ │ ├── MSizeOpcode.html │ │ ├── MStore8Opcode.html │ │ ├── MStoreOpcode.html │ │ ├── PCOpcode.html │ │ ├── PopOpcode.html │ │ ├── PushOpcode.html │ │ ├── SLoadOpcode.html │ │ ├── SStoreOpcode.html │ │ ├── SwapOpcode.html │ │ ├── package-summary.html │ │ └── package-tree.html │ └── systemOpcodes │ │ ├── CallCodeOpcode.html │ │ ├── CallOpcode.html │ │ ├── CreateOpcode.html │ │ ├── DelegateCallOpcode.html │ │ ├── ReturnOpcode.html │ │ ├── RevertOpcode.html │ │ ├── SelfDestructOpcode.html │ │ ├── StaticCallOpcode.html │ │ ├── package-summary.html │ │ └── package-tree.html ├── overview-summary.html ├── overview-tree.html ├── package-search-index.js ├── package-summary.html ├── package-tree.html ├── parseTree │ ├── BasicBlock.html │ ├── BasicBlockType.html │ ├── Bytecode.html │ ├── BytecodeParser.html │ ├── Cfg.html │ ├── CfgBuildReport.html │ ├── CfgBuilder.html │ ├── Contract.html │ ├── NotSolidityContractException.html │ ├── SymbolicExecution │ │ ├── StackExceededException.html │ │ ├── SymbolicExecutionStack.html │ │ ├── UnknownStackElementException.html │ │ ├── package-summary.html │ │ └── package-tree.html │ ├── package-summary.html │ └── package-tree.html ├── rebuiltabi │ ├── AbiExtractor.html │ ├── RebuiltAbi.html │ ├── RebuiltAbiFunction.html │ ├── fields │ │ ├── RebuiltIOElement.html │ │ ├── RebuiltSolidityType.html │ │ ├── RebuiltSolidityTypeID.html │ │ ├── package-summary.html │ │ └── package-tree.html │ ├── package-summary.html │ └── package-tree.html ├── resources │ ├── glass.png │ └── x.png ├── script.js ├── search.js ├── serialized-form.html ├── stylesheet.css ├── type-search-index.js └── utils │ ├── JsonExporter.html │ ├── Message.html │ ├── Pair.html │ ├── Triplet.html │ ├── package-summary.html │ └── package-tree.html ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── inputs ├── dataset.csv └── export-verified-contractaddress-opensource-license.csv └── settings.gradle /.gitattributes: -------------------------------------------------------------------------------- 1 | *.html linguist-detectable=false 2 | *.css linguist-detectable=false 3 | *.js linguist-detectable=false -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | # Created by https://www.gitignore.io/api/java,gradle,intellij 3 | # Edit at https://www.gitignore.io/?templates=java,gradle,intellij 4 | 5 | ### Intellij ### 6 | # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and WebStorm 7 | # Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 8 | 9 | # User-specific stuff 10 | .idea/**/workspace.xml 11 | .idea/**/tasks.xml 12 | .idea/**/usage.statistics.xml 13 | .idea/**/dictionaries 14 | .idea/**/shelf 15 | 16 | # Generated files 17 | .idea/**/contentModel.xml 18 | 19 | # Sensitive or high-churn files 20 | .idea/**/dataSources/ 21 | .idea/**/dataSources.ids 22 | .idea/**/dataSources.local.xml 23 | .idea/**/sqlDataSources.xml 24 | .idea/**/dynamic.xml 25 | .idea/**/uiDesigner.xml 26 | .idea/**/dbnavigator.xml 27 | 28 | # Gradle 29 | .idea/**/gradle.xml 30 | .idea/**/libraries 31 | 32 | # Gradle and Maven with auto-import 33 | # When using Gradle or Maven with auto-import, you should exclude module files, 34 | # since they will be recreated, and may cause churn. Uncomment if using 35 | # auto-import. 36 | # .idea/modules.xml 37 | # .idea/*.iml 38 | # .idea/modules 39 | # *.iml 40 | # *.ipr 41 | 42 | # CMake 43 | cmake-build-*/ 44 | 45 | # Mongo Explorer plugin 46 | .idea/**/mongoSettings.xml 47 | 48 | # File-based project format 49 | *.iws 50 | 51 | # IntelliJ 52 | out/ 53 | 54 | # mpeltonen/sbt-idea plugin 55 | .idea_modules/ 56 | 57 | # JIRA plugin 58 | atlassian-ide-plugin.xml 59 | 60 | # Cursive Clojure plugin 61 | .idea/replstate.xml 62 | 63 | # Crashlytics plugin (for Android Studio and IntelliJ) 64 | com_crashlytics_export_strings.xml 65 | crashlytics.properties 66 | crashlytics-build.properties 67 | fabric.properties 68 | 69 | # Editor-based Rest Client 70 | .idea/httpRequests 71 | 72 | # Android studio 3.1+ serialized cache file 73 | .idea/caches/build_file_checksums.ser 74 | 75 | ### Intellij Patch ### 76 | # Comment Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-215987721 77 | 78 | # *.iml 79 | # modules.xml 80 | # .idea/misc.xml 81 | # *.ipr 82 | 83 | # Sonarlint plugin 84 | .idea/**/sonarlint/ 85 | 86 | # SonarQube Plugin 87 | .idea/**/sonarIssues.xml 88 | 89 | # Markdown Navigator plugin 90 | .idea/**/markdown-navigator.xml 91 | .idea/**/markdown-navigator/ 92 | 93 | ### Java ### 94 | # Compiled class file 95 | *.class 96 | 97 | # Log file 98 | *.log 99 | 100 | # BlueJ files 101 | *.ctxt 102 | 103 | # Mobile Tools for Java (J2ME) 104 | .mtj.tmp/ 105 | 106 | # Package Files # 107 | *.jar 108 | *.war 109 | *.nar 110 | *.ear 111 | *.zip 112 | *.tar.gz 113 | *.rar 114 | 115 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml 116 | hs_err_pid* 117 | 118 | ### Gradle ### 119 | .gradle 120 | build/ 121 | 122 | # Ignore Gradle GUI config 123 | gradle-app.setting 124 | 125 | # Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored) 126 | !gradle-wrapper.jar 127 | 128 | # Avoid ignoring main artifact jar file (.jar files are usually ignored) 129 | !artifact/EtherSolve.jar 130 | 131 | # Cache of project 132 | .gradletasknamecache 133 | 134 | # # Work around https://youtrack.jetbrains.com/issue/IDEA-116898 135 | # gradle/wrapper/gradle-wrapper.properties 136 | 137 | ### Gradle Patch ### 138 | **/build/ 139 | 140 | # End of https://www.gitignore.io/api/java,gradle,intellij 141 | /outputs/ 142 | /inputs/abi/ 143 | 144 | **/.settings/ 145 | **/bin/ 146 | .classpath 147 | .project 148 | .vscode/ -------------------------------------------------------------------------------- /.idea/.name: -------------------------------------------------------------------------------- 1 | EtherSolve -------------------------------------------------------------------------------- /.idea/compiler.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /.idea/jarRepositories.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /.idea/jsLibraryMappings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /.idea/modules/Abi/EthereumBytecodeTransformer.Abi.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /.idea/modules/EtherSolve.iml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /.idea/runConfigurations.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.idea/webContexts.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /Abi/build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id 'java' 3 | } 4 | 5 | group 'org.example' 6 | version '1.0-SNAPSHOT' 7 | 8 | sourceCompatibility = 1.8 9 | 10 | repositories { 11 | mavenCentral() 12 | } 13 | 14 | dependencies { 15 | testCompile group: 'junit', name: 'junit', version: '4.12' 16 | implementation 'com.google.code.gson:gson:2.8.6' 17 | // https://mvnrepository.com/artifact/org.bouncycastle/bcprov-jdk15on 18 | compile group: 'org.bouncycastle', name: 'bcprov-jdk15on', version: '1.65' 19 | compile project(':Core') 20 | } 21 | 22 | task runIRExtractor(type: JavaExec) { 23 | group = "Execution" 24 | description = "Run the extractor to get the intermediate representation used for automatic analysis" 25 | classpath = sourceSets.main.runtimeClasspath 26 | main = "IRExtractor" 27 | } 28 | -------------------------------------------------------------------------------- /Abi/src/main/java/IRExtractor.java: -------------------------------------------------------------------------------- 1 | import SolidityInfo.SolidityVersionUnknownException; 2 | import com.google.gson.*; 3 | import etherscan.EtherScanDownloader; 4 | import ir.IRCfg; 5 | import parseTree.Contract; 6 | import parseTree.NotSolidityContractException; 7 | import parseTree.cfg.BasicBlock; 8 | import parseTree.cfg.BasicBlockType; 9 | import parseTree.cfg.Cfg; 10 | import utils.Message; 11 | import utils.Pair; 12 | 13 | import java.io.*; 14 | import java.nio.file.Files; 15 | import java.nio.file.Paths; 16 | import java.util.ArrayList; 17 | 18 | public class IRExtractor { 19 | private final static String ADDRESS_CSV = "../inputs/dataset.csv"; 20 | private final static String OUTPUT_FOLDER = "../outputs/cfgs/"; 21 | 22 | private final static int START = 0; 23 | private final static int END = 1000; 24 | 25 | public static void main(String[] args) { 26 | final ArrayList> dataset = loadDataset(); 27 | Gson gson = new GsonBuilder() 28 | .registerTypeAdapter(IRCfg.class, (JsonSerializer) (src, typeOfSrc, context) -> { 29 | JsonObject obj = new JsonObject(); 30 | obj.add("nodes", new Gson().toJsonTree(src.getNodes())); 31 | JsonArray edges = new JsonArray(); 32 | for (Pair edge : src.getEdges()) { 33 | JsonArray jsonEdge = new JsonArray(); 34 | jsonEdge.add(edge.getKey()); 35 | jsonEdge.add(edge.getValue()); 36 | edges.add(jsonEdge); 37 | } 38 | obj.add("edges", edges); 39 | obj.add("computedVersion", new JsonPrimitive(src.getVersion())); 40 | obj.add("timeMillis", new JsonPrimitive(src.getTimeMillis())); 41 | return obj; 42 | }) 43 | .disableHtmlEscaping() 44 | .setPrettyPrinting() 45 | .create(); 46 | 47 | int i = START; 48 | for (Pair entry : dataset){ 49 | String address = entry.getKey(); 50 | String name = entry.getValue(); 51 | System.out.println(String.format("Processing contract %d/%d: %s", i, END, address)); 52 | System.out.flush(); 53 | IRCfg result = getIR(name, address); 54 | String json = gson.toJson(result); 55 | File file = new File(OUTPUT_FOLDER + "Contract_" + address + ".json"); 56 | if (file.getParentFile().mkdirs()) 57 | Message.printDebug("Output folder will be created"); 58 | try (BufferedWriter out = new BufferedWriter(new FileWriter(file))) { 59 | out.write(json); 60 | } catch (IOException e) { 61 | System.err.format("Error writing file %s: %s%n", address, e); 62 | e.printStackTrace(); 63 | } 64 | i++; 65 | } 66 | 67 | } 68 | 69 | private static IRCfg getIR(String name, String address){ 70 | IRCfg result = new IRCfg(); 71 | try { 72 | String bytecode = EtherScanDownloader.getContractBytecode(address); 73 | long startTime = System.currentTimeMillis(); 74 | Contract contract = new Contract(name, bytecode, true); 75 | result.setTimeMillis(System.currentTimeMillis() - startTime); 76 | Cfg runtimeCfg = contract.getRuntimeCfg(); 77 | if (runtimeCfg.getBuildReport().getBlockLimitErrors() != 0) 78 | Message.printWarning("Block limit reached"); 79 | if (runtimeCfg.getBuildReport().getCriticalErrors() != 0) 80 | Message.printWarning("Critical errors:\n" + runtimeCfg.getBuildReport()); 81 | for (BasicBlock node : runtimeCfg) { 82 | if (node.getType() != BasicBlockType.EXIT) { 83 | result.addNode(node.getOffset()); 84 | for (BasicBlock successor : node.getSuccessors()) 85 | if (successor.getType() != BasicBlockType.EXIT) 86 | result.addEdge(node.getOffset(), successor.getOffset()); 87 | } 88 | } 89 | result.setVersion(contract.getExactSolidityVersion()); 90 | } catch (IOException e) { 91 | System.err.println("Error downloading contract " + address); 92 | } catch (NotSolidityContractException e) { 93 | Message.printWarning("Not solidity contract: empty nodes and edges"); 94 | result.setVersion("not Solidity"); 95 | } catch (SolidityVersionUnknownException e) { 96 | result.setVersion("<0.5.9"); 97 | } 98 | return result; 99 | } 100 | 101 | private static ArrayList> loadDataset(){ 102 | ArrayList> dataset = new ArrayList<>(); 103 | try (BufferedReader br = Files.newBufferedReader(Paths.get(ADDRESS_CSV))) { 104 | String line; 105 | int i = 0; 106 | // Skip the csv header 107 | br.readLine(); 108 | // Skip the first START lines 109 | while (i < START) { 110 | br.readLine(); 111 | i++; 112 | } 113 | while ((line = br.readLine()) != null && i < END) { 114 | String[] values = line.split(","); 115 | dataset.add(new Pair<>(values[1], values[0])); 116 | i++; 117 | } 118 | } catch (IOException e) { 119 | System.err.format("Error reading file %s: %s%n", ADDRESS_CSV, e); 120 | e.printStackTrace(); 121 | } 122 | return dataset; 123 | } 124 | } 125 | -------------------------------------------------------------------------------- /Abi/src/main/java/abi/Abi.java: -------------------------------------------------------------------------------- 1 | package abi; 2 | 3 | import gson.GsonAbi; 4 | 5 | import java.util.ArrayList; 6 | 7 | /** 8 | * Class to represent a complete ABI generated by Solidity compiler 9 | */ 10 | public class Abi { 11 | private final ArrayList functions; 12 | 13 | /** 14 | * Builds an empty ABI 15 | */ 16 | public Abi() { 17 | this.functions = new ArrayList<>(); 18 | } 19 | 20 | /** 21 | * Adds a function to the ABI 22 | * @param function function to add 23 | */ 24 | public void addFunction(AbiFunction function) { 25 | functions.add(function); 26 | } 27 | 28 | /** 29 | * Gets the functions 30 | * @return An iterable object with the functions 31 | */ 32 | public Iterable extends AbiFunction> getFunctions() { 33 | return functions; 34 | } 35 | 36 | /** 37 | * Static method to build an ABI from a json file generated by Solidity compiler 38 | * @param src string representing the Json source 39 | * @return the built ABI 40 | */ 41 | public static Abi fromJson(String src){ 42 | return new GsonAbi().fromJson(src, Abi.class); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /Abi/src/main/java/abi/AbiFunction.java: -------------------------------------------------------------------------------- 1 | package abi; 2 | 3 | import abi.fields.FunctionType; 4 | import abi.fields.IOElement; 5 | 6 | import java.util.ArrayList; 7 | 8 | /** 9 | * Class to represent a function inside an ABI. 10 | * 11 | * It does not store all the information, but only: 12 | * 13 | * Type 14 | * Name 15 | * Inputs 16 | * Outputs 17 | * 18 | * Where inputs and outputs are lists of IOElement 19 | */ 20 | public class AbiFunction { 21 | private final FunctionType type; 22 | private final String name; 23 | private final ArrayList inputs; 24 | private final ArrayList outputs; 25 | //private StateMutability stateMutability; 26 | 27 | /** 28 | * Default constructor to build an empty function given name and type 29 | * @param name function name 30 | * @param functionType function type 31 | */ 32 | public AbiFunction(String name, FunctionType functionType) { 33 | this.name = name; 34 | this.type = functionType; 35 | this.inputs = new ArrayList<>(); 36 | this.outputs = new ArrayList<>(); 37 | } 38 | /* 39 | Not considered, they can be calculated 40 | private boolean constant; 41 | private boolean payable; 42 | */ 43 | 44 | /** 45 | * Default getter 46 | * @return function type 47 | */ 48 | public FunctionType getType() { 49 | return type; 50 | } 51 | 52 | /** 53 | * Default getter 54 | * @return function name 55 | */ 56 | public String getName() { 57 | return name; 58 | } 59 | 60 | /** 61 | * Default getter 62 | * @return function inputs 63 | */ 64 | public ArrayList getInputs() { 65 | return inputs; 66 | } 67 | 68 | /** 69 | * Default getter 70 | * @return function outputs 71 | */ 72 | public ArrayList getOutputs() { 73 | return outputs; 74 | } 75 | 76 | /*public StateMutability getStateMutability() { 77 | return stateMutability; 78 | }*/ 79 | 80 | /** 81 | * Adds an input 82 | * @param input input to add 83 | */ 84 | public void addInput(IOElement input){ 85 | this.inputs.add(input); 86 | } 87 | 88 | /** 89 | * Adds an input 90 | * @param output output to add 91 | */ 92 | public void addOutput(IOElement output){ 93 | this.outputs.add(output); 94 | } 95 | 96 | /** 97 | * Pops an input 98 | */ 99 | public void popInput() { 100 | this.inputs.remove(this.inputs.size()-1); 101 | } 102 | 103 | /** 104 | * Pops an output 105 | */ 106 | public void popOutput() { 107 | this.outputs.remove(this.outputs.size()-1); 108 | } 109 | 110 | 111 | 112 | /* 113 | type: "function", "constructor", or "fallback" (the unnamed “default” function); 114 | name: the name of the function; 115 | inputs: an array of objects, each of which contains: 116 | name: the name of the parameter; 117 | type: the canonical type of the parameter (more below). 118 | components: used for tuple types (more below). 119 | outputs: an array of objects similar to inputs, can be omitted if function doesn’t return anything; 120 | payable: true if function accepts ether, defaults to false; 121 | stateMutability: a string with one of the following values: pure (specified to not read blockchain state), 122 | view (specified to not modify the blockchain state), nonpayable and payable (same as payable above). 123 | constant: true if function is either pure or view 124 | */ 125 | } 126 | -------------------------------------------------------------------------------- /Abi/src/main/java/abi/HashDB.java: -------------------------------------------------------------------------------- 1 | package abi; 2 | 3 | import com.google.gson.Gson; 4 | 5 | import java.io.BufferedReader; 6 | import java.io.IOException; 7 | import java.io.InputStreamReader; 8 | import java.net.HttpURLConnection; 9 | import java.net.URL; 10 | import java.net.URLEncoder; 11 | import java.util.ArrayList; 12 | import java.util.List; 13 | 14 | public class HashDB { 15 | private static HashDB ilSoloEUnico = new HashDB(); 16 | 17 | private HashDB() { 18 | } 19 | 20 | public static HashDB getInstance() { 21 | return ilSoloEUnico; 22 | } 23 | 24 | private static class FourBytesResult { 25 | public String id; 26 | public String created_at; 27 | public String text_signature; 28 | public String hex_signature; 29 | public String bytes_signature; 30 | } 31 | 32 | private static class FourBytesResponse { 33 | public int count; 34 | public String next; 35 | public String previous; 36 | public List results = new ArrayList<>(); 37 | } 38 | 39 | private String get4ByteJsonFromHash(String hash) throws IOException { 40 | String stringUrl = "https://www.4byte.directory/api/v1/signatures/?format=json&hex_signature="; 41 | stringUrl += URLEncoder.encode(hash, "UTF-8"); 42 | 43 | URL urlForGetRequest = new URL(stringUrl); 44 | HttpURLConnection conn = (HttpURLConnection) urlForGetRequest.openConnection(); 45 | conn.setRequestMethod("GET"); 46 | String USER_AGENT = "Mozilla/5.0"; 47 | conn.setRequestProperty("User-Agent", USER_AGENT); 48 | int responseCode = conn.getResponseCode(); 49 | 50 | if (responseCode == HttpURLConnection.HTTP_OK) { 51 | BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream())); 52 | StringBuilder response = new StringBuilder(); 53 | 54 | String readLine = null; 55 | while ((readLine = in.readLine()) != null) { 56 | response.append(readLine); 57 | } 58 | in.close(); 59 | return response.toString(); 60 | } 61 | return null; 62 | } 63 | 64 | public String getSignatureFromHash(String hash) throws IOException{ 65 | Gson gson = new Gson(); 66 | FourBytesResponse fbr = gson.fromJson(get4ByteJsonFromHash(hash), FourBytesResponse.class); 67 | return fbr.results.get(0).text_signature; 68 | } 69 | 70 | public AbiFunction getAbiFromHash(String hash) throws Exception{ 71 | return null; 72 | } 73 | 74 | public static void main(String[] args) throws Exception{ 75 | System.out.println(HashDB.getInstance().getSignatureFromHash("0xbeca2e86")); 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /Abi/src/main/java/abi/fields/FunctionType.java: -------------------------------------------------------------------------------- 1 | package abi.fields; 2 | 3 | public enum FunctionType { 4 | FUNCTION, 5 | CONSTRUCTOR, 6 | FALLBACK, 7 | RECEIVE, 8 | EVENT 9 | } 10 | -------------------------------------------------------------------------------- /Abi/src/main/java/abi/fields/IOElement.java: -------------------------------------------------------------------------------- 1 | package abi.fields; 2 | 3 | import utils.Pair; 4 | 5 | import java.util.ArrayList; 6 | 7 | /** 8 | * Class to represent an element inside a function (both input and output) 9 | * 10 | * It stores: 11 | * 12 | * Name 13 | * Type 14 | * Components (currently ignored) 15 | * 16 | */ 17 | public class IOElement { 18 | /* 19 | name: the name of the parameter; 20 | type: the canonical type of the parameter (more below). 21 | components: used for tuple types (more below). 22 | */ 23 | 24 | private final String name; 25 | private final SolidityType type; 26 | private final ArrayList> components; 27 | 28 | /** 29 | * Default constructor with name and type. Components is initialized as an empty list 30 | * @param name name of the element 31 | * @param type type of the element 32 | */ 33 | public IOElement(String name, SolidityType type){ 34 | this.name = name; 35 | this.type = type; 36 | this.components = new ArrayList<>(); 37 | } 38 | 39 | /** 40 | * Adds a component 41 | * @param component component 42 | */ 43 | public void addComponent(Pair component){ 44 | this.components.add(component); 45 | } 46 | 47 | /** 48 | * Default getter 49 | * @return type 50 | */ 51 | public SolidityType getType() { 52 | return type; 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /Abi/src/main/java/abi/fields/SolidityType.java: -------------------------------------------------------------------------------- 1 | package abi.fields; 2 | 3 | import java.util.Objects; 4 | 5 | public class SolidityType { 6 | 7 | private SolidityTypeID solidityTypeID; 8 | private int n; 9 | private boolean isArray; 10 | private boolean isFixed; 11 | private int arrayLength; 12 | 13 | public SolidityType(SolidityTypeID solidityTypeID){ 14 | this (solidityTypeID, 0); 15 | } 16 | 17 | public SolidityType(SolidityTypeID solidityTypeID, int n){ 18 | this (solidityTypeID, n, false, false, 0); 19 | } 20 | 21 | public SolidityType(SolidityTypeID solidityTypeID, int n, boolean isArray){ 22 | this (solidityTypeID, n, isArray, false, 0); 23 | } 24 | 25 | public SolidityType(SolidityTypeID solidityTypeID, int n, boolean isArray, boolean isFixed, int arrayLength) { 26 | this.solidityTypeID = solidityTypeID; 27 | this.n = n; 28 | this.isArray = isArray; 29 | this.isFixed = isFixed; 30 | this.arrayLength = arrayLength; 31 | } 32 | 33 | @Override 34 | public String toString() { 35 | String result = solidityTypeID.toString().toLowerCase() + (n != 0 ? n : ""); 36 | if (isArray){ 37 | result += "["; 38 | if (isFixed) 39 | result += arrayLength; 40 | result += "]"; 41 | } 42 | return result; 43 | } 44 | 45 | public SolidityTypeID getSolidityTypeID() { 46 | return solidityTypeID; 47 | } 48 | 49 | public int getN() { 50 | return n; 51 | } 52 | 53 | public boolean isArray() { 54 | return isArray; 55 | } 56 | 57 | @Override 58 | public boolean equals(Object o) { 59 | if (this == o) return true; 60 | if (o == null || getClass() != o.getClass()) return false; 61 | SolidityType that = (SolidityType) o; 62 | return n == that.n && solidityTypeID == that.solidityTypeID; 63 | } 64 | 65 | @Override 66 | public int hashCode() { 67 | return Objects.hash(solidityTypeID, n); 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /Abi/src/main/java/abi/fields/SolidityTypeID.java: -------------------------------------------------------------------------------- 1 | package abi.fields; 2 | 3 | public enum SolidityTypeID { 4 | INT, 5 | UINT, 6 | ADDRESS, 7 | BOOL, 8 | TUPLE, 9 | BYTES, 10 | STRING 11 | } 12 | -------------------------------------------------------------------------------- /Abi/src/main/java/abi/fields/StateMutability.java: -------------------------------------------------------------------------------- 1 | package abi.fields; 2 | 3 | public enum StateMutability { 4 | PURE, 5 | VIEW, 6 | PAYABLE, 7 | NON_PAYABLE 8 | } 9 | -------------------------------------------------------------------------------- /Abi/src/main/java/comparation/AbiComparator.java: -------------------------------------------------------------------------------- 1 | package comparation; 2 | 3 | import abi.Abi; 4 | import abi.AbiFunction; 5 | import abi.fields.FunctionType; 6 | import abi.fields.IOElement; 7 | import abi.fields.SolidityType; 8 | import abi.fields.SolidityTypeID; 9 | import org.bouncycastle.jcajce.provider.digest.Keccak; 10 | import rebuiltabi.RebuiltAbi; 11 | import rebuiltabi.RebuiltAbiFunction; 12 | import rebuiltabi.fields.RebuiltSolidityType; 13 | import rebuiltabi.fields.RebuiltSolidityTypeID; 14 | import utils.Message; 15 | 16 | import java.util.List; 17 | import java.util.stream.Collectors; 18 | 19 | public class AbiComparator { 20 | 21 | public static final double COMPLETE_MATCH = 1; 22 | public static final double PARTIAL_MATCH = 0.5; 23 | public static final double NO_MATCH = 0; 24 | 25 | public static AbiComparison compare(RebuiltAbi rebuiltAbi, Abi downloadedAbi){ 26 | AbiComparison result = new AbiComparison(); 27 | for (AbiFunction function : downloadedAbi.getFunctions()){ 28 | // Compare only functions and fallback 29 | if (function.getType() == FunctionType.FUNCTION || function.getType() == FunctionType.FALLBACK){ 30 | String hash = "0x" + keccak256(getSignature(function)).substring(0,8); 31 | RebuiltAbiFunction candidate = rebuiltAbi.getFunction(hash); 32 | if (function.getType() == FunctionType.FALLBACK) 33 | candidate = rebuiltAbi.getFunction(""); 34 | double[] score = null; 35 | if (candidate != null){ 36 | result.addMatch(); 37 | score = compare(candidate, function); 38 | } else { 39 | result.addMismatch(); 40 | } 41 | result.addScore(hash, score); 42 | } 43 | } 44 | result.addMismatchedRebuiltFunctions(rebuiltAbi.getLength() - result.getMatch()); 45 | return result; 46 | } 47 | 48 | private static double[] compare(RebuiltAbiFunction rebuiltAbiFunction, AbiFunction downloadedFunction){ 49 | int argMin = Math.min(rebuiltAbiFunction.getInputs().size(), downloadedFunction.getInputs().size()); 50 | int argMax = Math.max(rebuiltAbiFunction.getInputs().size(), downloadedFunction.getInputs().size()); 51 | // If there are no inputs then it's a complete match; 52 | if (argMax == 0) 53 | return new double[0]; 54 | // Else checks for the inputs 55 | double[] score = new double[argMax]; 56 | for (int i = 0; i < argMin; i++){ 57 | score[i] = compareIOTypes(rebuiltAbiFunction.getInputs().get(i).getType(), downloadedFunction.getInputs().get(i).getType()); 58 | } 59 | for (int i = argMin; i < argMax; i++){ 60 | score[i] = NO_MATCH; 61 | } 62 | return score; 63 | } 64 | 65 | private static double compareIOTypes(RebuiltSolidityType candidateType, SolidityType referenceType) { 66 | if (candidateType.getTypeID() == RebuiltSolidityTypeID.SIMPLE){ 67 | switch (referenceType.getSolidityTypeID()){ 68 | case UINT: 69 | case INT: 70 | if (candidateType.getN() == referenceType.getN()) 71 | return COMPLETE_MATCH; 72 | else 73 | return PARTIAL_MATCH; 74 | case ADDRESS: 75 | // Address is 160 bits 76 | return candidateType.getN() == 160 ? COMPLETE_MATCH : PARTIAL_MATCH; 77 | case BOOL: 78 | // Bool is 1 bit 79 | return candidateType.getN() == 1 ? COMPLETE_MATCH : PARTIAL_MATCH; 80 | default: 81 | return NO_MATCH; 82 | } 83 | 84 | } else if (candidateType.getTypeID() == RebuiltSolidityTypeID.COMPLEX){ 85 | if (referenceType.isArray() || referenceType.getSolidityTypeID() == SolidityTypeID.STRING) 86 | return COMPLETE_MATCH; 87 | else 88 | return NO_MATCH; 89 | } else 90 | return NO_MATCH; 91 | } 92 | 93 | private static String getSignature(AbiFunction function) { 94 | StringBuilder signature = new StringBuilder(); 95 | signature.append(function.getName()); 96 | signature.append("("); 97 | List parameters = function.getInputs().stream().map(input -> input.getType().toString()).collect(Collectors.toList()); 98 | signature.append(String.join(",", parameters)); 99 | signature.append(")"); 100 | return signature.toString(); 101 | } 102 | 103 | public static String keccak256(String input) { 104 | Keccak.Digest256 keccak = new Keccak.Digest256(); 105 | StringBuilder sb = new StringBuilder(); 106 | for (byte b : keccak.digest(input.getBytes())) 107 | sb.append(String.format("%02x", b)); 108 | return sb.toString(); 109 | } 110 | 111 | public static void main(String[] args) { 112 | AbiFunction function = new AbiFunction("a", FunctionType.FUNCTION); 113 | function.addInput(new IOElement("arg", new SolidityType(SolidityTypeID.UINT, 256))); 114 | function.addInput(new IOElement("arg1", new SolidityType(SolidityTypeID.INT, 128))); 115 | System.out.println(getSignature(function)); 116 | System.out.println(keccak256(getSignature(function)).substring(0, 8)); 117 | } 118 | } 119 | -------------------------------------------------------------------------------- /Abi/src/main/java/comparation/AbiComparison.java: -------------------------------------------------------------------------------- 1 | package comparation; 2 | 3 | import java.util.Arrays; 4 | import java.util.HashMap; 5 | 6 | public class AbiComparison { 7 | public static final int FUNCTIONS_FOUND = 0; 8 | public static final int FUNCTIONS_INPUTS = 1; 9 | public static final int FUNCTIONS_INPUTS_SIZE = 2; 10 | 11 | private final HashMap functionsScore; 12 | private int foundFunctions; 13 | private int totalOriginalFunctions; 14 | private int totalRebuiltFunctions; 15 | 16 | public AbiComparison(){ 17 | functionsScore = new HashMap<>(); 18 | foundFunctions = 0; 19 | totalOriginalFunctions = 0; 20 | totalRebuiltFunctions = 0; 21 | } 22 | 23 | public void addScore(String name, double[] score){ 24 | functionsScore.put(name, score); 25 | } 26 | 27 | @Override 28 | public String toString() { 29 | StringBuilder sb = new StringBuilder(); 30 | for (String hash : functionsScore.keySet()) { 31 | sb.append(hash); 32 | sb.append(": "); 33 | sb.append(Arrays.toString(functionsScore.get(hash))); 34 | sb.append('\n'); 35 | } 36 | sb.setLength(sb.length() - 1); 37 | return sb.toString(); 38 | } 39 | 40 | public void addMatch() { 41 | foundFunctions++; 42 | totalOriginalFunctions++; 43 | totalRebuiltFunctions++; 44 | } 45 | 46 | public void addMismatch() { 47 | totalOriginalFunctions++; 48 | } 49 | 50 | public double precision(int depth) { 51 | return countCorrectSignatures(depth) / totalRebuiltFunctions; 52 | } 53 | 54 | public double recall(int depth){ 55 | return countCorrectSignatures(depth) / totalOriginalFunctions; 56 | } 57 | 58 | private double countCorrectSignatures(int depth){ 59 | double correctSignatures = 0; 60 | switch (depth){ 61 | case 0: 62 | correctSignatures = foundFunctions; 63 | break; 64 | case 1: 65 | for (String hash : functionsScore.keySet()) { 66 | boolean isCorrect = true; 67 | if (functionsScore.get(hash) != null) { 68 | for (double score : functionsScore.get(hash)) 69 | if (score == AbiComparator.NO_MATCH){ 70 | isCorrect = false; 71 | break; 72 | } 73 | if (isCorrect) 74 | correctSignatures++; 75 | } 76 | } 77 | break; 78 | case 2: 79 | for (String hash : functionsScore.keySet()) { 80 | boolean isCorrect = true; 81 | if (functionsScore.get(hash) != null) { 82 | for (double score : functionsScore.get(hash)) 83 | if (score != AbiComparator.COMPLETE_MATCH) { 84 | isCorrect = false; 85 | break; 86 | } 87 | if (isCorrect) 88 | correctSignatures++; 89 | } 90 | } 91 | break; 92 | default: 93 | throw new IllegalArgumentException("depth must be in range [0-2]"); 94 | } 95 | return correctSignatures; 96 | } 97 | 98 | public int getMatch() { 99 | return foundFunctions; 100 | } 101 | 102 | public void addMismatchedRebuiltFunctions(int i) { 103 | totalRebuiltFunctions += i; 104 | } 105 | 106 | public int getTotalOriginalFunctions() { 107 | return totalOriginalFunctions; 108 | } 109 | 110 | public int getTotalRebuiltFunctions() { 111 | return totalRebuiltFunctions; 112 | } 113 | } 114 | -------------------------------------------------------------------------------- /Abi/src/main/java/etherscan/EtherScanDownloader.java: -------------------------------------------------------------------------------- 1 | package etherscan; 2 | 3 | import abi.Abi; 4 | import com.google.gson.Gson; 5 | import etherscan.gson.EtherscanResponse; 6 | 7 | import java.io.BufferedReader; 8 | import java.io.IOException; 9 | import java.io.InputStreamReader; 10 | import java.net.HttpURLConnection; 11 | import java.net.URL; 12 | 13 | /** 14 | * Utility class to download abi and source code of a given address 15 | */ 16 | public class EtherScanDownloader { 17 | 18 | private final static String API_KEY = "YA5HAVF4DMYX6X3VM3NS7JKHCKK7FAXK68"; 19 | 20 | /** 21 | * Downloads an Abi from Etherscan if the contract is a verified one 22 | * @param address contract address 23 | * @return Abi 24 | * @throws IOException 25 | */ 26 | public static Abi getContractAbi(String address) throws IOException { 27 | String abiString = request("contract", "getabi", address); 28 | Gson gson = new Gson(); 29 | EtherscanResponse response = gson.fromJson(abiString, EtherscanResponse.class); 30 | return Abi.fromJson(response.getResult()); 31 | } 32 | 33 | /** 34 | * Downloads the source code of a contract 35 | * @param address contract address 36 | * @return hexadecimal string with the source code 37 | * @throws IOException 38 | */ 39 | public static String getContractBytecode(String address) throws IOException { 40 | String bytecodeRequest = request("proxy", "eth_getCode", address); 41 | Gson gson = new Gson(); 42 | EtherscanResponse response = gson.fromJson(bytecodeRequest, EtherscanResponse.class); 43 | if (response.getResult() == null) 44 | throw new IOException("Error in contract download"); 45 | return response.getResult().substring(2); 46 | } 47 | 48 | 49 | private static String request(String module, String action, String address) throws IOException { 50 | String request = String.format("https://api.etherscan.io/api?module=%s&action=%s&address=%s&apikey=%s", module, action, address, API_KEY); 51 | URL requestUrl = new URL(request); 52 | HttpURLConnection connection = (HttpURLConnection) requestUrl.openConnection(); 53 | connection.setRequestMethod("GET"); 54 | connection.setRequestProperty("User-Agent", "Mozilla/5.0"); 55 | if (connection.getResponseCode() == HttpURLConnection.HTTP_OK){ 56 | BufferedReader in = new BufferedReader(new InputStreamReader(connection.getInputStream())); 57 | StringBuilder sb = new StringBuilder(); 58 | String readLine = null; 59 | while ((readLine = in.readLine()) != null) { 60 | sb.append(readLine); 61 | } 62 | in.close(); 63 | return sb.toString(); 64 | } else { 65 | return null; 66 | } 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /Abi/src/main/java/etherscan/gson/EtherscanResponse.java: -------------------------------------------------------------------------------- 1 | package etherscan.gson; 2 | 3 | public class EtherscanResponse { 4 | private String status; 5 | private String message; 6 | private String result; 7 | 8 | public String getStatus() { 9 | return status; 10 | } 11 | 12 | public String getMessage() { 13 | return message; 14 | } 15 | 16 | public String getResult() { 17 | return result; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /Abi/src/main/java/gson/GsonAbi.java: -------------------------------------------------------------------------------- 1 | package gson; 2 | 3 | import abi.Abi; 4 | import abi.AbiFunction; 5 | import abi.fields.FunctionType; 6 | import abi.fields.IOElement; 7 | import abi.fields.SolidityType; 8 | import abi.fields.SolidityTypeID; 9 | import com.google.gson.*; 10 | 11 | /** 12 | * Utility class to read and write Abi and Rebuilt ABI into Json files 13 | */ 14 | public class GsonAbi { 15 | 16 | private final Gson gson; 17 | 18 | /** 19 | * Constructor which registers type adapters 20 | */ 21 | public GsonAbi(){ 22 | GsonBuilder gsonBuilder = new GsonBuilder(); 23 | // Deserializers 24 | gsonBuilder.registerTypeAdapter(IOElement.class, (JsonDeserializer) (src, typeOfSrc, context) -> parseIOElement(src, gsonBuilder)); 25 | gsonBuilder.registerTypeAdapter(AbiFunction.class, (JsonDeserializer) (src, typeOfSrc, context) -> parseFunction(src, gsonBuilder)); 26 | gsonBuilder.registerTypeAdapter(Abi.class, (JsonDeserializer) (src, typeOfSrc, context) -> parseAbi(src, gsonBuilder)); 27 | 28 | //Serializers 29 | gsonBuilder.registerTypeAdapter(SolidityType.class, (JsonSerializer) (src, typeOfSrc, context) -> new JsonPrimitive(src.toString())); 30 | gsonBuilder.registerTypeAdapter(FunctionType.class, (JsonSerializer) (src, typeOfSrc, context) -> new JsonPrimitive(src.toString().toLowerCase())); 31 | 32 | gsonBuilder.setPrettyPrinting(); 33 | 34 | gson = gsonBuilder.create(); 35 | } 36 | 37 | private Abi parseAbi(JsonElement src, GsonBuilder gsonBuilder){ 38 | Abi result = new Abi(); 39 | Gson gson = gsonBuilder.create(); 40 | for (JsonElement function : src.getAsJsonArray()) 41 | result.addFunction(gson.fromJson(function, AbiFunction.class)); 42 | return result; 43 | } 44 | 45 | private AbiFunction parseFunction(JsonElement src, GsonBuilder gsonBuilder){ 46 | JsonObject object = src.getAsJsonObject(); 47 | FunctionType type; 48 | switch (object.get("type").getAsString()) { 49 | case "function": 50 | type = FunctionType.FUNCTION; 51 | break; 52 | case "fallback": 53 | return new AbiFunction("", FunctionType.FALLBACK); 54 | case "constructor": 55 | type = FunctionType.CONSTRUCTOR; 56 | break; 57 | case "receive": 58 | type = FunctionType.RECEIVE; 59 | break; 60 | case "event": 61 | type = FunctionType.EVENT; 62 | break; 63 | default: 64 | throw new IllegalStateException("Unexpected value: " + object.get("type").getAsString()); 65 | } 66 | String name = ""; 67 | if (type != FunctionType.CONSTRUCTOR && type != FunctionType.RECEIVE) 68 | name = object.get("name").getAsString(); 69 | 70 | AbiFunction function = new AbiFunction(name, type); 71 | 72 | // NOTE: Here the parsing can be enhanced with state mutability, payable and more... 73 | if (type != FunctionType.RECEIVE) 74 | for (JsonElement ioElement : object.get("inputs").getAsJsonArray()){ 75 | function.addInput(gsonBuilder.create().fromJson(ioElement, IOElement.class)); 76 | } 77 | if (type == FunctionType.FUNCTION) 78 | for (JsonElement ioElement : object.get("outputs").getAsJsonArray()){ 79 | function.addOutput(gsonBuilder.create().fromJson(ioElement, IOElement.class)); 80 | } 81 | return function; 82 | } 83 | 84 | private IOElement parseIOElement(JsonElement src, GsonBuilder gsonBuilder){ 85 | JsonObject object = src.getAsJsonObject(); 86 | String name = object.get("name").getAsString(); 87 | SolidityTypeID id; 88 | int n = 0; 89 | boolean isArray; 90 | boolean isFixed; 91 | int arrayLength = 0; 92 | String type = object.get("type").getAsString(); 93 | String[] types = type.split("\\[",2); 94 | if (types.length == 2){ 95 | isArray = true; 96 | String arrLen = types[1].substring(0, types[1].length() - 1); 97 | if (arrLen.equals("")) 98 | isFixed = false; 99 | else{ 100 | isFixed = true; 101 | try { 102 | arrayLength = Integer.parseInt(arrLen); 103 | } catch (NumberFormatException e) { 104 | isFixed = false; 105 | } 106 | } 107 | } else { 108 | isArray = false; 109 | isFixed = false; 110 | } 111 | String[] simpleTypes = types[0].split("(?=[0-9])", 2); 112 | id = gsonBuilder.create().fromJson(simpleTypes[0].toUpperCase(), SolidityTypeID.class); 113 | if (simpleTypes.length == 2) 114 | n = Integer.parseInt(simpleTypes[1]); 115 | return new IOElement(name, new SolidityType(id, n, isArray, isFixed, arrayLength)); 116 | } 117 | 118 | /** 119 | * Reads an abi from Json 120 | * @param abi json source 121 | * @param type output class 122 | * @param Output class 123 | * @return Instance of class T obtained by the json source 124 | */ 125 | public T fromJson(String abi, Class type) { 126 | return gson.fromJson(abi, type); 127 | } 128 | 129 | /** 130 | * Prints an object to Json representation 131 | * @param src object to print 132 | * @return json representation 133 | */ 134 | public String toJson(Object src){ 135 | return gson.toJson(src); 136 | } 137 | } 138 | -------------------------------------------------------------------------------- /Abi/src/main/java/ir/IRCfg.java: -------------------------------------------------------------------------------- 1 | package ir; 2 | 3 | import utils.Pair; 4 | 5 | import java.util.ArrayList; 6 | import java.util.List; 7 | 8 | public class IRCfg{ 9 | private final List nodes; 10 | private final List> edges; 11 | private String version; 12 | private long timeMillis; 13 | 14 | public IRCfg() { 15 | this.nodes = new ArrayList<>(); 16 | this.edges = new ArrayList<>(); 17 | this.version = ""; 18 | this.timeMillis = 0; 19 | } 20 | 21 | public void addNode(long offset) { 22 | this.nodes.add(offset); 23 | } 24 | 25 | public void addEdge(long from, long to) { 26 | this.edges.add(new Pair<>(from, to)); 27 | } 28 | 29 | public void setVersion(String version){ 30 | this.version = version; 31 | } 32 | 33 | public void setTimeMillis(long timeMillis) { 34 | this.timeMillis = timeMillis; 35 | } 36 | 37 | public List getNodes() { 38 | return nodes; 39 | } 40 | 41 | public List> getEdges() { 42 | return edges; 43 | } 44 | 45 | public String getVersion() { 46 | return version; 47 | } 48 | 49 | public long getTimeMillis() { 50 | return timeMillis; 51 | } 52 | } -------------------------------------------------------------------------------- /Abi/src/main/java/rebuiltabi/RebuiltAbi.java: -------------------------------------------------------------------------------- 1 | package rebuiltabi; 2 | 3 | import java.util.ArrayList; 4 | 5 | /** 6 | * Class to represent an approximation of the ABI given by the cfg. 7 | * 8 | * It's basically a list of rebuilt functions 9 | */ 10 | public class RebuiltAbi { 11 | private final ArrayList functions; 12 | 13 | /** 14 | * Default constructor which initialize an empty list 15 | */ 16 | public RebuiltAbi(){ 17 | functions = new ArrayList<>(); 18 | } 19 | 20 | /** 21 | * Adds a function 22 | * @param function function to add 23 | */ 24 | public void addFunction(RebuiltAbiFunction function) { 25 | functions.add(function); 26 | } 27 | 28 | /** 29 | * Default getters 30 | * @return iterable object with the functions 31 | */ 32 | public Iterable extends RebuiltAbiFunction> getFunctions() { 33 | return functions; 34 | } 35 | 36 | /** 37 | * Gets the function with a specified hash 38 | * @param hash function hash, first 4 bytes of the keccak256 of the signature 39 | * @return the function if present, null otherwise 40 | */ 41 | public RebuiltAbiFunction getFunction(String hash){ 42 | for (RebuiltAbiFunction function : functions) 43 | if (function.getHash().equals(hash)) 44 | return function; 45 | return null; 46 | } 47 | 48 | /** 49 | * Gets the functions number 50 | * @return functions number 51 | */ 52 | public int getLength() { 53 | return functions.size(); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /Abi/src/main/java/rebuiltabi/RebuiltAbiFunction.java: -------------------------------------------------------------------------------- 1 | package rebuiltabi; 2 | 3 | import abi.fields.FunctionType; 4 | import rebuiltabi.fields.RebuiltIOElement; 5 | 6 | import java.util.ArrayList; 7 | 8 | /** 9 | * Class to represent the rebuilt abi function 10 | * 11 | * It stores: 12 | * 13 | * Hash 14 | * Type 15 | * Inputs 16 | * 17 | */ 18 | public class RebuiltAbiFunction { 19 | private final String hash; 20 | private final FunctionType type; 21 | private final ArrayList inputs; 22 | 23 | /** 24 | * Default constructor with hash and type which initialize an empty list of inputs 25 | * @param hash function hash 26 | * @param type function type 27 | */ 28 | public RebuiltAbiFunction(String hash, FunctionType type){ 29 | this.hash = hash; 30 | this.type = type; 31 | this.inputs = new ArrayList<>(); 32 | } 33 | 34 | /** 35 | * Default getter 36 | * @return function hash 37 | */ 38 | public String getHash() { 39 | return hash; 40 | } 41 | 42 | /** 43 | * Default getter 44 | * @return function type 45 | */ 46 | public FunctionType getType() { 47 | return type; 48 | } 49 | 50 | /** 51 | * Default getter 52 | * @return function hash 53 | */ 54 | public ArrayList getInputs() { 55 | return inputs; 56 | } 57 | 58 | /** 59 | * Adds an input 60 | * @param input input to add 61 | */ 62 | public void addInput(RebuiltIOElement input){ 63 | this.inputs.add(input); 64 | } 65 | 66 | /** 67 | * Removes the last added input 68 | */ 69 | public void popInput() { 70 | this.inputs.remove(this.inputs.size() - 1); 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /Abi/src/main/java/rebuiltabi/fields/RebuiltIOElement.java: -------------------------------------------------------------------------------- 1 | package rebuiltabi.fields; 2 | 3 | /** 4 | * Class to represent a rebuilt element of input/output. 5 | * 6 | * Currently it's used only for inputs. 7 | * It stores: 8 | * 9 | * index 10 | * type 11 | * 12 | */ 13 | public class RebuiltIOElement { 14 | private final int index; 15 | private final RebuiltSolidityType type; 16 | 17 | /** 18 | * Default constructor 19 | * @param index position among inputs 20 | * @param type input type 21 | */ 22 | public RebuiltIOElement(int index, RebuiltSolidityType type) { 23 | this.index = index; 24 | this.type = type; 25 | } 26 | 27 | /** 28 | * String printer 29 | * @return string representation 30 | */ 31 | @Override 32 | public String toString() { 33 | return String.format("arg%d: %s", index, type); 34 | } 35 | 36 | /** 37 | * Default getter 38 | * @return type 39 | */ 40 | public RebuiltSolidityType getType() { 41 | return type; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /Abi/src/main/java/rebuiltabi/fields/RebuiltSolidityType.java: -------------------------------------------------------------------------------- 1 | package rebuiltabi.fields; 2 | 3 | /** 4 | * The rebuilt type can be Simple or Complex. If it's simple the tool tries to retrieve its size in bytes 5 | */ 6 | public class RebuiltSolidityType { 7 | private final RebuiltSolidityTypeID typeID; 8 | private final int n; 9 | 10 | /** 11 | * Default constructor with only type. Default size is 0 12 | * @param typeID type 13 | */ 14 | public RebuiltSolidityType(RebuiltSolidityTypeID typeID){ 15 | this(typeID, 0); 16 | } 17 | 18 | /** 19 | * Default constructor with type and size 20 | * @param typeID type 21 | * @param n size in bytes 22 | */ 23 | public RebuiltSolidityType(RebuiltSolidityTypeID typeID, int n) { 24 | this.typeID = typeID; 25 | this.n = n; 26 | } 27 | 28 | /** 29 | * String representation 30 | * @return string representation 31 | */ 32 | @Override 33 | public String toString() { 34 | return typeID.toString() + (n != 0 ? n : ""); 35 | } 36 | 37 | /** 38 | * Default getter 39 | * @return type (Simple or complex) 40 | */ 41 | public RebuiltSolidityTypeID getTypeID() { 42 | return typeID; 43 | } 44 | 45 | /** 46 | * Default getter 47 | * @return size in bytes 48 | */ 49 | public int getN() { 50 | return n; 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /Abi/src/main/java/rebuiltabi/fields/RebuiltSolidityTypeID.java: -------------------------------------------------------------------------------- 1 | package rebuiltabi.fields; 2 | 3 | public enum RebuiltSolidityTypeID { 4 | SIMPLE, 5 | COMPLEX 6 | } 7 | -------------------------------------------------------------------------------- /Core/build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id 'java' 3 | } 4 | 5 | group 'org.example' 6 | version '1.0-SNAPSHOT' 7 | 8 | sourceCompatibility = 1.8 9 | 10 | repositories { 11 | mavenCentral() 12 | } 13 | 14 | dependencies { 15 | testImplementation 'org.junit.jupiter:junit-jupiter-api:5.3.1' 16 | testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.3.1' 17 | implementation 'com.google.code.gson:gson:2.8.6' 18 | } 19 | 20 | test { 21 | useJUnitPlatform() 22 | } 23 | 24 | task runCoreMain(type: JavaExec) { 25 | group = "Execution" 26 | description = "Run the main class of Core module, which analyses a sample bytecode" 27 | classpath = sourceSets.main.runtimeClasspath 28 | main = "Main" 29 | } 30 | -------------------------------------------------------------------------------- /Core/src/main/java/Main.java: -------------------------------------------------------------------------------- 1 | import parseTree.Contract; 2 | import parseTree.NotSolidityContractException; 3 | import utils.JsonExporter; 4 | import utils.Message; 5 | 6 | import java.io.BufferedWriter; 7 | import java.io.File; 8 | import java.io.FileWriter; 9 | import java.io.IOException; 10 | 11 | public class Main { 12 | public static void main(String[] args) { 13 | String bytecode = "608060405260aa60005534801561001557600080fd5b50610184806100256000396000f3fe608060405234801561001057600080fd5b506004361061004c5760003560e01c80634b3df200146100515780635bfd987d1461006f578063c2985578146100b1578063febb0f7e146100cf575b600080fd5b6100596100ed565b6040518082815260200191505060405180910390f35b61009b6004803603602081101561008557600080fd5b810190808035906020019092919050505061011d565b6040518082815260200191505060405180910390f35b6100b961012a565b6040518082815260200191505060405180910390f35b6100d761013c565b6040518082815260200191505060405180910390f35b6000806000815480929190600101919050555060aa600054141561011557600054905061011a565b600080fd5b90565b6000816088019050919050565b600061013761cccc61011d565b905090565b600061014961dddd61011d565b90509056fea2646970667358221220e619b234c1887f9b10b567ee21364dbf523a19001c8c47a33049907c0398563164736f6c63430006040033"; 14 | try { 15 | Contract contract = new Contract("Sample", bytecode); 16 | String json = new JsonExporter().toJson(contract); 17 | File file = new File("../outputs/json/" + contract.getContractHash() + ".json"); 18 | if (file.getParentFile().mkdirs()) 19 | Message.printDebug("Output folder will be created"); 20 | try (BufferedWriter out = new BufferedWriter(new FileWriter(file))) { 21 | out.write(json); 22 | System.out.println("Contract analysis exported in " + file.getCanonicalPath()); 23 | } catch (IOException e) { 24 | System.err.format("Error writing file %s: %s%n", contract.getContractHash(), e); 25 | e.printStackTrace(); 26 | } 27 | } catch (NotSolidityContractException e) { 28 | e.printStackTrace(); 29 | } 30 | } 31 | } -------------------------------------------------------------------------------- /Core/src/main/java/SolidityInfo/SolidityVersion.java: -------------------------------------------------------------------------------- 1 | package SolidityInfo; 2 | 3 | public enum SolidityVersion { 4 | UNKNOWN, 5 | FROM_0_4_17_TO_0_5_8, 6 | FROM_0_5_9_TO_0_5_11, 7 | FROM_0_5_12_TO_0_5_15, 8 | FROM_0_4_17_TO_0_5_8_EXPERIMENTAL, 9 | FROM_0_5_9_TO_0_5_11_EXPERIMENTAL, 10 | FROM_0_5_12_TO_0_5_15_EXPERIMENTAL, 11 | FROM_0_6_0_TO_0_6_1, 12 | FROM_0_6_2_TO_LATEST 13 | } 14 | -------------------------------------------------------------------------------- /Core/src/main/java/SolidityInfo/SolidityVersionUnknownException.java: -------------------------------------------------------------------------------- 1 | package SolidityInfo; 2 | 3 | public class SolidityVersionUnknownException extends Exception { 4 | public SolidityVersionUnknownException(String s) { 5 | super(s); 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /Core/src/main/java/opcodes/ArithmeticOpcode.java: -------------------------------------------------------------------------------- 1 | package opcodes; 2 | 3 | public abstract class ArithmeticOpcode extends Opcode { 4 | public ArithmeticOpcode(OpcodeID opcodeID) { 5 | super(opcodeID); 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /Core/src/main/java/opcodes/BlockOpcode.java: -------------------------------------------------------------------------------- 1 | package opcodes; 2 | 3 | public abstract class BlockOpcode extends Opcode { 4 | protected BlockOpcode(OpcodeID opcodeID) { 5 | super(opcodeID); 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /Core/src/main/java/opcodes/ControlFlowOpcode.java: -------------------------------------------------------------------------------- 1 | package opcodes; 2 | 3 | public abstract class ControlFlowOpcode extends Opcode{ 4 | protected ControlFlowOpcode(OpcodeID opcodeID) { 5 | super(opcodeID); 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /Core/src/main/java/opcodes/EnvironmentalOpcode.java: -------------------------------------------------------------------------------- 1 | package opcodes; 2 | 3 | public abstract class EnvironmentalOpcode extends Opcode { 4 | protected EnvironmentalOpcode(OpcodeID opcodeID) { 5 | super(opcodeID); 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /Core/src/main/java/opcodes/InvalidOpcode.java: -------------------------------------------------------------------------------- 1 | package opcodes; 2 | 3 | public class InvalidOpcode extends Opcode { 4 | 5 | private final byte realOpcode; 6 | 7 | public InvalidOpcode(long offset, byte realOpcode) { 8 | super(OpcodeID.INVALID); 9 | this.offset = offset; 10 | this.realOpcode = realOpcode; 11 | } 12 | 13 | @Override 14 | public int getStackGenerated() { 15 | return 0; 16 | } 17 | 18 | @Override 19 | public int getStackConsumed() { 20 | return 0; 21 | } 22 | 23 | @Override 24 | public String getBytes() { 25 | return String.format("%02x", realOpcode); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /Core/src/main/java/opcodes/LogOpcode.java: -------------------------------------------------------------------------------- 1 | package opcodes; 2 | 3 | public class LogOpcode extends Opcode { 4 | 5 | private final int topicNumber; 6 | 7 | /** 8 | * Basic constructor for all LOG opcodes. 9 | * @param offset the offset in the bytecode, expressed in bytes. 10 | * @param topic_number the number of the event's topics. It must be between 0 and 4. 11 | */ 12 | public LogOpcode(long offset, int topic_number) { 13 | super(OpcodeID.LOG); 14 | if (topic_number < 0 || topic_number > 4) 15 | throw new IllegalArgumentException("Events can have up to 4 topics"); 16 | this.offset = offset; 17 | this.topicNumber = topic_number; 18 | } 19 | 20 | @Override 21 | public int getStackConsumed() { 22 | return 2 + topicNumber; 23 | } 24 | 25 | @Override 26 | public int getStackGenerated() { 27 | return 0; 28 | } 29 | 30 | @Override 31 | public String toString() { 32 | return super.toString() + topicNumber; 33 | } 34 | 35 | @Override 36 | public String getBytes() { 37 | byte opcode = (byte) (opcodeID.getOpcode() + topicNumber); 38 | return String.format("%02x", opcode); 39 | } 40 | 41 | @Override 42 | public boolean isSameOpcode(Opcode other) { 43 | return super.isSameOpcode(other) && ((LogOpcode) other).topicNumber == this.topicNumber; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /Core/src/main/java/opcodes/Opcode.java: -------------------------------------------------------------------------------- 1 | package opcodes; 2 | 3 | public abstract class Opcode { 4 | protected final OpcodeID opcodeID; 5 | protected long offset; 6 | 7 | protected Opcode(OpcodeID opcodeID) { 8 | this.opcodeID = opcodeID; 9 | } 10 | 11 | /** 12 | * Get the bytecode length of the opcode. 13 | * 14 | * Default value is 1, but the PUSH statement overrides this method. 15 | * @return length in byte of the opcode. 16 | */ 17 | public int getLength(){ 18 | return 1; 19 | } 20 | 21 | 22 | /** 23 | * Get the number of elements that the opcode consumes. They have to be already in the stack. 24 | * @return consumed stack elements. 25 | */ 26 | public abstract int getStackConsumed(); 27 | 28 | /** 29 | * Get the number of elements that the opcode generates on the stack. 30 | * 31 | * Default value is 1, but some opcodes override this method 32 | * @return generated stack elements. 33 | */ 34 | public int getStackGenerated(){ 35 | return 1; 36 | } 37 | 38 | /** 39 | * Default getter for opcodeID 40 | * @return opcodeID 41 | */ 42 | public OpcodeID getOpcodeID() { 43 | return opcodeID; 44 | } 45 | 46 | /** 47 | * Default getter for Name 48 | * @return name of the opcode 49 | */ 50 | public String getName() { 51 | return opcodeID.getName(); 52 | } 53 | 54 | /** 55 | * Assembles the opcode giving the bytes representation 56 | * @return bytes representation 57 | */ 58 | public String getBytes() { 59 | return String.format("%02x", opcodeID.getOpcode()); 60 | } 61 | 62 | /** 63 | * Default getter for the offset, the position in the code 64 | * @return offset of the opcode 65 | */ 66 | public long getOffset() { 67 | return offset; 68 | } 69 | 70 | /** 71 | * String representation of the opcode, with offset and name 72 | * 73 | * e.g. "0: PUSH1 60" 74 | * @return "offset: opcode" 75 | */ 76 | @Override 77 | public String toString() { 78 | return offset + ": " + opcodeID.getName(); 79 | } 80 | 81 | /** 82 | * Checks whether the other opcode represents the same one, even if with a different offset 83 | * @param other opcode to test 84 | * @return if they represents the same opcode 85 | */ 86 | public boolean isSameOpcode(Opcode other){ 87 | return this.opcodeID == other.opcodeID; 88 | } 89 | 90 | /** 91 | * Two opcodes are equals iff they have the same opcodeID and offset 92 | * @param o other object to test 93 | * @return if they are equals 94 | */ 95 | @Override 96 | public boolean equals(Object o) { 97 | if (this == o) return true; 98 | if (o == null || getClass() != o.getClass()) return false; 99 | Opcode opcode = (Opcode) o; 100 | return offset == opcode.offset && opcodeID == opcode.opcodeID; 101 | } 102 | 103 | /** 104 | * Default hashcode. It's calculated as a xor between opcodeID hashcode and the offset 105 | * @return hashcode 106 | */ 107 | @Override 108 | public int hashCode() { 109 | return (int) (opcodeID.hashCode() ^ offset); 110 | } 111 | } 112 | -------------------------------------------------------------------------------- /Core/src/main/java/opcodes/OpcodeID.java: -------------------------------------------------------------------------------- 1 | package opcodes; 2 | 3 | public enum OpcodeID { 4 | 5 | STOP ((byte) 0x00,"STOP"), 6 | ADD ((byte) 0x01,"ADD"), 7 | MUL ((byte) 0x02,"MUL"), 8 | SUB ((byte) 0x03,"SUB"), 9 | DIV ((byte) 0x04,"DIV"), 10 | SDIV ((byte) 0x05,"SDIV"), 11 | MOD ((byte) 0x06,"MOD"), 12 | SMOD ((byte) 0x07,"SMOD"), 13 | ADDMOD ((byte) 0x08,"ADDMOD"), 14 | MULMOD ((byte) 0x09,"MULMOD"), 15 | EXP ((byte) 0x0a,"EXP"), 16 | SIGNEXTEND ((byte) 0x0b,"SIGNEXTEND"), 17 | LT ((byte) 0x10,"LT"), 18 | GT ((byte) 0x11,"GT"), 19 | SLT ((byte) 0x12,"SLT"), 20 | SGT ((byte) 0x13,"SGT"), 21 | EQ ((byte) 0x14,"EQ"), 22 | ISZERO ((byte) 0x15,"ISZERO"), 23 | AND ((byte) 0x16,"AND"), 24 | OR ((byte) 0x17,"OR"), 25 | XOR ((byte) 0x18,"XOR"), 26 | NOT ((byte) 0x19,"NOT"), 27 | BYTE ((byte) 0x1a,"BYTE"), 28 | SHL ((byte) 0x1b, "SHL"), 29 | SHR ((byte) 0x1c, "SHR"), 30 | SAR ((byte) 0x1d, "SAR"), 31 | SHA3 ((byte) 0x20,"SHA3"), 32 | ADDRESS ((byte) 0x30,"ADDRESS"), 33 | BALANCE ((byte) 0x31,"BALANCE"), 34 | ORIGIN ((byte) 0x32,"ORIGIN"), 35 | CALLER ((byte) 0x33,"CALLER"), 36 | CALLVALUE ((byte) 0x34,"CALLVALUE"), 37 | CALLDATALOAD ((byte) 0x35,"CALLDATALOAD"), 38 | CALLDATASIZE ((byte) 0x36,"CALLDATASIZE"), 39 | CALLDATACOPY ((byte) 0x37,"CALLDATACOPY"), 40 | CODESIZE ((byte) 0x38,"CODESIZE"), 41 | CODECOPY ((byte) 0x39,"CODECOPY"), 42 | GASPRICE ((byte) 0x3a,"GASPRICE"), 43 | EXTCODESIZE ((byte) 0x3b,"EXTCODESIZE"), 44 | EXTCODECOPY ((byte) 0x3c,"EXTCODECOPY"), 45 | RETURNDATASIZE ((byte) 0x3d,"RETURNDATASIZE"), 46 | RETURNDATACOPY ((byte) 0x3e,"RETURNDATACOPY"), 47 | EXTCODEHASH ((byte) 0x3f, "EXTCODEHASH"), 48 | BLOCKHASH ((byte) 0x40,"BLOCKHASH"), 49 | COINBASE ((byte) 0x41,"COINBASE"), 50 | TIMESTAMP ((byte) 0x42,"TIMESTAMP"), 51 | NUMBER ((byte) 0x43,"NUMBER"), 52 | DIFFICULTY ((byte) 0x44,"DIFFICULTY"), 53 | GASLIMIT ((byte) 0x45,"GASLIMIT"), 54 | CHAINID ((byte) 0x46, "CHAINID"), 55 | SELFBALANCE ((byte) 0x47, "SELFBALANCE"), 56 | POP ((byte) 0x50,"POP"), 57 | MLOAD ((byte) 0x51,"MLOAD"), 58 | MSTORE ((byte) 0x52,"MSTORE"), 59 | MSTORE8 ((byte) 0x53,"MSTORE8"), 60 | SLOAD ((byte) 0x54,"SLOAD"), 61 | SSTORE ((byte) 0x55,"SSTORE"), 62 | JUMP ((byte) 0x56,"JUMP"), 63 | JUMPI ((byte) 0x57,"JUMPI"), 64 | PC ((byte) 0x58,"PC"), 65 | MSIZE ((byte) 0x59,"MSIZE"), 66 | GAS ((byte) 0x5a,"GAS"), 67 | JUMPDEST ((byte) 0x5b,"JUMPDEST"), 68 | PUSH ((byte) 0x60,"PUSH"), 69 | DUP ((byte) 0x80,"DUP"), 70 | SWAP ((byte) 0x90,"SWAP"), 71 | LOG ((byte) 0xa0,"LOG"), 72 | CREATE ((byte) 0xf0,"CREATE"), 73 | CALL ((byte) 0xf1,"CALL"), 74 | CALLCODE ((byte) 0xf2,"CALLCODE"), 75 | RETURN ((byte) 0xf3,"RETURN"), 76 | DELEGATECALL ((byte) 0xf4,"DELEGATECALL"), 77 | STATICCALL ((byte) 0xfa,"STATICCALL"), 78 | REVERT ((byte) 0xfd,"REVERT"), 79 | INVALID ((byte) 0xfe,"INVALID"), 80 | SELFDESTRUCT ((byte) 0xff,"SELFDESTRUCT"); 81 | 82 | private final byte opcode; 83 | private final String name; 84 | 85 | OpcodeID(byte opcode, String name) { 86 | this.opcode = opcode; 87 | this.name = name; 88 | } 89 | 90 | public byte getOpcode() { 91 | return opcode; 92 | } 93 | 94 | public String getName() { 95 | return name; 96 | } 97 | 98 | @Override 99 | public String toString() { 100 | return name; 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /Core/src/main/java/opcodes/StackOpcode.java: -------------------------------------------------------------------------------- 1 | package opcodes; 2 | 3 | public abstract class StackOpcode extends Opcode { 4 | protected StackOpcode(OpcodeID opcodeID) { 5 | super(opcodeID); 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /Core/src/main/java/opcodes/SystemOpcode.java: -------------------------------------------------------------------------------- 1 | package opcodes; 2 | 3 | public abstract class SystemOpcode extends Opcode { 4 | protected SystemOpcode(OpcodeID opcodeID) { 5 | super(opcodeID); 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /Core/src/main/java/opcodes/arithmeticOpcodes/BinaryArithmeticOpcode.java: -------------------------------------------------------------------------------- 1 | package opcodes.arithmeticOpcodes; 2 | 3 | import opcodes.ArithmeticOpcode; 4 | import opcodes.OpcodeID; 5 | 6 | public abstract class BinaryArithmeticOpcode extends ArithmeticOpcode { 7 | public BinaryArithmeticOpcode(OpcodeID opcodeID) { 8 | super(opcodeID); 9 | } 10 | 11 | @Override 12 | public int getStackConsumed() { 13 | return 2; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Core/src/main/java/opcodes/arithmeticOpcodes/TernaryArithmeticOpcode.java: -------------------------------------------------------------------------------- 1 | package opcodes.arithmeticOpcodes; 2 | 3 | import opcodes.ArithmeticOpcode; 4 | import opcodes.OpcodeID; 5 | 6 | public abstract class TernaryArithmeticOpcode extends ArithmeticOpcode { 7 | public TernaryArithmeticOpcode(OpcodeID opcodeID) { 8 | super(opcodeID); 9 | } 10 | 11 | @Override 12 | public int getStackConsumed() { 13 | return 3; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Core/src/main/java/opcodes/arithmeticOpcodes/UnaryArithmeticOpcode.java: -------------------------------------------------------------------------------- 1 | package opcodes.arithmeticOpcodes; 2 | 3 | import opcodes.ArithmeticOpcode; 4 | import opcodes.OpcodeID; 5 | 6 | public abstract class UnaryArithmeticOpcode extends ArithmeticOpcode { 7 | public UnaryArithmeticOpcode(OpcodeID opcodeID) { 8 | super(opcodeID); 9 | } 10 | 11 | @Override 12 | public int getStackConsumed() { 13 | return 1; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Core/src/main/java/opcodes/arithmeticOpcodes/binaryArithmeticOpcodes/AddOpcode.java: -------------------------------------------------------------------------------- 1 | package opcodes.arithmeticOpcodes.binaryArithmeticOpcodes; 2 | 3 | import opcodes.OpcodeID; 4 | import opcodes.arithmeticOpcodes.BinaryArithmeticOpcode; 5 | 6 | public class AddOpcode extends BinaryArithmeticOpcode { 7 | public AddOpcode(long offset) { 8 | super(OpcodeID.ADD); 9 | this.offset = offset; 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /Core/src/main/java/opcodes/arithmeticOpcodes/binaryArithmeticOpcodes/AndOpcode.java: -------------------------------------------------------------------------------- 1 | package opcodes.arithmeticOpcodes.binaryArithmeticOpcodes; 2 | 3 | import opcodes.OpcodeID; 4 | import opcodes.arithmeticOpcodes.BinaryArithmeticOpcode; 5 | 6 | public class AndOpcode extends BinaryArithmeticOpcode { 7 | public AndOpcode(long offset) { 8 | super(OpcodeID.AND); 9 | this.offset = offset; 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /Core/src/main/java/opcodes/arithmeticOpcodes/binaryArithmeticOpcodes/ByteOpcode.java: -------------------------------------------------------------------------------- 1 | package opcodes.arithmeticOpcodes.binaryArithmeticOpcodes; 2 | 3 | import opcodes.OpcodeID; 4 | import opcodes.arithmeticOpcodes.BinaryArithmeticOpcode; 5 | 6 | public class ByteOpcode extends BinaryArithmeticOpcode { 7 | public ByteOpcode(long offset) { 8 | super(OpcodeID.BYTE); 9 | this.offset = offset; 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /Core/src/main/java/opcodes/arithmeticOpcodes/binaryArithmeticOpcodes/DivOpcode.java: -------------------------------------------------------------------------------- 1 | package opcodes.arithmeticOpcodes.binaryArithmeticOpcodes; 2 | 3 | import opcodes.OpcodeID; 4 | import opcodes.arithmeticOpcodes.BinaryArithmeticOpcode; 5 | 6 | public class DivOpcode extends BinaryArithmeticOpcode { 7 | public DivOpcode(long offset) { 8 | super(OpcodeID.DIV); 9 | this.offset = offset; 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /Core/src/main/java/opcodes/arithmeticOpcodes/binaryArithmeticOpcodes/EQOpcode.java: -------------------------------------------------------------------------------- 1 | package opcodes.arithmeticOpcodes.binaryArithmeticOpcodes; 2 | 3 | import opcodes.OpcodeID; 4 | import opcodes.arithmeticOpcodes.BinaryArithmeticOpcode; 5 | 6 | public class EQOpcode extends BinaryArithmeticOpcode { 7 | public EQOpcode(long offset) { 8 | super(OpcodeID.EQ); 9 | this.offset = offset; 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /Core/src/main/java/opcodes/arithmeticOpcodes/binaryArithmeticOpcodes/ExpOpcode.java: -------------------------------------------------------------------------------- 1 | package opcodes.arithmeticOpcodes.binaryArithmeticOpcodes; 2 | 3 | import opcodes.OpcodeID; 4 | import opcodes.arithmeticOpcodes.BinaryArithmeticOpcode; 5 | 6 | public class ExpOpcode extends BinaryArithmeticOpcode { 7 | public ExpOpcode(long offset) { 8 | super(OpcodeID.EXP); 9 | this.offset = offset; 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /Core/src/main/java/opcodes/arithmeticOpcodes/binaryArithmeticOpcodes/GTOpcode.java: -------------------------------------------------------------------------------- 1 | package opcodes.arithmeticOpcodes.binaryArithmeticOpcodes; 2 | 3 | import opcodes.OpcodeID; 4 | import opcodes.arithmeticOpcodes.BinaryArithmeticOpcode; 5 | 6 | public class GTOpcode extends BinaryArithmeticOpcode { 7 | public GTOpcode(long offset) { 8 | super(OpcodeID.GT); 9 | this.offset = offset; 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /Core/src/main/java/opcodes/arithmeticOpcodes/binaryArithmeticOpcodes/LTOpcode.java: -------------------------------------------------------------------------------- 1 | package opcodes.arithmeticOpcodes.binaryArithmeticOpcodes; 2 | 3 | import opcodes.OpcodeID; 4 | import opcodes.arithmeticOpcodes.BinaryArithmeticOpcode; 5 | 6 | public class LTOpcode extends BinaryArithmeticOpcode { 7 | 8 | public LTOpcode(long offset) { 9 | super(OpcodeID.LT); 10 | this.offset = offset; 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Core/src/main/java/opcodes/arithmeticOpcodes/binaryArithmeticOpcodes/ModOpcode.java: -------------------------------------------------------------------------------- 1 | package opcodes.arithmeticOpcodes.binaryArithmeticOpcodes; 2 | 3 | import opcodes.OpcodeID; 4 | import opcodes.arithmeticOpcodes.BinaryArithmeticOpcode; 5 | 6 | public class ModOpcode extends BinaryArithmeticOpcode { 7 | public ModOpcode(long offset) { 8 | super(OpcodeID.MOD); 9 | this.offset = offset; 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /Core/src/main/java/opcodes/arithmeticOpcodes/binaryArithmeticOpcodes/MulOpcode.java: -------------------------------------------------------------------------------- 1 | package opcodes.arithmeticOpcodes.binaryArithmeticOpcodes; 2 | 3 | import opcodes.OpcodeID; 4 | import opcodes.arithmeticOpcodes.BinaryArithmeticOpcode; 5 | 6 | public class MulOpcode extends BinaryArithmeticOpcode { 7 | public MulOpcode(long offset) { 8 | super(OpcodeID.MUL); 9 | this.offset = offset; 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /Core/src/main/java/opcodes/arithmeticOpcodes/binaryArithmeticOpcodes/OrOpcode.java: -------------------------------------------------------------------------------- 1 | package opcodes.arithmeticOpcodes.binaryArithmeticOpcodes; 2 | 3 | import opcodes.OpcodeID; 4 | import opcodes.arithmeticOpcodes.BinaryArithmeticOpcode; 5 | 6 | public class OrOpcode extends BinaryArithmeticOpcode { 7 | public OrOpcode(long offset) { 8 | super(OpcodeID.OR); 9 | this.offset = offset; 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /Core/src/main/java/opcodes/arithmeticOpcodes/binaryArithmeticOpcodes/SAROpcode.java: -------------------------------------------------------------------------------- 1 | package opcodes.arithmeticOpcodes.binaryArithmeticOpcodes; 2 | 3 | import opcodes.OpcodeID; 4 | import opcodes.arithmeticOpcodes.BinaryArithmeticOpcode; 5 | 6 | public class SAROpcode extends BinaryArithmeticOpcode { 7 | public SAROpcode(long offset) { 8 | super(OpcodeID.SAR); 9 | this.offset = offset; 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /Core/src/main/java/opcodes/arithmeticOpcodes/binaryArithmeticOpcodes/SDivOpcode.java: -------------------------------------------------------------------------------- 1 | package opcodes.arithmeticOpcodes.binaryArithmeticOpcodes; 2 | 3 | import opcodes.OpcodeID; 4 | import opcodes.arithmeticOpcodes.BinaryArithmeticOpcode; 5 | 6 | public class SDivOpcode extends BinaryArithmeticOpcode { 7 | public SDivOpcode(long offset) { 8 | super(OpcodeID.SDIV); 9 | this.offset = offset; 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /Core/src/main/java/opcodes/arithmeticOpcodes/binaryArithmeticOpcodes/SGTOpcode.java: -------------------------------------------------------------------------------- 1 | package opcodes.arithmeticOpcodes.binaryArithmeticOpcodes; 2 | 3 | import opcodes.OpcodeID; 4 | import opcodes.arithmeticOpcodes.BinaryArithmeticOpcode; 5 | 6 | public class SGTOpcode extends BinaryArithmeticOpcode { 7 | public SGTOpcode(long offset) { 8 | super(OpcodeID.SGT); 9 | this.offset = offset; 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /Core/src/main/java/opcodes/arithmeticOpcodes/binaryArithmeticOpcodes/SHA3Opcode.java: -------------------------------------------------------------------------------- 1 | package opcodes.arithmeticOpcodes.binaryArithmeticOpcodes; 2 | 3 | import opcodes.OpcodeID; 4 | import opcodes.arithmeticOpcodes.BinaryArithmeticOpcode; 5 | 6 | public class SHA3Opcode extends BinaryArithmeticOpcode { 7 | public SHA3Opcode(long offset) { 8 | super(OpcodeID.SHA3); 9 | this.offset = offset; 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /Core/src/main/java/opcodes/arithmeticOpcodes/binaryArithmeticOpcodes/SHLOpcode.java: -------------------------------------------------------------------------------- 1 | package opcodes.arithmeticOpcodes.binaryArithmeticOpcodes; 2 | 3 | import opcodes.OpcodeID; 4 | import opcodes.arithmeticOpcodes.BinaryArithmeticOpcode; 5 | 6 | public class SHLOpcode extends BinaryArithmeticOpcode { 7 | public SHLOpcode(long offset) { 8 | super(OpcodeID.SHL); 9 | this.offset = offset; 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /Core/src/main/java/opcodes/arithmeticOpcodes/binaryArithmeticOpcodes/SHROpcode.java: -------------------------------------------------------------------------------- 1 | package opcodes.arithmeticOpcodes.binaryArithmeticOpcodes; 2 | 3 | import opcodes.OpcodeID; 4 | import opcodes.arithmeticOpcodes.BinaryArithmeticOpcode; 5 | 6 | public class SHROpcode extends BinaryArithmeticOpcode { 7 | public SHROpcode(long offset) { 8 | super(OpcodeID.SHR); 9 | this.offset = offset; 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /Core/src/main/java/opcodes/arithmeticOpcodes/binaryArithmeticOpcodes/SLTOpcode.java: -------------------------------------------------------------------------------- 1 | package opcodes.arithmeticOpcodes.binaryArithmeticOpcodes; 2 | 3 | import opcodes.OpcodeID; 4 | import opcodes.arithmeticOpcodes.BinaryArithmeticOpcode; 5 | 6 | public class SLTOpcode extends BinaryArithmeticOpcode { 7 | public SLTOpcode(long offset) { 8 | super(OpcodeID.SLT); 9 | this.offset = offset; 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /Core/src/main/java/opcodes/arithmeticOpcodes/binaryArithmeticOpcodes/SModOpcode.java: -------------------------------------------------------------------------------- 1 | package opcodes.arithmeticOpcodes.binaryArithmeticOpcodes; 2 | 3 | import opcodes.OpcodeID; 4 | import opcodes.arithmeticOpcodes.BinaryArithmeticOpcode; 5 | 6 | public class SModOpcode extends BinaryArithmeticOpcode { 7 | public SModOpcode(long offset) { 8 | super(OpcodeID.SMOD); 9 | this.offset = offset; 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /Core/src/main/java/opcodes/arithmeticOpcodes/binaryArithmeticOpcodes/SignExtendOpcode.java: -------------------------------------------------------------------------------- 1 | package opcodes.arithmeticOpcodes.binaryArithmeticOpcodes; 2 | 3 | import opcodes.OpcodeID; 4 | import opcodes.arithmeticOpcodes.BinaryArithmeticOpcode; 5 | 6 | public class SignExtendOpcode extends BinaryArithmeticOpcode { 7 | public SignExtendOpcode(long offset) { 8 | super(OpcodeID.SIGNEXTEND); 9 | this.offset = offset; 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /Core/src/main/java/opcodes/arithmeticOpcodes/binaryArithmeticOpcodes/SubOpcode.java: -------------------------------------------------------------------------------- 1 | package opcodes.arithmeticOpcodes.binaryArithmeticOpcodes; 2 | 3 | import opcodes.OpcodeID; 4 | import opcodes.arithmeticOpcodes.BinaryArithmeticOpcode; 5 | 6 | public class SubOpcode extends BinaryArithmeticOpcode { 7 | public SubOpcode(long offset) { 8 | super(OpcodeID.SUB); 9 | this.offset = offset; 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /Core/src/main/java/opcodes/arithmeticOpcodes/binaryArithmeticOpcodes/XorOpcode.java: -------------------------------------------------------------------------------- 1 | package opcodes.arithmeticOpcodes.binaryArithmeticOpcodes; 2 | 3 | import opcodes.OpcodeID; 4 | import opcodes.arithmeticOpcodes.BinaryArithmeticOpcode; 5 | 6 | public class XorOpcode extends BinaryArithmeticOpcode { 7 | public XorOpcode(long offset) { 8 | super(OpcodeID.XOR); 9 | this.offset = offset; 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /Core/src/main/java/opcodes/arithmeticOpcodes/ternaryArithmeticOpcodes/AddModOpcode.java: -------------------------------------------------------------------------------- 1 | package opcodes.arithmeticOpcodes.ternaryArithmeticOpcodes; 2 | 3 | import opcodes.OpcodeID; 4 | import opcodes.arithmeticOpcodes.TernaryArithmeticOpcode; 5 | 6 | public class AddModOpcode extends TernaryArithmeticOpcode { 7 | public AddModOpcode(long offset) { 8 | super(OpcodeID.ADDMOD); 9 | this.offset = offset; 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /Core/src/main/java/opcodes/arithmeticOpcodes/ternaryArithmeticOpcodes/MulModOpcode.java: -------------------------------------------------------------------------------- 1 | package opcodes.arithmeticOpcodes.ternaryArithmeticOpcodes; 2 | 3 | import opcodes.OpcodeID; 4 | import opcodes.arithmeticOpcodes.TernaryArithmeticOpcode; 5 | 6 | public class MulModOpcode extends TernaryArithmeticOpcode { 7 | public MulModOpcode(long offset) { 8 | super(OpcodeID.MULMOD); 9 | this.offset = offset; 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /Core/src/main/java/opcodes/arithmeticOpcodes/unaryArithmeticOpcodes/IsZeroOpcode.java: -------------------------------------------------------------------------------- 1 | package opcodes.arithmeticOpcodes.unaryArithmeticOpcodes; 2 | 3 | import opcodes.OpcodeID; 4 | import opcodes.arithmeticOpcodes.UnaryArithmeticOpcode; 5 | 6 | public class IsZeroOpcode extends UnaryArithmeticOpcode { 7 | public IsZeroOpcode(long offset) { 8 | super(OpcodeID.ISZERO); 9 | this.offset = offset; 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /Core/src/main/java/opcodes/arithmeticOpcodes/unaryArithmeticOpcodes/NotOpcode.java: -------------------------------------------------------------------------------- 1 | package opcodes.arithmeticOpcodes.unaryArithmeticOpcodes; 2 | 3 | import opcodes.OpcodeID; 4 | import opcodes.arithmeticOpcodes.UnaryArithmeticOpcode; 5 | 6 | public class NotOpcode extends UnaryArithmeticOpcode { 7 | public NotOpcode(long offset) { 8 | super(OpcodeID.NOT); 9 | this.offset = offset; 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /Core/src/main/java/opcodes/blockOpcodes/BlockHashOpcode.java: -------------------------------------------------------------------------------- 1 | package opcodes.blockOpcodes; 2 | 3 | import opcodes.BlockOpcode; 4 | import opcodes.OpcodeID; 5 | 6 | public class BlockHashOpcode extends BlockOpcode { 7 | 8 | public BlockHashOpcode(long offset) { 9 | super(OpcodeID.BLOCKHASH); 10 | this.offset = offset; 11 | } 12 | 13 | @Override 14 | public int getStackConsumed() { 15 | return 1; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Core/src/main/java/opcodes/blockOpcodes/ChainIdOpcode.java: -------------------------------------------------------------------------------- 1 | package opcodes.blockOpcodes; 2 | 3 | import opcodes.BlockOpcode; 4 | import opcodes.OpcodeID; 5 | 6 | public class ChainIdOpcode extends BlockOpcode { 7 | public ChainIdOpcode(long offset){ 8 | super(OpcodeID.CHAINID); 9 | this.offset = offset; 10 | } 11 | 12 | @Override 13 | public int getStackConsumed() { 14 | return 0; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /Core/src/main/java/opcodes/blockOpcodes/CoinBaseOpcode.java: -------------------------------------------------------------------------------- 1 | package opcodes.blockOpcodes; 2 | 3 | import opcodes.BlockOpcode; 4 | import opcodes.OpcodeID; 5 | 6 | public class CoinBaseOpcode extends BlockOpcode { 7 | 8 | public CoinBaseOpcode(long offset) { 9 | super(OpcodeID.COINBASE); 10 | this.offset = offset; 11 | } 12 | 13 | @Override 14 | public int getStackConsumed() { 15 | return 0; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Core/src/main/java/opcodes/blockOpcodes/DifficultyOpcode.java: -------------------------------------------------------------------------------- 1 | package opcodes.blockOpcodes; 2 | 3 | import opcodes.BlockOpcode; 4 | import opcodes.OpcodeID; 5 | 6 | public class DifficultyOpcode extends BlockOpcode { 7 | 8 | public DifficultyOpcode(long offset) { 9 | super(OpcodeID.DIFFICULTY); 10 | this.offset = offset; 11 | } 12 | 13 | @Override 14 | public int getStackConsumed() { 15 | return 0; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Core/src/main/java/opcodes/blockOpcodes/GasLimitOpcode.java: -------------------------------------------------------------------------------- 1 | package opcodes.blockOpcodes; 2 | 3 | import opcodes.BlockOpcode; 4 | import opcodes.OpcodeID; 5 | 6 | public class GasLimitOpcode extends BlockOpcode { 7 | 8 | public GasLimitOpcode(long offset) { 9 | super(OpcodeID.GASLIMIT); 10 | this.offset = offset; 11 | } 12 | 13 | @Override 14 | public int getStackConsumed() { 15 | return 0; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Core/src/main/java/opcodes/blockOpcodes/NumberOpcode.java: -------------------------------------------------------------------------------- 1 | package opcodes.blockOpcodes; 2 | 3 | import opcodes.BlockOpcode; 4 | import opcodes.OpcodeID; 5 | 6 | public class NumberOpcode extends BlockOpcode { 7 | 8 | public NumberOpcode(long offset) { 9 | super(OpcodeID.NUMBER); 10 | this.offset = offset; 11 | } 12 | 13 | @Override 14 | public int getStackConsumed() { 15 | return 0; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Core/src/main/java/opcodes/blockOpcodes/TimeStampOpcode.java: -------------------------------------------------------------------------------- 1 | package opcodes.blockOpcodes; 2 | 3 | import opcodes.BlockOpcode; 4 | import opcodes.OpcodeID; 5 | 6 | public class TimeStampOpcode extends BlockOpcode { 7 | 8 | public TimeStampOpcode(long offset) { 9 | super(OpcodeID.TIMESTAMP); 10 | this.offset = offset; 11 | } 12 | 13 | @Override 14 | public int getStackConsumed() { 15 | return 0; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Core/src/main/java/opcodes/controlFlowOpcodes/JumpDestOpcode.java: -------------------------------------------------------------------------------- 1 | package opcodes.controlFlowOpcodes; 2 | 3 | import opcodes.ControlFlowOpcode; 4 | import opcodes.OpcodeID; 5 | 6 | public class JumpDestOpcode extends ControlFlowOpcode { 7 | 8 | public JumpDestOpcode(long offset) { 9 | super(OpcodeID.JUMPDEST); 10 | this.offset = offset; 11 | } 12 | 13 | @Override 14 | public int getStackGenerated() { 15 | return 0; 16 | } 17 | 18 | @Override 19 | public int getStackConsumed() { 20 | return 0; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Core/src/main/java/opcodes/controlFlowOpcodes/JumpIOpcode.java: -------------------------------------------------------------------------------- 1 | package opcodes.controlFlowOpcodes; 2 | 3 | import opcodes.ControlFlowOpcode; 4 | import opcodes.OpcodeID; 5 | 6 | public class JumpIOpcode extends ControlFlowOpcode { 7 | 8 | public JumpIOpcode(long offset) { 9 | super(OpcodeID.JUMPI); 10 | this.offset = offset; 11 | } 12 | 13 | @Override 14 | public int getStackGenerated() { 15 | return 0; 16 | } 17 | 18 | @Override 19 | public int getStackConsumed() { 20 | return 2; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Core/src/main/java/opcodes/controlFlowOpcodes/JumpOpcode.java: -------------------------------------------------------------------------------- 1 | package opcodes.controlFlowOpcodes; 2 | 3 | import opcodes.ControlFlowOpcode; 4 | import opcodes.OpcodeID; 5 | 6 | public class JumpOpcode extends ControlFlowOpcode { 7 | 8 | public JumpOpcode(long offset) { 9 | super(OpcodeID.JUMP); 10 | this.offset = offset; 11 | } 12 | 13 | @Override 14 | public int getStackGenerated() { 15 | return 0; 16 | } 17 | 18 | @Override 19 | public int getStackConsumed() { 20 | return 1; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Core/src/main/java/opcodes/controlFlowOpcodes/StopOpcode.java: -------------------------------------------------------------------------------- 1 | package opcodes.controlFlowOpcodes; 2 | 3 | import opcodes.ControlFlowOpcode; 4 | import opcodes.OpcodeID; 5 | 6 | public class StopOpcode extends ControlFlowOpcode { 7 | 8 | public StopOpcode(long offset) { 9 | super(OpcodeID.STOP); 10 | this.offset = offset; 11 | } 12 | 13 | @Override 14 | public int getStackConsumed() { 15 | return 0; 16 | } 17 | 18 | @Override 19 | public int getStackGenerated() { 20 | return 0; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Core/src/main/java/opcodes/environmentalOpcodes/AddressOpcode.java: -------------------------------------------------------------------------------- 1 | package opcodes.environmentalOpcodes; 2 | 3 | import opcodes.EnvironmentalOpcode; 4 | import opcodes.OpcodeID; 5 | 6 | public class AddressOpcode extends EnvironmentalOpcode { 7 | 8 | public AddressOpcode(long offset) { 9 | super(OpcodeID.ADDRESS); 10 | this.offset = offset; 11 | } 12 | 13 | @Override 14 | public int getStackConsumed() { 15 | return 0; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Core/src/main/java/opcodes/environmentalOpcodes/BalanceOpcode.java: -------------------------------------------------------------------------------- 1 | package opcodes.environmentalOpcodes; 2 | 3 | import opcodes.EnvironmentalOpcode; 4 | import opcodes.OpcodeID; 5 | 6 | public class BalanceOpcode extends EnvironmentalOpcode { 7 | 8 | public BalanceOpcode(long offset) { 9 | super(OpcodeID.BALANCE); 10 | this.offset = offset; 11 | } 12 | 13 | @Override 14 | public int getStackConsumed() { 15 | return 1; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Core/src/main/java/opcodes/environmentalOpcodes/CallDataCopyOpcode.java: -------------------------------------------------------------------------------- 1 | package opcodes.environmentalOpcodes; 2 | 3 | import opcodes.EnvironmentalOpcode; 4 | import opcodes.OpcodeID; 5 | 6 | public class CallDataCopyOpcode extends EnvironmentalOpcode { 7 | 8 | public CallDataCopyOpcode(long offset) { 9 | super(OpcodeID.CALLDATACOPY); 10 | this.offset = offset; 11 | } 12 | 13 | @Override 14 | public int getStackConsumed() { 15 | return 3; 16 | } 17 | 18 | @Override 19 | public int getStackGenerated() { 20 | return 0; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Core/src/main/java/opcodes/environmentalOpcodes/CallDataLoadOpcode.java: -------------------------------------------------------------------------------- 1 | package opcodes.environmentalOpcodes; 2 | 3 | import opcodes.EnvironmentalOpcode; 4 | import opcodes.OpcodeID; 5 | 6 | public class CallDataLoadOpcode extends EnvironmentalOpcode { 7 | 8 | public CallDataLoadOpcode(long offset) { 9 | super(OpcodeID.CALLDATALOAD); 10 | this.offset = offset; 11 | } 12 | 13 | @Override 14 | public int getStackConsumed() { 15 | return 1; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Core/src/main/java/opcodes/environmentalOpcodes/CallDataSizeOpcode.java: -------------------------------------------------------------------------------- 1 | package opcodes.environmentalOpcodes; 2 | 3 | import opcodes.EnvironmentalOpcode; 4 | import opcodes.OpcodeID; 5 | 6 | public class CallDataSizeOpcode extends EnvironmentalOpcode { 7 | 8 | public CallDataSizeOpcode(long offset) { 9 | super(OpcodeID.CALLDATASIZE); 10 | this.offset = offset; 11 | } 12 | 13 | @Override 14 | public int getStackConsumed() { 15 | return 0; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Core/src/main/java/opcodes/environmentalOpcodes/CallValueOpcode.java: -------------------------------------------------------------------------------- 1 | package opcodes.environmentalOpcodes; 2 | 3 | import opcodes.EnvironmentalOpcode; 4 | import opcodes.OpcodeID; 5 | 6 | public class CallValueOpcode extends EnvironmentalOpcode { 7 | 8 | public CallValueOpcode(long offset) { 9 | super(OpcodeID.CALLVALUE); 10 | this.offset = offset; 11 | } 12 | 13 | @Override 14 | public int getStackConsumed() { 15 | return 0; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Core/src/main/java/opcodes/environmentalOpcodes/CallerOpcode.java: -------------------------------------------------------------------------------- 1 | package opcodes.environmentalOpcodes; 2 | 3 | import opcodes.EnvironmentalOpcode; 4 | import opcodes.OpcodeID; 5 | 6 | public class CallerOpcode extends EnvironmentalOpcode { 7 | 8 | public CallerOpcode(long offset) { 9 | super(OpcodeID.CALLER); 10 | this.offset = offset; 11 | } 12 | 13 | @Override 14 | public int getStackConsumed() { 15 | return 0; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Core/src/main/java/opcodes/environmentalOpcodes/CodeCopyOpcode.java: -------------------------------------------------------------------------------- 1 | package opcodes.environmentalOpcodes; 2 | 3 | import opcodes.EnvironmentalOpcode; 4 | import opcodes.OpcodeID; 5 | 6 | public class CodeCopyOpcode extends EnvironmentalOpcode { 7 | 8 | public CodeCopyOpcode(long offset) { 9 | super(OpcodeID.CODECOPY); 10 | this.offset = offset; 11 | } 12 | 13 | @Override 14 | public int getStackGenerated() { 15 | return 0; 16 | } 17 | 18 | @Override 19 | public int getStackConsumed() { 20 | return 3; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Core/src/main/java/opcodes/environmentalOpcodes/CodeSizeOpcode.java: -------------------------------------------------------------------------------- 1 | package opcodes.environmentalOpcodes; 2 | 3 | import opcodes.EnvironmentalOpcode; 4 | import opcodes.OpcodeID; 5 | 6 | public class CodeSizeOpcode extends EnvironmentalOpcode { 7 | 8 | public CodeSizeOpcode(long offset) { 9 | super(OpcodeID.CODESIZE); 10 | this.offset = offset; 11 | } 12 | 13 | @Override 14 | public int getStackConsumed() { 15 | return 0; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Core/src/main/java/opcodes/environmentalOpcodes/ExtCodeCopyOpcode.java: -------------------------------------------------------------------------------- 1 | package opcodes.environmentalOpcodes; 2 | 3 | import opcodes.EnvironmentalOpcode; 4 | import opcodes.OpcodeID; 5 | 6 | public class ExtCodeCopyOpcode extends EnvironmentalOpcode { 7 | 8 | public ExtCodeCopyOpcode(long offset) { 9 | super(OpcodeID.EXTCODECOPY); 10 | this.offset = offset; 11 | } 12 | 13 | @Override 14 | public int getStackGenerated() { 15 | return 0; 16 | } 17 | 18 | @Override 19 | public int getStackConsumed() { 20 | return 4; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Core/src/main/java/opcodes/environmentalOpcodes/ExtCodeHashOpcode.java: -------------------------------------------------------------------------------- 1 | package opcodes.environmentalOpcodes; 2 | 3 | import opcodes.EnvironmentalOpcode; 4 | import opcodes.OpcodeID; 5 | 6 | public class ExtCodeHashOpcode extends EnvironmentalOpcode { 7 | 8 | public ExtCodeHashOpcode(long offset) { 9 | super(OpcodeID.EXTCODEHASH); 10 | this.offset = offset; 11 | } 12 | 13 | @Override 14 | public int getStackConsumed() { 15 | return 1; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Core/src/main/java/opcodes/environmentalOpcodes/ExtCodeSizeOpcode.java: -------------------------------------------------------------------------------- 1 | package opcodes.environmentalOpcodes; 2 | 3 | import opcodes.EnvironmentalOpcode; 4 | import opcodes.OpcodeID; 5 | 6 | public class ExtCodeSizeOpcode extends EnvironmentalOpcode { 7 | 8 | public ExtCodeSizeOpcode(long offset) { 9 | super(OpcodeID.EXTCODESIZE); 10 | this.offset = offset; 11 | } 12 | 13 | @Override 14 | public int getStackConsumed() { 15 | return 1; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Core/src/main/java/opcodes/environmentalOpcodes/GasPriceOpcode.java: -------------------------------------------------------------------------------- 1 | package opcodes.environmentalOpcodes; 2 | 3 | import opcodes.EnvironmentalOpcode; 4 | import opcodes.OpcodeID; 5 | 6 | public class GasPriceOpcode extends EnvironmentalOpcode { 7 | 8 | public GasPriceOpcode(long offset) { 9 | super(OpcodeID.GASPRICE); 10 | this.offset = offset; 11 | } 12 | 13 | @Override 14 | public int getStackConsumed() { 15 | return 0; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Core/src/main/java/opcodes/environmentalOpcodes/OriginOpcode.java: -------------------------------------------------------------------------------- 1 | package opcodes.environmentalOpcodes; 2 | 3 | import opcodes.EnvironmentalOpcode; 4 | import opcodes.OpcodeID; 5 | 6 | public class OriginOpcode extends EnvironmentalOpcode { 7 | 8 | public OriginOpcode(long offset) { 9 | super(OpcodeID.ORIGIN); 10 | this.offset = offset; 11 | } 12 | 13 | @Override 14 | public int getStackConsumed() { 15 | return 0; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Core/src/main/java/opcodes/environmentalOpcodes/ReturnDataCopyOpcode.java: -------------------------------------------------------------------------------- 1 | package opcodes.environmentalOpcodes; 2 | 3 | import opcodes.EnvironmentalOpcode; 4 | import opcodes.OpcodeID; 5 | 6 | public class ReturnDataCopyOpcode extends EnvironmentalOpcode { 7 | 8 | public ReturnDataCopyOpcode(long offset) { 9 | super(OpcodeID.RETURNDATACOPY); 10 | this.offset = offset; 11 | } 12 | 13 | @Override 14 | public int getStackGenerated() { 15 | return 0; 16 | } 17 | 18 | @Override 19 | public int getStackConsumed() { 20 | return 3; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Core/src/main/java/opcodes/environmentalOpcodes/ReturnDataSizeOpcode.java: -------------------------------------------------------------------------------- 1 | package opcodes.environmentalOpcodes; 2 | 3 | import opcodes.EnvironmentalOpcode; 4 | import opcodes.OpcodeID; 5 | 6 | public class ReturnDataSizeOpcode extends EnvironmentalOpcode { 7 | 8 | public ReturnDataSizeOpcode(long offset) { 9 | super(OpcodeID.RETURNDATASIZE); 10 | this.offset = offset; 11 | } 12 | 13 | @Override 14 | public int getStackConsumed() { 15 | return 0; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Core/src/main/java/opcodes/environmentalOpcodes/SelfBalanceOpcode.java: -------------------------------------------------------------------------------- 1 | package opcodes.environmentalOpcodes; 2 | 3 | import opcodes.EnvironmentalOpcode; 4 | import opcodes.OpcodeID; 5 | 6 | public class SelfBalanceOpcode extends EnvironmentalOpcode { 7 | 8 | public SelfBalanceOpcode(long offset) { 9 | super(OpcodeID.SELFBALANCE); 10 | this.offset = offset; 11 | } 12 | 13 | @Override 14 | public int getStackConsumed() { 15 | return 0; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Core/src/main/java/opcodes/stackOpcodes/DupOpcode.java: -------------------------------------------------------------------------------- 1 | package opcodes.stackOpcodes; 2 | 3 | import opcodes.Opcode; 4 | import opcodes.OpcodeID; 5 | import opcodes.StackOpcode; 6 | 7 | public class DupOpcode extends StackOpcode { 8 | 9 | private int value; 10 | 11 | /** 12 | * Basic constructor for all DUP opcodes. 13 | * @param offset the offset in the bytecode, expressed in bytes. 14 | * @param value the number of the stack value to be duplicated. It must be between 1 and 16. 15 | */ 16 | public DupOpcode(long offset, int value) { 17 | super(OpcodeID.DUP); 18 | if (value < 1 || value > 16) 19 | throw new IllegalArgumentException("DUP number must be between 1 and 16"); 20 | this.offset = offset; 21 | this.value = value; 22 | } 23 | 24 | @Override 25 | public int getStackConsumed() { 26 | return value; 27 | } 28 | 29 | @Override 30 | public int getStackGenerated() { 31 | return super.getStackGenerated() + value; 32 | } 33 | 34 | @Override 35 | public String getBytes() { 36 | byte opcode = (byte) (opcodeID.getOpcode() + value - 1); 37 | return String.format("%02x", opcode); 38 | } 39 | 40 | @Override 41 | public String toString() { 42 | return super.toString() + value; 43 | } 44 | 45 | public int getValue() { 46 | return value; 47 | } 48 | 49 | @Override 50 | public boolean isSameOpcode(Opcode other) { 51 | return super.isSameOpcode(other) && ((DupOpcode) other).value == this.value; 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /Core/src/main/java/opcodes/stackOpcodes/GasOpcode.java: -------------------------------------------------------------------------------- 1 | package opcodes.stackOpcodes; 2 | 3 | import opcodes.OpcodeID; 4 | import opcodes.StackOpcode; 5 | 6 | public class GasOpcode extends StackOpcode { 7 | 8 | public GasOpcode(long offset) { 9 | super(OpcodeID.GAS); 10 | this.offset = offset; 11 | } 12 | 13 | @Override 14 | public int getStackConsumed() { 15 | return 0; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Core/src/main/java/opcodes/stackOpcodes/MLoadOpcode.java: -------------------------------------------------------------------------------- 1 | package opcodes.stackOpcodes; 2 | 3 | import opcodes.OpcodeID; 4 | import opcodes.StackOpcode; 5 | 6 | public class MLoadOpcode extends StackOpcode { 7 | 8 | public MLoadOpcode(long offset) { 9 | super(OpcodeID.MLOAD); 10 | this.offset = offset; 11 | } 12 | 13 | @Override 14 | public int getStackConsumed() { 15 | return 1; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Core/src/main/java/opcodes/stackOpcodes/MSizeOpcode.java: -------------------------------------------------------------------------------- 1 | package opcodes.stackOpcodes; 2 | 3 | import opcodes.OpcodeID; 4 | import opcodes.StackOpcode; 5 | 6 | public class MSizeOpcode extends StackOpcode { 7 | 8 | public MSizeOpcode(long offset) { 9 | super(OpcodeID.MSIZE); 10 | this.offset = offset; 11 | } 12 | 13 | @Override 14 | public int getStackConsumed() { 15 | return 0; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Core/src/main/java/opcodes/stackOpcodes/MStore8Opcode.java: -------------------------------------------------------------------------------- 1 | package opcodes.stackOpcodes; 2 | 3 | import opcodes.OpcodeID; 4 | import opcodes.StackOpcode; 5 | 6 | public class MStore8Opcode extends StackOpcode { 7 | 8 | public MStore8Opcode(long offset) { 9 | super(OpcodeID.MSTORE8); 10 | this.offset = offset; 11 | } 12 | 13 | @Override 14 | public int getStackGenerated() { 15 | return 0; 16 | } 17 | 18 | @Override 19 | public int getStackConsumed() { 20 | return 2; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Core/src/main/java/opcodes/stackOpcodes/MStoreOpcode.java: -------------------------------------------------------------------------------- 1 | package opcodes.stackOpcodes; 2 | 3 | import opcodes.OpcodeID; 4 | import opcodes.StackOpcode; 5 | 6 | public class MStoreOpcode extends StackOpcode { 7 | 8 | public MStoreOpcode(long offset) { 9 | super(OpcodeID.MSTORE); 10 | this.offset = offset; 11 | } 12 | 13 | @Override 14 | public int getStackGenerated() { 15 | return 0; 16 | } 17 | 18 | @Override 19 | public int getStackConsumed() { 20 | return 2; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Core/src/main/java/opcodes/stackOpcodes/PCOpcode.java: -------------------------------------------------------------------------------- 1 | package opcodes.stackOpcodes; 2 | 3 | import opcodes.OpcodeID; 4 | import opcodes.StackOpcode; 5 | 6 | public class PCOpcode extends StackOpcode { 7 | 8 | public PCOpcode(long offset) { 9 | super(OpcodeID.PC); 10 | this.offset = offset; 11 | } 12 | 13 | @Override 14 | public int getStackConsumed() { 15 | return 0; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Core/src/main/java/opcodes/stackOpcodes/PopOpcode.java: -------------------------------------------------------------------------------- 1 | package opcodes.stackOpcodes; 2 | 3 | import opcodes.OpcodeID; 4 | import opcodes.StackOpcode; 5 | 6 | public class PopOpcode extends StackOpcode { 7 | 8 | public PopOpcode(long offset) { 9 | super(OpcodeID.POP); 10 | this.offset = offset; 11 | } 12 | 13 | @Override 14 | public int getStackGenerated() { 15 | return 0; 16 | } 17 | 18 | @Override 19 | public int getStackConsumed() { 20 | return 1; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Core/src/main/java/opcodes/stackOpcodes/PushOpcode.java: -------------------------------------------------------------------------------- 1 | package opcodes.stackOpcodes; 2 | 3 | import opcodes.Opcode; 4 | import opcodes.OpcodeID; 5 | import opcodes.StackOpcode; 6 | 7 | import java.math.BigInteger; 8 | 9 | public class PushOpcode extends StackOpcode { 10 | protected final int parameterLength; 11 | protected final BigInteger parameter; 12 | 13 | /** 14 | * Basic constructor for all Push opcodes 15 | * @param offset the offset in the bytecode, expressed in bytes 16 | * @param parameter_length the number of the PUSH. It must be between 1 and 32 17 | * @param parameter the number pushed to the stack. 18 | */ 19 | public PushOpcode(long offset, int parameter_length, BigInteger parameter) { 20 | super(OpcodeID.PUSH); 21 | if (parameter_length < 1 || parameter_length > 32) 22 | throw new IllegalArgumentException("Push parameter length must be between 1 and 32 bytes"); 23 | this.offset = offset; 24 | this.parameterLength = parameter_length; 25 | this.parameter = parameter; 26 | } 27 | 28 | public PushOpcode(long offset, int parameterLength) { 29 | this(offset, parameterLength, BigInteger.ZERO); 30 | } 31 | 32 | public BigInteger getParameter() { 33 | return parameter; 34 | } 35 | 36 | public int getParameterLength() { 37 | return parameterLength; 38 | } 39 | 40 | @Override 41 | public int getLength() { 42 | return super.getLength() + parameterLength; 43 | } 44 | 45 | @Override 46 | public int getStackConsumed() { 47 | return 0; 48 | } 49 | 50 | @Override 51 | public String toString() { 52 | return super.toString() + parameterLength + " 0x" + getBytes().substring(2); 53 | } 54 | 55 | @Override 56 | public String getBytes() { 57 | byte opcode = (byte) (opcodeID.getOpcode() + parameterLength - 1); 58 | String argument = parameter.toString(16); 59 | // print the argument with the right number of leading zeros 60 | int zeros = parameterLength * 2 - argument.length(); 61 | StringBuilder sb = new StringBuilder(); 62 | for (int i = 0; i < zeros; i++) { 63 | sb.append('0'); 64 | } 65 | return String.format("%x%s", opcode, sb.toString() + argument); 66 | } 67 | 68 | /** 69 | * Two pushOpcode are considered the same opcode if they have the same parameter length, ignoring the argument 70 | * @param other opcode to test 71 | * @return if they are both push of the same length (e.g. PUSH1 != PUSH20) 72 | */ 73 | @Override 74 | public boolean isSameOpcode(Opcode other) { 75 | // Ignore the parameter value 76 | return super.isSameOpcode(other) && ((PushOpcode) other).parameterLength == this.parameterLength; 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /Core/src/main/java/opcodes/stackOpcodes/SLoadOpcode.java: -------------------------------------------------------------------------------- 1 | package opcodes.stackOpcodes; 2 | 3 | import opcodes.OpcodeID; 4 | import opcodes.StackOpcode; 5 | 6 | public class SLoadOpcode extends StackOpcode { 7 | 8 | public SLoadOpcode(long offset) { 9 | super(OpcodeID.SLOAD); 10 | this.offset = offset; 11 | } 12 | 13 | @Override 14 | public int getStackConsumed() { 15 | return 1; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Core/src/main/java/opcodes/stackOpcodes/SStoreOpcode.java: -------------------------------------------------------------------------------- 1 | package opcodes.stackOpcodes; 2 | 3 | import opcodes.OpcodeID; 4 | import opcodes.StackOpcode; 5 | 6 | public class SStoreOpcode extends StackOpcode { 7 | 8 | public SStoreOpcode(long offset) { 9 | super(OpcodeID.SSTORE); 10 | this.offset = offset; 11 | } 12 | 13 | @Override 14 | public int getStackGenerated() { 15 | return 0; 16 | } 17 | 18 | @Override 19 | public int getStackConsumed() { 20 | return 2; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Core/src/main/java/opcodes/stackOpcodes/SwapOpcode.java: -------------------------------------------------------------------------------- 1 | package opcodes.stackOpcodes; 2 | 3 | import opcodes.Opcode; 4 | import opcodes.OpcodeID; 5 | import opcodes.StackOpcode; 6 | 7 | public class SwapOpcode extends StackOpcode { 8 | 9 | private int value; 10 | 11 | /** 12 | * Basic constructor for all SWAP opcodes. 13 | * @param offset the offset in the bytecode, expressed in bytes. 14 | * @param value the number of the stack value to be swapped with the last. It must be between 1 and 16. 15 | */ 16 | public SwapOpcode(long offset, int value) { 17 | super(OpcodeID.SWAP); 18 | if (value < 1 || value > 16) 19 | throw new IllegalArgumentException("DUP number must be between 1 and 16"); 20 | this.offset = offset; 21 | this.value = value; 22 | } 23 | 24 | @Override 25 | public int getStackConsumed() { 26 | return value + 1; 27 | } 28 | 29 | @Override 30 | public int getStackGenerated() { 31 | return super.getStackGenerated() + value; 32 | } 33 | 34 | @Override 35 | public String toString() { 36 | return super.toString() + value; 37 | } 38 | 39 | @Override 40 | public String getBytes() { 41 | byte opcode = (byte) (opcodeID.getOpcode() + value - 1); 42 | return String.format("%02x", opcode); 43 | } 44 | 45 | public int getValue() { 46 | return value; 47 | } 48 | 49 | @Override 50 | public boolean isSameOpcode(Opcode other) { 51 | return super.isSameOpcode(other) && ((SwapOpcode)other).value == this.value; 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /Core/src/main/java/opcodes/systemOpcodes/CallCodeOpcode.java: -------------------------------------------------------------------------------- 1 | package opcodes.systemOpcodes; 2 | 3 | import opcodes.OpcodeID; 4 | import opcodes.SystemOpcode; 5 | 6 | public class CallCodeOpcode extends SystemOpcode { 7 | 8 | public CallCodeOpcode(long offset) { 9 | super(OpcodeID.CALLCODE); 10 | this.offset = offset; 11 | } 12 | 13 | @Override 14 | public int getStackConsumed() { 15 | return 7; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Core/src/main/java/opcodes/systemOpcodes/CallOpcode.java: -------------------------------------------------------------------------------- 1 | package opcodes.systemOpcodes; 2 | 3 | import opcodes.OpcodeID; 4 | import opcodes.SystemOpcode; 5 | 6 | public class CallOpcode extends SystemOpcode { 7 | 8 | public CallOpcode(long offset) { 9 | super(OpcodeID.CALL); 10 | this.offset = offset; 11 | } 12 | 13 | @Override 14 | public int getStackConsumed() { 15 | return 7; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Core/src/main/java/opcodes/systemOpcodes/CreateOpcode.java: -------------------------------------------------------------------------------- 1 | package opcodes.systemOpcodes; 2 | 3 | import opcodes.OpcodeID; 4 | import opcodes.SystemOpcode; 5 | 6 | public class CreateOpcode extends SystemOpcode { 7 | 8 | public CreateOpcode(long offset) { 9 | super(OpcodeID.CREATE); 10 | this.offset = offset; 11 | } 12 | 13 | @Override 14 | public int getStackConsumed() { 15 | return 3; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Core/src/main/java/opcodes/systemOpcodes/DelegateCallOpcode.java: -------------------------------------------------------------------------------- 1 | package opcodes.systemOpcodes; 2 | 3 | import opcodes.OpcodeID; 4 | import opcodes.SystemOpcode; 5 | 6 | public class DelegateCallOpcode extends SystemOpcode { 7 | 8 | public DelegateCallOpcode(long offset) { 9 | super(OpcodeID.DELEGATECALL); 10 | this.offset = offset; 11 | } 12 | 13 | @Override 14 | public int getStackConsumed() { 15 | return 6; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Core/src/main/java/opcodes/systemOpcodes/ReturnOpcode.java: -------------------------------------------------------------------------------- 1 | package opcodes.systemOpcodes; 2 | 3 | import opcodes.OpcodeID; 4 | import opcodes.SystemOpcode; 5 | 6 | public class ReturnOpcode extends SystemOpcode { 7 | 8 | public ReturnOpcode(long offset) { 9 | super(OpcodeID.RETURN); 10 | this.offset = offset; 11 | } 12 | 13 | @Override 14 | public int getStackGenerated() { 15 | return 0; 16 | } 17 | 18 | @Override 19 | public int getStackConsumed() { 20 | return 2; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Core/src/main/java/opcodes/systemOpcodes/RevertOpcode.java: -------------------------------------------------------------------------------- 1 | package opcodes.systemOpcodes; 2 | 3 | import opcodes.OpcodeID; 4 | import opcodes.SystemOpcode; 5 | 6 | public class RevertOpcode extends SystemOpcode { 7 | 8 | public RevertOpcode(long offset) { 9 | super(OpcodeID.REVERT); 10 | this.offset = offset; 11 | } 12 | 13 | @Override 14 | public int getStackGenerated() { 15 | return 0; 16 | } 17 | 18 | @Override 19 | public int getStackConsumed() { 20 | return 2; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Core/src/main/java/opcodes/systemOpcodes/SelfDestructOpcode.java: -------------------------------------------------------------------------------- 1 | package opcodes.systemOpcodes; 2 | 3 | import opcodes.OpcodeID; 4 | import opcodes.SystemOpcode; 5 | 6 | public class SelfDestructOpcode extends SystemOpcode { 7 | 8 | public SelfDestructOpcode(long offset) { 9 | super(OpcodeID.SELFDESTRUCT); 10 | this.offset = offset; 11 | } 12 | 13 | @Override 14 | public int getStackGenerated() { 15 | return 0; 16 | } 17 | 18 | @Override 19 | public int getStackConsumed() { 20 | return 1; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Core/src/main/java/opcodes/systemOpcodes/StaticCallOpcode.java: -------------------------------------------------------------------------------- 1 | package opcodes.systemOpcodes; 2 | 3 | import opcodes.OpcodeID; 4 | import opcodes.SystemOpcode; 5 | 6 | public class StaticCallOpcode extends SystemOpcode { 7 | 8 | public StaticCallOpcode(long offset) { 9 | super(OpcodeID.STATICCALL); 10 | this.offset = offset; 11 | } 12 | 13 | @Override 14 | public int getStackConsumed() { 15 | return 6; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Core/src/main/java/parseTree/NotSolidityContractException.java: -------------------------------------------------------------------------------- 1 | package parseTree; 2 | 3 | public class NotSolidityContractException extends Exception { 4 | } 5 | -------------------------------------------------------------------------------- /Core/src/main/java/parseTree/SymbolicExecution/StackExceededException.java: -------------------------------------------------------------------------------- 1 | package parseTree.SymbolicExecution; 2 | 3 | public class StackExceededException extends Exception { 4 | } 5 | -------------------------------------------------------------------------------- /Core/src/main/java/parseTree/SymbolicExecution/UnknownStackElementException.java: -------------------------------------------------------------------------------- 1 | package parseTree.SymbolicExecution; 2 | 3 | public class UnknownStackElementException extends Throwable { 4 | } 5 | -------------------------------------------------------------------------------- /Core/src/main/java/parseTree/cfg/BasicBlock.java: -------------------------------------------------------------------------------- 1 | package parseTree.cfg; 2 | 3 | import opcodes.Opcode; 4 | import parseTree.Bytecode; 5 | 6 | import java.util.ArrayList; 7 | import java.util.List; 8 | 9 | public class BasicBlock extends Bytecode { 10 | 11 | private final ArrayList predecessors; 12 | private final ArrayList successors; 13 | private int stackBalance; 14 | private BasicBlockType type; 15 | 16 | /** 17 | * Default constructor with offset 0 and no opcodes 18 | */ 19 | public BasicBlock(){ 20 | this(0); 21 | } 22 | 23 | /** 24 | * Default constructor with no opcodes 25 | * @param offset position in the bytecode 26 | */ 27 | public BasicBlock(long offset) { 28 | this(offset, new ArrayList<>()); 29 | } 30 | 31 | /** 32 | * Default constructor with offset and opcodes 33 | * @param offset position in the code 34 | * @param opcodes list of opcodes 35 | */ 36 | public BasicBlock(long offset, ArrayList opcodes) { 37 | super(offset, opcodes); 38 | this.successors = new ArrayList<>(); 39 | this.predecessors = new ArrayList<>(); 40 | this.type = BasicBlockType.COMMON; 41 | } 42 | 43 | private int calculateStackBalance() { 44 | int balance = 0; 45 | for (Opcode o : this.getOpcodes()){ 46 | balance -= o.getStackConsumed(); 47 | balance += o.getStackGenerated(); 48 | } 49 | return balance; 50 | } 51 | 52 | /** 53 | * Default getter for the successors of the block 54 | * @return successors blocks 55 | */ 56 | public ArrayList getSuccessors() { 57 | return successors; 58 | } 59 | 60 | /** 61 | * Default getter for the predecessors of the block 62 | * @return predecessors blocks 63 | */ 64 | public ArrayList getPredecessors() { 65 | return predecessors; 66 | } 67 | 68 | /** 69 | * Default getter for the stack balance. It represents the number of elements added/removed to the stack if the entire block is executed 70 | * @return the stack balance 71 | */ 72 | public int getStackBalance() { 73 | return stackBalance; 74 | } 75 | 76 | /** 77 | * Adds a successor to the block. The block is also added to the successor block as a predecessor 78 | * @param next the next block 79 | */ 80 | public void addSuccessor(BasicBlock next){ 81 | this.successors.add(next); 82 | next.predecessors.add(this); 83 | } 84 | 85 | /** 86 | * Adds the opcode and updates the stack balance 87 | * @param opcode the opcode to add 88 | */ 89 | @Override 90 | public void addOpcode(Opcode opcode) { 91 | super.addOpcode(opcode); 92 | this.stackBalance -= opcode.getStackConsumed(); 93 | this.stackBalance += opcode.getStackGenerated(); 94 | } 95 | 96 | /** 97 | * Adds the opcodes and updates the stack balance 98 | * @param opcodes opcodes to be added 99 | */ 100 | @Override 101 | public void addAll(Opcode... opcodes) { 102 | super.addAll(opcodes); 103 | this.stackBalance = calculateStackBalance(); 104 | } 105 | 106 | /** 107 | * Adds the opcodes and updates the stack balance 108 | * @param subList list of opcode to add 109 | */ 110 | @Override 111 | public void addAll(List subList) { 112 | super.addAll(subList); 113 | this.stackBalance = calculateStackBalance(); 114 | } 115 | 116 | /** 117 | * Default setter for the type 118 | * @param type block's type 119 | */ 120 | public void setType(BasicBlockType type) { 121 | this.type = type; 122 | } 123 | 124 | /** 125 | * Default getter for the type 126 | * @return block's type 127 | */ 128 | public BasicBlockType getType() { 129 | return type; 130 | } 131 | 132 | /** 133 | * Default representation of the block as bytecode. The special case is the exit block 134 | * @return block's string representation 135 | */ 136 | @Override 137 | public String toString() { 138 | if (type == BasicBlockType.EXIT) 139 | return getOffset() + ": EXIT BLOCK"; 140 | else 141 | return super.toString(); 142 | } 143 | } 144 | -------------------------------------------------------------------------------- /Core/src/main/java/parseTree/cfg/BasicBlockType.java: -------------------------------------------------------------------------------- 1 | package parseTree.cfg; 2 | 3 | public enum BasicBlockType { 4 | COMMON, 5 | DISPATCHER, 6 | FALLBACK, 7 | EXIT 8 | } 9 | -------------------------------------------------------------------------------- /Core/src/main/java/parseTree/cfg/Cfg.java: -------------------------------------------------------------------------------- 1 | package parseTree.cfg; 2 | 3 | import parseTree.Bytecode; 4 | 5 | import java.util.*; 6 | 7 | public class Cfg implements Iterable{ 8 | 9 | private final TreeMap basicBlocks; 10 | private final Bytecode bytecode; 11 | private final CfgBuildReport buildReport; 12 | private final String remainingData; 13 | 14 | protected Cfg(Bytecode bytecode, TreeMap basicBlocks, String remainingData, CfgBuildReport buildReport) { 15 | this.bytecode = bytecode; 16 | this.basicBlocks = basicBlocks; 17 | this.remainingData = remainingData; 18 | this.buildReport = buildReport; 19 | } 20 | 21 | /** 22 | * Default getter for the bytecode 23 | * @return bytecode 24 | */ 25 | public Bytecode getBytecode() { 26 | return bytecode; 27 | } 28 | 29 | /** 30 | * Default getter for the block with a certain offset 31 | * @param offset the offset of the block 32 | * @return the block with that offset 33 | */ 34 | public BasicBlock getBasicBlock(long offset){ 35 | return basicBlocks.get(offset); 36 | } 37 | 38 | /** 39 | * Default getter for the build report 40 | * @return build report 41 | */ 42 | public CfgBuildReport getBuildReport() { 43 | return buildReport; 44 | } 45 | 46 | /** 47 | * Default getter for the remaining data 48 | * @return remaining data 49 | */ 50 | public String getRemainingData() { 51 | return remainingData; 52 | } 53 | 54 | /** 55 | * Generates the adjacency list for the graph. It is a map which associates to each offset a list with the offsets of the successors. 56 | * @return the adjacency list 57 | */ 58 | public Map> getSuccessorsMap(){ 59 | Map> successors = new TreeMap<>(); 60 | for (Long offset : basicBlocks.keySet()){ 61 | ArrayList arr = new ArrayList<>(); 62 | for (BasicBlock successor : basicBlocks.get(offset).getSuccessors()) 63 | arr.add(successor.getOffset()); 64 | successors.put(offset, arr); 65 | } 66 | return successors; 67 | } 68 | 69 | /** 70 | * Default iterator over the basic blocks 71 | * @return iterator over the basic blocks 72 | */ 73 | @Override 74 | public Iterator iterator() { 75 | return basicBlocks.values().iterator(); 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /Core/src/main/java/utils/Message.java: -------------------------------------------------------------------------------- 1 | package utils; 2 | 3 | /** 4 | * Util class to print errors, warning and debug messages 5 | */ 6 | public class Message { 7 | private static final String ANSI_RESET = "\u001B[0m"; 8 | private static final String ANSI_YELLOW = "\u001B[33m"; 9 | private static boolean printDebug = false; 10 | 11 | /** 12 | * Prints an error to the stderr 13 | * @param message printed error 14 | */ 15 | public static void printError(String message){ 16 | System.err.println(message); 17 | } 18 | 19 | /** 20 | * Prints a warning to stdout with a yellow color 21 | * @param message printed warning 22 | */ 23 | public static void printWarning(String message){ 24 | System.out.println(ANSI_YELLOW + message + ANSI_RESET); 25 | } 26 | 27 | /** 28 | * Prints a message as debug to stdout if the debug option is active 29 | * @param message 30 | */ 31 | public static void printDebug(String message){ 32 | if (printDebug) 33 | System.out.println(message); 34 | } 35 | 36 | /** 37 | * Set the debug level 38 | * @param printDebug true: do print, false: don't print 39 | */ 40 | public static void setPrintDebug(boolean printDebug) { 41 | Message.printDebug = printDebug; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /Core/src/main/java/utils/Pair.java: -------------------------------------------------------------------------------- 1 | package utils; 2 | 3 | /** 4 | * Class to create a 2-tuple with no complex methods 5 | * @param Type of the key 6 | * @param Type of the value 7 | */ 8 | public class Pair { 9 | 10 | private final T1 key; 11 | private final T2 value; 12 | 13 | /** 14 | * The only constructor to set the two elements 15 | * @param key key object 16 | * @param value value object 17 | */ 18 | public Pair(T1 key, T2 value) { 19 | this.key = key; 20 | this.value = value; 21 | } 22 | 23 | /** 24 | * Getter for the first element 25 | * @return key 26 | */ 27 | public T1 getKey() { 28 | return key; 29 | } 30 | 31 | /** 32 | * Getter for the second element 33 | * @return value 34 | */ 35 | public T2 getValue() { 36 | return value; 37 | } 38 | 39 | /** 40 | * Returns a string representation of the pair 41 | * @return <Key, Value> 42 | */ 43 | @Override 44 | public String toString() { 45 | return "<" + key + ", " + value + ">"; 46 | } 47 | 48 | /** 49 | * Standard equals function, check if both keys and values are equals 50 | * @param o other object 51 | * @return if they represent the same key-value pair 52 | */ 53 | @Override 54 | public boolean equals(Object o) { 55 | if (this == o) return true; 56 | if (o == null || getClass() != o.getClass()) return false; 57 | Pair, ?> pair = (Pair, ?>) o; 58 | return this.key.equals(pair.key) && this.value.equals(pair.value); 59 | } 60 | 61 | /** 62 | * Standard hashcode function. 63 | * I't a xor between the hashcode of key and value 64 | * @return hashcode 65 | */ 66 | @Override 67 | public int hashCode() { 68 | return key.hashCode() ^ value.hashCode(); 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /Core/src/main/java/utils/Triplet.java: -------------------------------------------------------------------------------- 1 | package utils; 2 | 3 | /** 4 | * Class to create a 3-tuple with no complex methods 5 | * @param Type of the first element 6 | * @param Type of the second element 7 | * @param Type of the third element 8 | */ 9 | public class Triplet { 10 | private final T1 elem1; 11 | private final T2 elem2; 12 | private final T3 elem3; 13 | 14 | /** 15 | * The only constructor to set the two elements 16 | * @param elem1 first object 17 | * @param elem2 second object 18 | * @param elem3 third object 19 | */ 20 | public Triplet(T1 elem1, T2 elem2, T3 elem3) { 21 | this.elem1 = elem1; 22 | this.elem2 = elem2; 23 | this.elem3 = elem3; 24 | } 25 | 26 | /** 27 | * Simple getter for the fist element 28 | * @return the first element 29 | */ 30 | public T1 getElem1() { 31 | return elem1; 32 | } 33 | 34 | /** 35 | * Simple getter for the second element 36 | * @return the second element 37 | */ 38 | public T2 getElem2() { 39 | return elem2; 40 | } 41 | 42 | /** 43 | * Simple getter for the third element 44 | * @return the third element 45 | */ 46 | public T3 getElem3() { 47 | return elem3; 48 | } 49 | 50 | /** 51 | * Returns a string representation of the pair 52 | * @return <Element1, Element2, Element3> 53 | */ 54 | @Override 55 | public String toString() { 56 | return "<" + elem1 + ", " + elem2 + ", " + elem3 + ">"; 57 | } 58 | 59 | /** 60 | * Standard equals function, check if the 3 elements are equals with the 3 elements of o 61 | * @param o other object 62 | * @return if they represent the same 3-tuple 63 | */ 64 | @Override 65 | public boolean equals(Object o) { 66 | if (this == o) return true; 67 | if (o == null || getClass() != o.getClass()) return false; 68 | Triplet, ?, ?> triplet = (Triplet, ?, ?>) o; 69 | return elem1.equals(triplet.elem1) && 70 | elem2.equals(triplet.elem2) && 71 | elem3.equals(triplet.elem3); 72 | } 73 | 74 | /** 75 | * Standard hashcode function. 76 | * I't a xor between the hashcode of the three elements 77 | * @return hashcode 78 | */ 79 | @Override 80 | public int hashCode() { 81 | return elem1.hashCode() ^ elem2.hashCode() ^ elem3.hashCode(); 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /Core/src/test/java/parseTree/SymbolicExecutionStackTest.java: -------------------------------------------------------------------------------- 1 | package parseTree; 2 | 3 | import opcodes.arithmeticOpcodes.binaryArithmeticOpcodes.AddOpcode; 4 | import opcodes.stackOpcodes.DupOpcode; 5 | import opcodes.stackOpcodes.PopOpcode; 6 | import opcodes.stackOpcodes.PushOpcode; 7 | import opcodes.stackOpcodes.SwapOpcode; 8 | import org.junit.jupiter.api.Test; 9 | import parseTree.SymbolicExecution.StackExceededException; 10 | import parseTree.SymbolicExecution.SymbolicExecutionStack; 11 | import parseTree.SymbolicExecution.UnknownStackElementException; 12 | 13 | import java.math.BigInteger; 14 | 15 | import static org.junit.jupiter.api.Assertions.assertEquals; 16 | import static org.junit.jupiter.api.Assertions.assertThrows; 17 | 18 | class SymbolicExecutionStackTest { 19 | 20 | @Test 21 | void executeOpcodeAdd() throws StackExceededException { 22 | SymbolicExecutionStack stack = new SymbolicExecutionStack(); 23 | stack.executeOpcode(new PushOpcode(0, 4, new BigInteger("8"))); 24 | stack.executeOpcode(new PushOpcode(0, 4, new BigInteger("2"))); 25 | stack.executeOpcode(new AddOpcode(0)); 26 | assertThrows(UnknownStackElementException.class, stack::peek); 27 | } 28 | 29 | @Test 30 | void executeOpcodePush() throws StackExceededException { 31 | SymbolicExecutionStack stack = new SymbolicExecutionStack(); 32 | stack.executeOpcode(new PushOpcode(0, 4, new BigInteger("8"))); 33 | try { 34 | assertEquals(8, stack.peek().longValue()); 35 | } catch (UnknownStackElementException e) { 36 | e.printStackTrace(); 37 | } 38 | } 39 | 40 | @Test 41 | void executeOpcodeDup() throws StackExceededException { 42 | SymbolicExecutionStack stack = new SymbolicExecutionStack(); 43 | stack.executeOpcode(new PushOpcode(0, 4, new BigInteger("8"))); 44 | stack.executeOpcode(new PushOpcode(0, 4, new BigInteger("7"))); 45 | stack.executeOpcode(new PushOpcode(0, 4, new BigInteger("4"))); 46 | stack.executeOpcode(new DupOpcode(0, 2)); 47 | try { 48 | assertEquals(7, stack.peek().longValue()); 49 | } catch (UnknownStackElementException e) { 50 | e.printStackTrace(); 51 | } 52 | } 53 | 54 | @Test 55 | void executeOpcodeSwap() throws StackExceededException { 56 | SymbolicExecutionStack stack = new SymbolicExecutionStack(); 57 | stack.executeOpcode(new PushOpcode(0, 4, new BigInteger("8"))); 58 | stack.executeOpcode(new PushOpcode(0, 4, new BigInteger("7"))); 59 | stack.executeOpcode(new PushOpcode(0, 4, new BigInteger("4"))); 60 | stack.executeOpcode(new PushOpcode(0, 4, new BigInteger("3"))); 61 | stack.executeOpcode(new SwapOpcode(0, 3)); 62 | stack.executeOpcode(new PopOpcode(0)); 63 | stack.executeOpcode(new PopOpcode(0)); 64 | stack.executeOpcode(new PopOpcode(0)); 65 | try { 66 | assertEquals(3, stack.peek().longValue()); 67 | } catch (UnknownStackElementException e) { 68 | e.printStackTrace(); 69 | } 70 | } 71 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 SeUniVr 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Logo/Logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SeUniVr/EtherSolve/59fe4412f7230d9ee1047b25fbcf30b63cb89488/Logo/Logo.png -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | # EtherSolve 3 | 4 | EtherSolve is a tool for *Control Flow Graph (CFG)* reconstruction and *static analysis* of Solidity smart-contracts from Ethereum bytecode. 5 | 6 | The tool is based on the peer-reviewed pubblication 7 | > Michele Pasqua, Andrea Benini, Filippo Contro, Marco Crosara, Mila Dalla Preda, and Mariano Ceccato. "Enhancing Ethereum smart-contracts static analysis by computing a precise Control-Flow Graph of Ethereum bytecode". In: *Journal of Systems and Software* (pp. 1-18), Elsevier, 2023. DOI: [10.1016/j.jss.2023.111653](https://doi.org/10.1016/j.jss.2023.111653) 8 | 9 | That is a revised and extended version of the peer-reviewed publication 10 | > Filippo Contro, Marco Crosara, Mariano Ceccato, and Mila Dalla Preda. "EtherSolve: Computing an Accurate Control-Flow Graph from Ethereum Bytecode". In: *Proceedings of the 29th IEEE/ACM International Conference on Program Comprehension* (pp. 127-137), IEEE, 2021. DOI: [10.1109/ICPC52881.2021.00021](https://doi.org/10.1109/ICPC52881.2021.00021) 11 | 12 | ### Vulnerability Detection 13 | The tool also provides modules for the detection of Ethereum vulnerabilities. It currently supports *Re-entrancy* and *Tx.origin* vulnerabilities. 14 | 15 | ## Usage 16 | 17 | ### JAR 18 | 19 | The simplest way to try EtherSolve is through the provided `EtherSolve.jar` ([link](artifact/EtherSolve.jar)). 20 | 21 | ```bash 22 | Usage: ethersolve [-hV] [--re-entrancy] [--tx-origin] [-o=] (-c | -r) (-j | -H | -s | -d) 23 | EtherSolve, build an accurate CFG from Ethereum bytecode. 24 | Bytecode string or file containing it. 25 | -h, --help Show this help message and exit. 26 | -V, --version Print version information and exit. 27 | --re-entrancy Execute the Re-entrancy detector and save output. 28 | --tx-origin Execute the Tx.origin detector and save output. 29 | -o, --output= Output file name. 30 | -c, --creation Parse bytecode as creation code. 31 | -r, --runtime Parse bytecode as runtime code. 32 | -j, --json Export a Json report. 33 | -H, --html Export a graphic HTML report. Graphviz is required! 34 | -s, --svg Export a graphic SVG image. Graphviz is required! 35 | -d, --dot Export a dot-notation file. 36 | ``` 37 | 38 | The source can be the EVM bytecode string or a path to a file containing it. Specify if the bytecode is creation code (`-c`) or runtime code (`-r`), and the desired output type. 39 | The tool has been tested on Linux x64 with Java 11.0.8. To produce a graphical output (HTML or SVG) [Graphviz](https://graphviz.org/) is required. 40 | 41 | To run the Re-entrancy and the Tx.origin validators add the `--re-entrancy` and the `--tx-origin` options, respectively. The tool will create a CSV file containing the detected vulnerabilities and their location in the code. 42 | 43 | #### Examples 44 | 45 | To analize the bytecode of a smart-contract contained in a given file, you can run following: 46 | 47 | ```bash 48 | # Generate HTML report for creation-code source file 49 | java -jar EtherSolve.jar -c -H path/to/bytecode/file.evm 50 | ``` 51 | 52 | ```bash 53 | # Generate JSON report in 'report.json' for creation-code source file 54 | java -jar EtherSolve.jar -c -j -o report.json path/to/bytecode/file.evm 55 | ``` 56 | 57 | ```bash 58 | # Generate HTML report in 'index.html' for runtime-code source file 59 | java -jar EtherSolve.jar -r -H -o index.html path/to/bytecode/file.evm 60 | ``` 61 | 62 | ```bash 63 | # Generate HTML report in 'index.html' for creation-code source file with Re-entrancy detection analysis 64 | java -jar EtherSolve.jar -c -H -o index.html --re-entrancy path/to/bytecode/file.evm 65 | ``` 66 | 67 | ### Gradle 68 | 69 | To build from source and run the project you should use gradle (minimum Gradle supported version: *5.2.1*). To build from source **Java 8** is required. 70 | 71 | EtherSolve is composed of five modules. 72 | - **Core**: it contains the main procedures to parse the bytecode and build the CFG. 73 | - **Abi**: it contains the validation methods (see the paper) and a prototype for an Abi extraction. 74 | - **UI**: it contains the procedures to graphically represent the CFG using Graphviz and to produce the HTML report. It also contains the command line interface and the main class of the tool. 75 | - **SecurityAnalysis**: it contains the security analyser and the dataset tester used for the comparison with the [SolidiFI](https://arxiv.org/pdf/2005.11613.pdf) survey. 76 | - **WebApp**: it contains a simple SpringBoot server to provide analysis via APIs (unmantained). 77 | 78 | The following Gradle tasks are available. 79 | - `bootRun`: run the project as a Spring Boot application. 80 | - `runCoreMain`: run the main class of the Core module, that analyses a sample bytecode written in the `Main` class, producing a JSON output. 81 | - `runIRExtractor`: run the extractor to get the intermediate representation used for the analysis. 82 | - `runSecurityAnalyser`: run the main class of the Core module, that analyses a sample bytecode. 83 | - `jar`: build a JAR for each module. The only JAR having an entry point is the one of the UI module. The artifact output can be found in the `UI/build/libs` folder. 84 | 85 | For the full list run `gradle tasks`. 86 | 87 | ## Replication Package 88 | 89 | The material to replicate the results presented in the JSS 2023 publication can be found in the [JSS Replication Package](https://zenodo.org/record/7545056). 90 | -------------------------------------------------------------------------------- /SecurityAnalysis/build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id 'java' 3 | } 4 | 5 | group 'org.example' 6 | version '1.0-SNAPSHOT' 7 | 8 | repositories { 9 | mavenCentral() 10 | } 11 | 12 | dependencies { 13 | compile project(':Core') 14 | testCompile group: 'junit', name: 'junit', version: '4.12' 15 | } 16 | 17 | task runSecurityAnalyser(type: JavaExec) { 18 | group = "Execution" 19 | description = "Run the main class of Core module, which analyses a sample bytecode" 20 | classpath = sourceSets.main.runtimeClasspath 21 | main = "main.SecurityAnalyser" 22 | } -------------------------------------------------------------------------------- /SecurityAnalysis/src/main/java/analysers/StoreAccessAfterUnsafeCall.java: -------------------------------------------------------------------------------- 1 | package analysers; 2 | 3 | import main.SecurityAnalysisReport; 4 | import main.SecurityDetection; 5 | import main.SecurityVulnerability; 6 | import opcodes.Opcode; 7 | import opcodes.stackOpcodes.SLoadOpcode; 8 | import opcodes.stackOpcodes.SStoreOpcode; 9 | import opcodes.systemOpcodes.CallOpcode; 10 | import parseTree.Contract; 11 | import parseTree.SymbolicExecution.StackExceededException; 12 | import parseTree.SymbolicExecution.SymbolicExecutionStack; 13 | import parseTree.SymbolicExecution.UnknownStackElementException; 14 | import parseTree.cfg.BasicBlock; 15 | import parseTree.cfg.BasicBlockType; 16 | import parseTree.cfg.Cfg; 17 | 18 | import java.util.HashSet; 19 | import java.util.Stack; 20 | 21 | public class StoreAccessAfterUnsafeCall { 22 | private static final String SLOAD_MESSAGE = "Store access in read mode after an unsafe call"; 23 | private static final String SSTORE_MESSAGE = "Store access in write mode after an unsafe call; this could bring to a re-entrancy vulnerability"; 24 | 25 | 26 | public static void analyse(Contract contract, SecurityAnalysisReport report) { 27 | // Get the CFG 28 | Cfg runtimeCfg = contract.getRuntimeCfg(); 29 | // Gather the blocks containing the CALL opcode 30 | for (BasicBlock bb : runtimeCfg){ 31 | if (bb.checkPattern(new CallOpcode(0)) && bb.getType() == BasicBlockType.COMMON){ 32 | // Check if it is an unsafe call 33 | if (isUnsafeCall(bb)){ 34 | // Check if it can reach an SSTORE or an SLOAD opcode through DFS 35 | BasicBlock currentBlock; 36 | Stack queue = new Stack<>(); 37 | queue.add(bb); 38 | HashSet visited = new HashSet<>(); 39 | while (! queue.isEmpty()){ 40 | currentBlock = queue.pop(); 41 | visited.add(currentBlock); 42 | 43 | if (currentBlock.checkPattern(new SLoadOpcode(0))){ 44 | Opcode sLoadOpcode = null; 45 | for (Opcode o : currentBlock) 46 | if (o instanceof SLoadOpcode) 47 | sLoadOpcode = o; 48 | report.addDetection(new SecurityDetection(SecurityVulnerability.STORE_READ_AFTER_UNSAFE_CALL, sLoadOpcode, SLOAD_MESSAGE)); 49 | } 50 | if (currentBlock.checkPattern(new SStoreOpcode(0))){ 51 | Opcode sStoreOpcode = null; 52 | for (Opcode o : currentBlock) 53 | if (o instanceof SStoreOpcode) 54 | sStoreOpcode = o; 55 | report.addDetection(new SecurityDetection(SecurityVulnerability.STORE_WRITE_AFTER_UNSAFE_CALL, sStoreOpcode, SSTORE_MESSAGE)); 56 | } 57 | 58 | for (BasicBlock successor : currentBlock.getSuccessors()) 59 | if (! visited.contains(successor) && successor.getType() == BasicBlockType.COMMON) 60 | queue.add(successor); 61 | } 62 | } 63 | 64 | } 65 | 66 | } 67 | } 68 | 69 | private static boolean isUnsafeCall(BasicBlock bb) { 70 | SymbolicExecutionStack stack = new SymbolicExecutionStack(); 71 | for (Opcode o : bb){ 72 | if (o instanceof CallOpcode){ 73 | try { 74 | stack.peek(1); 75 | return false; 76 | } catch (UnknownStackElementException e) { 77 | return true; 78 | } 79 | } else { 80 | try { 81 | stack.executeOpcode(o); 82 | } catch (StackExceededException | IndexOutOfBoundsException e) { 83 | //Message.printWarning("Cannot determine safeness of block " + bb.getOffset()); 84 | return true; 85 | } 86 | } 87 | } 88 | return true; 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /SecurityAnalysis/src/main/java/analysers/TxOrigin.java: -------------------------------------------------------------------------------- 1 | package analysers; 2 | 3 | import main.SecurityAnalysisReport; 4 | import main.SecurityDetection; 5 | import main.SecurityVulnerability; 6 | import opcodes.Opcode; 7 | import opcodes.arithmeticOpcodes.binaryArithmeticOpcodes.AndOpcode; 8 | import opcodes.arithmeticOpcodes.binaryArithmeticOpcodes.EQOpcode; 9 | import opcodes.arithmeticOpcodes.unaryArithmeticOpcodes.IsZeroOpcode; 10 | import opcodes.controlFlowOpcodes.JumpIOpcode; 11 | import opcodes.environmentalOpcodes.OriginOpcode; 12 | import opcodes.stackOpcodes.PushOpcode; 13 | import parseTree.Contract; 14 | import parseTree.cfg.BasicBlock; 15 | import parseTree.cfg.BasicBlockType; 16 | import parseTree.cfg.Cfg; 17 | 18 | public class TxOrigin { 19 | private static final String TX_ORIGIN_MESSAGE = "tx.origin used as authentication check"; 20 | private static final Opcode origin = new OriginOpcode(0); 21 | private static final Opcode push20 = new PushOpcode(0, 20); 22 | private static final Opcode and = new AndOpcode(0); 23 | private static final Opcode eq = new EQOpcode(0); 24 | private static final Opcode iszero = new IsZeroOpcode(0); 25 | private static final Opcode push2 = new PushOpcode(0, 2); 26 | private static final Opcode jumpi = new JumpIOpcode(0); 27 | private static final Opcode[] pattern1 = {origin, push20, and, eq, push2, jumpi}; 28 | private static final Opcode[] pattern2 = {origin, push20, and, eq, iszero, iszero, push2, jumpi}; 29 | 30 | 31 | public static void analyse(Contract contract, SecurityAnalysisReport report) { 32 | // Get the CFG 33 | Cfg runtimeCfg = contract.getRuntimeCfg(); 34 | // Gather the blocks containing the ORIGIN opcode 35 | for (BasicBlock bb : runtimeCfg) { 36 | if (bb.checkPattern(new OriginOpcode(0)) && bb.getType() == BasicBlockType.COMMON) { 37 | // Searching for patterns: ORIGIN, PUSH20 0XFFF..., AND, EQ, (ISZERO, ISZERO,)fffffe PUSH2 ..., JUMPI 38 | if ((bb.checkPattern(pattern1) || bb.checkPattern(pattern2)) && bb.getType() == BasicBlockType.COMMON) { 39 | report.addDetection(new SecurityDetection(SecurityVulnerability.TX_ORIGIN_AS_AUTHENTICATION, getOrigin(bb), TX_ORIGIN_MESSAGE)); 40 | } else if (taintCheck(bb)) { 41 | // Taint analysis returns TRUE 42 | report.addDetection(new SecurityDetection(SecurityVulnerability.TX_ORIGIN_AS_AUTHENTICATION, getOrigin(bb), TX_ORIGIN_MESSAGE)); 43 | } 44 | } 45 | } 46 | } 47 | 48 | private static boolean taintCheck(BasicBlock bb) { 49 | int pos = -1; 50 | for (Opcode o : bb) { 51 | if (o instanceof OriginOpcode && pos < 0) { 52 | // ORIGIN opcode found 53 | pos = 0; 54 | } else { 55 | // tracking 56 | int add = o.getStackGenerated(); 57 | int remove = o.getStackConsumed(); 58 | if (add > 0 && remove == 0) { 59 | // OP adds only 60 | pos += add; 61 | } else if (add == 0 && remove > 0) { 62 | // OP removes only 63 | pos -= remove; 64 | if (pos < 0) { 65 | // check for JUMPI 66 | return o instanceof JumpIOpcode; 67 | } 68 | } else if (add > 0 && remove > 0) { 69 | pos -= remove; 70 | if (pos < 0) { 71 | pos = 0; 72 | } else { 73 | pos += add; 74 | } 75 | } 76 | } 77 | } 78 | return false; 79 | } 80 | 81 | private static Opcode getOrigin(BasicBlock bb) { 82 | for (Opcode o : bb) { 83 | if (o instanceof OriginOpcode) { 84 | return o; 85 | } 86 | } 87 | 88 | return null; 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /SecurityAnalysis/src/main/java/main/SecurityAnalysisReport.java: -------------------------------------------------------------------------------- 1 | package main; 2 | 3 | import parseTree.Contract; 4 | 5 | import java.util.HashSet; 6 | import java.util.Iterator; 7 | import java.util.Spliterator; 8 | import java.util.function.Consumer; 9 | 10 | public class SecurityAnalysisReport implements Iterable { 11 | private final Contract contract; 12 | private final HashSet detections; 13 | private long analysisTimeMillis; 14 | 15 | public SecurityAnalysisReport(Contract contract) { 16 | this.contract = contract; 17 | this.analysisTimeMillis = System.currentTimeMillis(); 18 | this.detections = new HashSet<>(); 19 | } 20 | 21 | public Contract getContract() { 22 | return contract; 23 | } 24 | 25 | public HashSet getDetections() { 26 | return detections; 27 | } 28 | 29 | public long getAnalysisTimeMillis() { 30 | return analysisTimeMillis; 31 | } 32 | 33 | public void addDetection(SecurityDetection detection){ 34 | this.detections.add(detection); 35 | } 36 | 37 | public void stopTimer(){ 38 | this.analysisTimeMillis = System.currentTimeMillis() - this.analysisTimeMillis; 39 | } 40 | 41 | @Override 42 | public String toString() { 43 | return "main.SecurityAnalysisReport{\n\t" + 44 | "detections=" + detections + 45 | ",\n\tanalysisTimeMillis=" + analysisTimeMillis + 46 | "\n}"; 47 | } 48 | 49 | public int countDetections(SecurityVulnerability... vulnerabilities) { 50 | int count = 0; 51 | for (SecurityDetection d : this.detections) 52 | for (SecurityVulnerability v : vulnerabilities) 53 | if (d.getVulnerability() == v) 54 | count++; 55 | return count; 56 | } 57 | 58 | @Override 59 | public Iterator iterator() { 60 | return detections.iterator(); 61 | } 62 | 63 | @Override 64 | public void forEach(Consumer super SecurityDetection> action) { 65 | detections.forEach(action); 66 | } 67 | 68 | @Override 69 | public Spliterator spliterator() { 70 | return detections.spliterator(); 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /SecurityAnalysis/src/main/java/main/SecurityDetection.java: -------------------------------------------------------------------------------- 1 | package main; 2 | 3 | import opcodes.Opcode; 4 | 5 | public class SecurityDetection implements Comparable { 6 | private final SecurityVulnerability vulnerability; 7 | private final Opcode location; 8 | private final String message; 9 | 10 | public SecurityDetection(SecurityVulnerability vulnerability, Opcode location) { 11 | this(vulnerability, location, ""); 12 | } 13 | 14 | public SecurityDetection(SecurityVulnerability vulnerability, Opcode location, String message) { 15 | this.vulnerability = vulnerability; 16 | this.location = location; 17 | this.message = message; 18 | } 19 | 20 | public SecurityVulnerability getVulnerability() { 21 | return vulnerability; 22 | } 23 | 24 | public Opcode getLocation() { 25 | return location; 26 | } 27 | 28 | public String getMessage() { 29 | return message; 30 | } 31 | 32 | @Override 33 | public String toString() { 34 | return String.format("%s at opcode %s - %s", vulnerability.getName(), location, message); 35 | } 36 | 37 | @Override 38 | public int compareTo(SecurityDetection other) { 39 | return Long.compare(this.location.getOffset(), other.location.getOffset()); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /SecurityAnalysis/src/main/java/main/SecurityVulnerability.java: -------------------------------------------------------------------------------- 1 | package main; 2 | 3 | public enum SecurityVulnerability { 4 | STORE_READ_AFTER_UNSAFE_CALL("Store read after unsafe call"), 5 | STORE_WRITE_AFTER_UNSAFE_CALL("Store write after unsafe call"), 6 | TX_ORIGIN_AS_AUTHENTICATION("tx.origin used as authentication check"); 7 | 8 | private final String name; 9 | 10 | SecurityVulnerability(String name) { 11 | this.name = name; 12 | } 13 | 14 | public String getName() { 15 | return name; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /SecurityAnalysis/src/main/java/main/SnippetsTester.java: -------------------------------------------------------------------------------- 1 | package main; 2 | 3 | import parseTree.Contract; 4 | import parseTree.NotSolidityContractException; 5 | 6 | import java.io.BufferedReader; 7 | import java.io.IOException; 8 | import java.nio.file.Files; 9 | import java.nio.file.Paths; 10 | 11 | public class SnippetsTester { 12 | 13 | private static final String FOLDER = "outputs/re-entrancy_dataset/snippets_evm/"; 14 | private static final int N = 42; 15 | 16 | public static void main(String[] args) { 17 | for (int i = 1; i <= N; i++) { 18 | // Read the bytecode from the file 19 | String bytecode; 20 | try (BufferedReader br = Files.newBufferedReader(Paths.get(FOLDER + i + ".evm"))) { 21 | bytecode = br.readLine(); 22 | } catch (IOException e) { 23 | System.err.format("Error reading file %s: %s\n", i + ".evm", e); 24 | continue; 25 | } 26 | try { 27 | // Analyse the contract 28 | Contract contract = new Contract("Contract-" + i, bytecode, false); 29 | SecurityAnalysisReport report = SecurityAnalyser.analyse(contract); 30 | System.out.println("Contract-" + i + ": " + report.countDetections(SecurityVulnerability.STORE_WRITE_AFTER_UNSAFE_CALL)); 31 | } catch (NotSolidityContractException e) { 32 | System.err.format("Error creating contract for sample %s\n", i); 33 | } 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /UI/build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id 'java' 3 | } 4 | 5 | group 'org.example' 6 | version '1.0-SNAPSHOT' 7 | 8 | sourceCompatibility = 1.8 9 | 10 | repositories { 11 | mavenCentral() 12 | } 13 | 14 | dependencies { 15 | testCompile group: 'junit', name: 'junit', version: '4.12' 16 | compile project(':Core') 17 | compile project(':SecurityAnalysis') 18 | compile 'info.picocli:picocli:4.4.0' 19 | annotationProcessor 'info.picocli:picocli-codegen:4.4.0' 20 | } 21 | 22 | jar { 23 | manifest { 24 | attributes 'Main-Class': 'cli.MainCLI' 25 | } 26 | from { configurations.compile.collect { it.isDirectory() ? it : zipTree(it) } } 27 | baseName 'EtherSolve' 28 | } 29 | -------------------------------------------------------------------------------- /UI/src/main/java/graphviz/GVBlock.java: -------------------------------------------------------------------------------- 1 | package graphviz; 2 | 3 | import parseTree.cfg.BasicBlock; 4 | import parseTree.cfg.BasicBlockType; 5 | 6 | public class GVBlock { 7 | private final BasicBlock mBasicBlock; 8 | 9 | private GVBlock(){ 10 | this(new BasicBlock()); 11 | } 12 | 13 | public GVBlock(BasicBlock mBasicBlock) { 14 | this.mBasicBlock = mBasicBlock; 15 | } 16 | 17 | @Override 18 | public boolean equals(Object o) { 19 | if (this == o) return true; 20 | if (o == null || getClass() != o.getClass()) return false; 21 | GVBlock that = (GVBlock) o; 22 | return mBasicBlock.equals(that.mBasicBlock); 23 | } 24 | 25 | @Override 26 | public int hashCode() { 27 | return mBasicBlock.hashCode(); 28 | } 29 | 30 | @Override 31 | public String toString() { 32 | StringBuilder sb = new StringBuilder(); 33 | sb.append(this.getId()); 34 | 35 | sb.append(" ["); 36 | sb.append("label=\""); 37 | sb.append(mBasicBlock.toString().replace("\n", "\\l")); 38 | sb.append("\\l\" "); 39 | 40 | if(this.isDispatcherBlock()) 41 | sb.append("fillcolor=lemonchiffon "); 42 | if (this.isRootBlock()) 43 | sb.append("shape=Msquare fillcolor=gold "); 44 | else if (this.isExitBlock()) 45 | sb.append("fillcolor=crimson "); 46 | else if (this.isLeafBlock()) 47 | sb.append("shape=Msquare color=crimson "); 48 | else if (this.isFallBackBlock()) 49 | sb.append("fillcolor=orange "); 50 | 51 | sb.append("]"); 52 | return sb.toString(); 53 | } 54 | 55 | public String getId(){ 56 | return String.valueOf(mBasicBlock.getOffset()); 57 | } 58 | 59 | public boolean isDispatcherBlock() { 60 | return mBasicBlock.getType() == BasicBlockType.DISPATCHER; 61 | } 62 | 63 | public boolean isFallBackBlock() { 64 | return mBasicBlock.getType() == BasicBlockType.FALLBACK; 65 | } 66 | 67 | public boolean isRootBlock() { 68 | return mBasicBlock.getPredecessors().isEmpty(); 69 | } 70 | 71 | public boolean isLeafBlock() { 72 | return mBasicBlock.getSuccessors().isEmpty() || (mBasicBlock.getType() != BasicBlockType.EXIT && 73 | mBasicBlock.getSuccessors().get(0).getType() == BasicBlockType.EXIT); 74 | } 75 | 76 | public boolean isExitBlock() { 77 | return mBasicBlock.getType() == BasicBlockType.EXIT; 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /UI/src/main/java/graphviz/GVEdge.java: -------------------------------------------------------------------------------- 1 | package graphviz; 2 | 3 | public class GVEdge{ 4 | GVBlock from; 5 | GVBlock to; 6 | 7 | public GVEdge(GVBlock from, GVBlock to) { 8 | this.from = from; 9 | this.to = to; 10 | } 11 | 12 | public GVBlock getFrom() { 13 | return from; 14 | } 15 | 16 | public GVBlock getTo() { 17 | return to; 18 | } 19 | 20 | @Override 21 | public boolean equals(Object o) { 22 | if (this == o) return true; 23 | if (o == null || getClass() != o.getClass()) return false; 24 | GVEdge that = (GVEdge) o; 25 | return from.equals(that.from) && to.equals(that.to); 26 | } 27 | 28 | @Override 29 | public int hashCode() { 30 | return from.hashCode() ^ to.hashCode(); 31 | } 32 | 33 | @Override 34 | public String toString() { 35 | return from.getId() + " -> " + to.getId(); 36 | } 37 | 38 | } 39 | -------------------------------------------------------------------------------- /UI/src/main/java/graphviz/GVGraph.java: -------------------------------------------------------------------------------- 1 | package graphviz; 2 | 3 | import java.util.HashSet; 4 | import java.util.Set; 5 | 6 | public class GVGraph { 7 | private static final String GRAPH_NAME = "G"; 8 | private static final String PROPRIETIES = "bgcolor=transparent rankdir=UD;"; 9 | private static final String DEFAULT_NODE_STYLE = "shape=box style=filled color=black fillcolor=white " + //snow2 10 | "fontname=arial fontcolor=black"; 11 | private static final String FINAL_STATE_NODE_STYLE = "shape = doublecircle, color=black, fontcolor=black"; 12 | 13 | Set blocks; 14 | Set edges; 15 | 16 | public GVGraph() { 17 | blocks = new HashSet<>(); 18 | edges = new HashSet<>(); 19 | } 20 | 21 | public void addBlock(GVBlock block){ 22 | blocks.add(block); 23 | } 24 | 25 | public void addEdge(GVEdge edge){ 26 | blocks.add(edge.getFrom()); 27 | blocks.add(edge.getTo()); 28 | edges.add(edge); 29 | } 30 | 31 | public void addEdge(GVBlock from, GVBlock to){ 32 | GVEdge edge = new GVEdge(from, to); 33 | addEdge(edge); 34 | } 35 | 36 | public Set getEdges() { 37 | return edges; 38 | } 39 | 40 | public Set getBlocks(){ 41 | return blocks; 42 | } 43 | 44 | @Override 45 | public String toString() { 46 | StringBuilder s = new StringBuilder("digraph " + GRAPH_NAME + " {\n" + 47 | PROPRIETIES); //+ "\n" + 48 | // "node [shape = point, color=white, fontcolor=white]; start;\n"; 49 | 50 | s.append("\nnode [" + DEFAULT_NODE_STYLE + "];\n"); 51 | // Add nodes 52 | for (GVBlock block : blocks) { 53 | s.append(block); 54 | s.append(";\n"); 55 | } 56 | 57 | // Add edges 58 | for (GVEdge edge : edges) { 59 | s.append(edge); 60 | s.append(";\n"); 61 | } 62 | 63 | s.append("}"); 64 | return s.toString(); 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /UI/src/main/java/graphviz/MainGV.java: -------------------------------------------------------------------------------- 1 | package graphviz; 2 | 3 | import SolidityInfo.SolidityVersionUnknownException; 4 | import parseTree.Contract; 5 | import parseTree.NotSolidityContractException; 6 | import parseTree.cfg.Cfg; 7 | 8 | public class MainGV { 9 | 10 | public static void main(String[] args){ 11 | String ottOtt = "608060405260aa60005534801561001557600080fd5b50610184806100256000396000f3fe608060405234801561001057600080fd5b506004361061004c5760003560e01c80634b3df200146100515780635bfd987d1461006f578063c2985578146100b1578063febb0f7e146100cf575b600080fd5b6100596100ed565b6040518082815260200191505060405180910390f35b61009b6004803603602081101561008557600080fd5b810190808035906020019092919050505061011d565b6040518082815260200191505060405180910390f35b6100b961012a565b6040518082815260200191505060405180910390f35b6100d761013c565b6040518082815260200191505060405180910390f35b6000806000815480929190600101919050555060aa600054141561011557600054905061011a565b600080fd5b90565b6000816088019050919050565b600061013761cccc61011d565b905090565b600061014961dddd61011d565b90509056fea2646970667358221220e619b234c1887f9b10b567ee21364dbf523a19001c8c47a33049907c0398563164736f6c63430006040033"; 12 | 13 | System.out.println("START"); 14 | long pre = System.currentTimeMillis(); 15 | Contract contract = null; 16 | try { 17 | contract = new Contract("OttOtt", ottOtt, false); 18 | } catch (NotSolidityContractException e) { 19 | e.printStackTrace(); 20 | return; 21 | } 22 | Cfg generated_cfg = contract.getRuntimeCfg(); 23 | long post = System.currentTimeMillis(); 24 | System.out.println("ELAPSED TIME: " + (post-pre)); 25 | 26 | String solidity_version; 27 | try { 28 | solidity_version = contract.getExactSolidityVersion(); 29 | System.out.println("Solidity version: " + solidity_version); 30 | } catch (SolidityVersionUnknownException e) { 31 | solidity_version = "unknown or before 0.5.9"; 32 | } 33 | 34 | System.out.println("Constructor CFG remaining data: \"" + contract.getConstructorCfg().getRemainingData() + '"'); 35 | System.out.println("Runtime CFG remaining data: \"" + contract.getRuntimeCfg().getRemainingData() + '"'); 36 | System.out.println("Constructor remaining data: \"" + contract.getConstructorRemainingData() + '"'); 37 | System.out.println("Runtime CFG build report:\n\t" + contract.getRuntimeCfg().getBuildReport().toString().replace("\n", "\n\t")); 38 | 39 | String svgPath = CFGPrinter.renderAndSave(generated_cfg); 40 | String reportPath = CFGPrinter.createReport(svgPath, solidity_version, post-pre, generated_cfg.getRemainingData(), generated_cfg.getBuildReport()); 41 | CFGPrinter.openHtmlReport(reportPath); 42 | } 43 | 44 | } 45 | -------------------------------------------------------------------------------- /WebApp/build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id 'java' 3 | id 'org.springframework.boot' version '2.0.5.RELEASE' 4 | id 'io.spring.dependency-management' version '1.0.7.RELEASE' 5 | } 6 | 7 | group 'org.example' 8 | version '1.0-SNAPSHOT' 9 | 10 | repositories { 11 | mavenCentral() 12 | maven { url 'https://jitpack.io' } 13 | } 14 | 15 | dependencies { 16 | testCompile group: 'junit', name: 'junit', version: '4.12' 17 | 18 | compile project(':Core') 19 | compile project(':Abi') 20 | compile project(':UI') 21 | 22 | implementation 'com.google.code.gson:gson:2.8.6' 23 | 24 | implementation 'org.springframework.boot:spring-boot-dependencies:2.0.5.RELEASE' 25 | implementation 'org.springframework.boot:spring-boot-starter-web' 26 | 27 | testImplementation 'org.springframework.boot:spring-boot-starter-test' 28 | 29 | components { 30 | withModule('org.springframework:spring-beans') { 31 | allVariants { 32 | withDependencyConstraints { 33 | // Need to patch constraints because snakeyaml is an optional dependency 34 | it.findAll { it.name == 'snakeyaml' }.each { it.version { strictly '1.19' } } 35 | } 36 | } 37 | } 38 | } 39 | } 40 | 41 | bootJar { 42 | mainClassName = 'server.App' 43 | } 44 | -------------------------------------------------------------------------------- /WebApp/src/main/java/json_utils/PostRequestBody.java: -------------------------------------------------------------------------------- 1 | package json_utils; 2 | 3 | public class PostRequestBody { 4 | private final String address; 5 | private final String bytecode; 6 | private final boolean isOnlyRuntime; 7 | private final String name; 8 | 9 | public PostRequestBody(String address, String bytecode, boolean isOnlyRuntime, String name) { 10 | this.address = address; 11 | this.bytecode = bytecode; 12 | this.isOnlyRuntime = isOnlyRuntime; 13 | this.name = name; 14 | } 15 | 16 | public String getAddress() { 17 | return address; 18 | } 19 | 20 | public String getBytecode() { 21 | return bytecode; 22 | } 23 | 24 | public boolean isOnlyRuntime() { 25 | return isOnlyRuntime; 26 | } 27 | 28 | public String getName() { 29 | return name; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /WebApp/src/main/java/json_utils/RenderRequestBody.java: -------------------------------------------------------------------------------- 1 | package json_utils; 2 | 3 | public class RenderRequestBody { 4 | private final String dot; 5 | 6 | public RenderRequestBody(String dot) { 7 | this.dot = dot; 8 | } 9 | 10 | public String getDot() { 11 | return dot; 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /WebApp/src/main/java/json_utils/Response.java: -------------------------------------------------------------------------------- 1 | package json_utils; 2 | 3 | public class Response { 4 | private final String status; 5 | private final String message; 6 | private final Object result; 7 | 8 | public Response(String status, String message, Object result) { 9 | this.status = status; 10 | this.message = message; 11 | this.result = result; 12 | } 13 | 14 | public String getStatus() { 15 | return status; 16 | } 17 | 18 | public String getMessage() { 19 | return message; 20 | } 21 | 22 | public Object getResult() { 23 | return result; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /WebApp/src/main/java/processing/AddressProcessor.java: -------------------------------------------------------------------------------- 1 | package processing; 2 | 3 | import etherscan.EtherScanDownloader; 4 | import json_utils.Response; 5 | 6 | import java.io.IOException; 7 | 8 | public class AddressProcessor { 9 | private final static Response CONTRACT_DOWNLOAD_ERROR = new Response("0", 10 | "A critical error occurred during contract download", 11 | null); 12 | private final static Response CONTRACT_ADDRESS_FORMAT_ERROR = new Response("0", 13 | "Address is malformed", 14 | null); 15 | 16 | public static Response process(String name, String address){ 17 | try { 18 | if (! address.startsWith("0x")) 19 | address = "0x" + address; 20 | if (! address.matches("0x([0-9a-fA-F]{40})")) 21 | return CONTRACT_ADDRESS_FORMAT_ERROR; 22 | String bytecode = EtherScanDownloader.getContractBytecode(address); 23 | return BytecodeProcessor.process(name, bytecode, true, address); 24 | } catch (IOException e) { 25 | return CONTRACT_DOWNLOAD_ERROR; 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /WebApp/src/main/java/processing/BytecodeProcessor.java: -------------------------------------------------------------------------------- 1 | package processing; 2 | 3 | import com.google.gson.JsonElement; 4 | import com.google.gson.JsonObject; 5 | import com.google.gson.JsonPrimitive; 6 | import graphviz.CFGPrinter; 7 | import json_utils.Response; 8 | import parseTree.Contract; 9 | import parseTree.NotSolidityContractException; 10 | import utils.JsonExporter; 11 | 12 | public class BytecodeProcessor { 13 | private final static Response NOT_SOLIDITY_CONTRACT_ERROR = new Response("0", 14 | "Source bytecode is not a Solidity contract", 15 | null); 16 | private final static Response CONTRACT_ANALYSIS_ERROR = new Response("0", 17 | "A critical error occurred during contract analysis", 18 | null); 19 | 20 | public static Response process(String name, String bytecode, boolean isOnlyRuntime, String address) { 21 | if (bytecode.startsWith("0x")) 22 | bytecode = bytecode.substring(2); 23 | try { 24 | Contract contract = new Contract(name, bytecode, isOnlyRuntime, address); 25 | JsonObject contractJson = (JsonObject) new JsonExporter().getJsonTree(contract); 26 | contractJson.add("dotNotation", new JsonPrimitive(CFGPrinter.getDotNotation(contract.getRuntimeCfg()))); 27 | return new Response("1", 28 | "Analysis completed", 29 | contractJson); 30 | } catch (NotSolidityContractException e) { 31 | return NOT_SOLIDITY_CONTRACT_ERROR; 32 | } catch (Exception e) { 33 | e.printStackTrace(); 34 | return CONTRACT_ANALYSIS_ERROR; 35 | } 36 | } 37 | 38 | public static Response process(String name, String bytecode, boolean isOnlyRuntime){ 39 | return process(name, bytecode, isOnlyRuntime, ""); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /WebApp/src/main/java/processing/GraphvizException.java: -------------------------------------------------------------------------------- 1 | package processing; 2 | 3 | public class GraphvizException extends Exception { 4 | } 5 | -------------------------------------------------------------------------------- /WebApp/src/main/java/processing/GraphvizProcessor.java: -------------------------------------------------------------------------------- 1 | package processing; 2 | 3 | import graphviz.CFGPrinter; 4 | 5 | public class GraphvizProcessor { 6 | public static String process(String dotNotation) throws GraphvizException{ 7 | return CFGPrinter.renderDotToSvgString(dotNotation); 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /WebApp/src/main/java/server/ApiController.java: -------------------------------------------------------------------------------- 1 | package server; 2 | 3 | import com.google.gson.Gson; 4 | import json_utils.PostRequestBody; 5 | import json_utils.Response; 6 | import org.springframework.web.bind.MissingServletRequestParameterException; 7 | import org.springframework.web.bind.annotation.*; 8 | import processing.AddressProcessor; 9 | import processing.BytecodeProcessor; 10 | 11 | import java.util.concurrent.atomic.AtomicInteger; 12 | 13 | 14 | @RestController 15 | @RequestMapping("/api") 16 | public class ApiController { 17 | private static final AtomicInteger CONTACT_COUNTER = new AtomicInteger(0); 18 | private static final Gson gson = new Gson(); 19 | private static final Response MISSING_INVALID_PARAMS_ERROR = new Response("0", 20 | "Missing/invalid argument. Request needs to have at least: \"address\" (String) with no other arguments or \"bytecode\" (String) with \"isOnlyRuntime\" (Boolean)", 21 | null); 22 | 23 | /* EXAMPLE 24 | 25 | @GetMapping(value = "/api") 26 | public String getRequest(@RequestParam(required = false) String address, 27 | @RequestParam(defaultValue = "Contract") String name){ 28 | return "APIAddress: " + address + "Name: " + name; 29 | }*/ 30 | 31 | @GetMapping 32 | public String getRequest(@RequestParam String address, @RequestParam(required = false) String name){ 33 | Response response; 34 | if (name == null) 35 | name = "Contract" + CONTACT_COUNTER.getAndIncrement(); 36 | response = AddressProcessor.process(name, address); 37 | return gson.toJson(response); 38 | } 39 | 40 | @PostMapping(consumes = "application/json", produces = "application/json") 41 | public String postRequest(@RequestBody String requestBody){ 42 | PostRequestBody parsedRequestBody; 43 | parsedRequestBody = gson.fromJson(requestBody, PostRequestBody.class); 44 | // System.out.println(String.format("address:%s\nbytecode:%s\nisOnlyRuntime%s\n", parsedRequestBody.getAddress(), parsedRequestBody.getBytecode(), parsedRequestBody.isOnlyRuntime())); 45 | Response response; 46 | 47 | String name; 48 | if (parsedRequestBody.getName() == null) 49 | name = "Contract" + CONTACT_COUNTER.getAndIncrement(); 50 | else 51 | name = parsedRequestBody.getName(); 52 | 53 | if (parsedRequestBody.getAddress() != null) 54 | response = AddressProcessor.process(name, parsedRequestBody.getAddress()); 55 | else if (parsedRequestBody.getBytecode() != null) 56 | response = BytecodeProcessor.process(name, parsedRequestBody.getBytecode(), parsedRequestBody.isOnlyRuntime()); 57 | else 58 | response = MISSING_INVALID_PARAMS_ERROR; 59 | return gson.toJson(response); 60 | } 61 | 62 | @ExceptionHandler({MissingServletRequestParameterException.class, IllegalStateException.class}) 63 | public String requestFormatError() { 64 | return gson.toJson(MISSING_INVALID_PARAMS_ERROR); 65 | } 66 | } 67 | 68 | -------------------------------------------------------------------------------- /WebApp/src/main/java/server/App.java: -------------------------------------------------------------------------------- 1 | package server; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | @SpringBootApplication 7 | public class App { 8 | 9 | public static void main(String[] args) { 10 | SpringApplication.run(App.class, args); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /WebApp/src/main/java/server/GuiController.java: -------------------------------------------------------------------------------- 1 | package server; 2 | 3 | import org.springframework.web.bind.annotation.GetMapping; 4 | import org.springframework.web.bind.annotation.RestController; 5 | 6 | @RestController("/") 7 | public class GuiController { 8 | 9 | @GetMapping 10 | public String getRequest(){ 11 | return "GUI"; 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /WebApp/src/main/java/server/RenderController.java: -------------------------------------------------------------------------------- 1 | package server; 2 | 3 | import com.google.gson.Gson; 4 | import json_utils.RenderRequestBody; 5 | import json_utils.Response; 6 | import org.springframework.web.bind.annotation.PostMapping; 7 | import org.springframework.web.bind.annotation.RequestBody; 8 | import org.springframework.web.bind.annotation.RequestMapping; 9 | import org.springframework.web.bind.annotation.RestController; 10 | import processing.GraphvizException; 11 | import processing.GraphvizProcessor; 12 | 13 | @RestController 14 | @RequestMapping("/render") 15 | public class RenderController { 16 | private final static Response GRAPHVIZ_ERROR = new Response("0", 17 | "A critical error occurred during graphviz render", 18 | null); 19 | private static final Gson gson = new Gson(); 20 | 21 | @PostMapping(consumes = "application/json", produces = "application/json") 22 | public String postRequest(@RequestBody String requestBody){ 23 | RenderRequestBody parsedRequestBody; 24 | parsedRequestBody = gson.fromJson(requestBody, RenderRequestBody.class); 25 | 26 | String dotNotation = parsedRequestBody.getDot(); 27 | Response response; 28 | try { 29 | String svg = GraphvizProcessor.process(dotNotation); 30 | response = new Response("1", "Graphviz render completed", svg); 31 | } catch (GraphvizException e) { 32 | response = GRAPHVIZ_ERROR; 33 | } 34 | 35 | return gson.toJson(response); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /WebApp/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | server: 2 | port: 8081 -------------------------------------------------------------------------------- /artifact/EtherSolve.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SeUniVr/EtherSolve/59fe4412f7230d9ee1047b25fbcf30b63cb89488/artifact/EtherSolve.jar -------------------------------------------------------------------------------- /build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id 'java' 3 | } 4 | 5 | group 'org.example' 6 | version '1.0-SNAPSHOT' 7 | 8 | sourceCompatibility = 1.8 9 | 10 | repositories { 11 | mavenCentral() 12 | } 13 | 14 | dependencies { 15 | testCompile group: 'junit', name: 'junit', version: '4.12' 16 | } -------------------------------------------------------------------------------- /doc/deprecated-list.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Deprecated List 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 17 | 18 | 19 | 20 | 21 | 22 | 34 | 35 | JavaScript is disabled on your browser. 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | Skip navigation links 45 | 46 | 47 | 48 | 49 | Overview 50 | Package 51 | Class 52 | Tree 53 | Deprecated 54 | Index 55 | Help 56 | 57 | 58 | 59 | 60 | All Classes 61 | 62 | 63 | SEARCH: 64 | 65 | 66 | 67 | 68 | 69 | 79 | 80 | JavaScript is disabled on your browser. 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 93 | 94 | 95 | 96 | 97 | Deprecated API 98 | Contents 99 | 100 | 101 | 146 | 147 | 148 | -------------------------------------------------------------------------------- /doc/element-list: -------------------------------------------------------------------------------- 1 | unnamed package 2 | abi 3 | abi.fields 4 | comparation 5 | etherscan 6 | etherscan.gson 7 | graphviz 8 | gson 9 | javafx 10 | opcodes 11 | opcodes.arithmeticOpcodes 12 | opcodes.arithmeticOpcodes.binaryArithmeticOpcodes 13 | opcodes.arithmeticOpcodes.ternaryArithmeticOpcodes 14 | opcodes.arithmeticOpcodes.unaryArithmeticOpcodes 15 | opcodes.blockOpcodes 16 | opcodes.controlFlowOpcodes 17 | opcodes.environmentalOpcodes 18 | opcodes.stackOpcodes 19 | opcodes.systemOpcodes 20 | parseTree 21 | parseTree.cfg 22 | parseTree.SymbolicExecution 23 | rebuiltabi 24 | rebuiltabi.fields 25 | SolidityInfo 26 | utils 27 | -------------------------------------------------------------------------------- /doc/etherscan/package-tree.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | etherscan Class Hierarchy 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 17 | 18 | 19 | 20 | 21 | 22 | 34 | 35 | JavaScript is disabled on your browser. 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | Skip navigation links 45 | 46 | 47 | 48 | 49 | Overview 50 | Package 51 | Class 52 | Tree 53 | Deprecated 54 | Index 55 | Help 56 | 57 | 58 | 59 | 60 | All Classes 61 | 62 | 63 | SEARCH: 64 | 65 | 66 | 67 | 68 | 69 | 79 | 80 | JavaScript is disabled on your browser. 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 93 | 94 | 95 | 96 | 97 | Hierarchy For Package etherscan 98 | Package Hierarchies: 99 | 100 | All Packages 101 | 102 | 103 | 104 | 105 | Class Hierarchy 106 | 107 | java.lang.Object 108 | 109 | etherscan.EtherScanDownloader 110 | 111 | 112 | 113 | 114 | 115 | 116 | 161 | 162 | 163 | -------------------------------------------------------------------------------- /doc/gson/package-tree.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | gson Class Hierarchy 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 17 | 18 | 19 | 20 | 21 | 22 | 34 | 35 | JavaScript is disabled on your browser. 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | Skip navigation links 45 | 46 | 47 | 48 | 49 | Overview 50 | Package 51 | Class 52 | Tree 53 | Deprecated 54 | Index 55 | Help 56 | 57 | 58 | 59 | 60 | All Classes 61 | 62 | 63 | SEARCH: 64 | 65 | 66 | 67 | 68 | 69 | 79 | 80 | JavaScript is disabled on your browser. 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 93 | 94 | 95 | 96 | 97 | Hierarchy For Package gson 98 | Package Hierarchies: 99 | 100 | All Packages 101 | 102 | 103 | 104 | 105 | Class Hierarchy 106 | 107 | java.lang.Object 108 | 109 | gson.GsonAbi 110 | 111 | 112 | 113 | 114 | 115 | 116 | 161 | 162 | 163 | -------------------------------------------------------------------------------- /doc/jquery/images/ui-bg_glass_55_fbf9ee_1x400.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SeUniVr/EtherSolve/59fe4412f7230d9ee1047b25fbcf30b63cb89488/doc/jquery/images/ui-bg_glass_55_fbf9ee_1x400.png -------------------------------------------------------------------------------- /doc/jquery/images/ui-bg_glass_65_dadada_1x400.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SeUniVr/EtherSolve/59fe4412f7230d9ee1047b25fbcf30b63cb89488/doc/jquery/images/ui-bg_glass_65_dadada_1x400.png -------------------------------------------------------------------------------- /doc/jquery/images/ui-bg_glass_75_dadada_1x400.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SeUniVr/EtherSolve/59fe4412f7230d9ee1047b25fbcf30b63cb89488/doc/jquery/images/ui-bg_glass_75_dadada_1x400.png -------------------------------------------------------------------------------- /doc/jquery/images/ui-bg_glass_75_e6e6e6_1x400.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SeUniVr/EtherSolve/59fe4412f7230d9ee1047b25fbcf30b63cb89488/doc/jquery/images/ui-bg_glass_75_e6e6e6_1x400.png -------------------------------------------------------------------------------- /doc/jquery/images/ui-bg_glass_95_fef1ec_1x400.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SeUniVr/EtherSolve/59fe4412f7230d9ee1047b25fbcf30b63cb89488/doc/jquery/images/ui-bg_glass_95_fef1ec_1x400.png -------------------------------------------------------------------------------- /doc/jquery/images/ui-bg_highlight-soft_75_cccccc_1x100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SeUniVr/EtherSolve/59fe4412f7230d9ee1047b25fbcf30b63cb89488/doc/jquery/images/ui-bg_highlight-soft_75_cccccc_1x100.png -------------------------------------------------------------------------------- /doc/jquery/images/ui-icons_222222_256x240.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SeUniVr/EtherSolve/59fe4412f7230d9ee1047b25fbcf30b63cb89488/doc/jquery/images/ui-icons_222222_256x240.png -------------------------------------------------------------------------------- /doc/jquery/images/ui-icons_2e83ff_256x240.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SeUniVr/EtherSolve/59fe4412f7230d9ee1047b25fbcf30b63cb89488/doc/jquery/images/ui-icons_2e83ff_256x240.png -------------------------------------------------------------------------------- /doc/jquery/images/ui-icons_454545_256x240.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SeUniVr/EtherSolve/59fe4412f7230d9ee1047b25fbcf30b63cb89488/doc/jquery/images/ui-icons_454545_256x240.png -------------------------------------------------------------------------------- /doc/jquery/images/ui-icons_888888_256x240.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SeUniVr/EtherSolve/59fe4412f7230d9ee1047b25fbcf30b63cb89488/doc/jquery/images/ui-icons_888888_256x240.png -------------------------------------------------------------------------------- /doc/jquery/images/ui-icons_cd0a0a_256x240.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SeUniVr/EtherSolve/59fe4412f7230d9ee1047b25fbcf30b63cb89488/doc/jquery/images/ui-icons_cd0a0a_256x240.png -------------------------------------------------------------------------------- /doc/jquery/jquery-ui.structure.css: -------------------------------------------------------------------------------- 1 | /*! 2 | * jQuery UI CSS Framework 1.12.1 3 | * http://jqueryui.com 4 | * 5 | * Copyright jQuery Foundation and other contributors 6 | * Released under the MIT license. 7 | * http://jquery.org/license 8 | * 9 | * http://api.jqueryui.com/category/theming/ 10 | */ 11 | /* Layout helpers 12 | ----------------------------------*/ 13 | .ui-helper-hidden { 14 | display: none; 15 | } 16 | .ui-helper-hidden-accessible { 17 | border: 0; 18 | clip: rect(0 0 0 0); 19 | height: 1px; 20 | margin: -1px; 21 | overflow: hidden; 22 | padding: 0; 23 | position: absolute; 24 | width: 1px; 25 | } 26 | .ui-helper-reset { 27 | margin: 0; 28 | padding: 0; 29 | border: 0; 30 | outline: 0; 31 | line-height: 1.3; 32 | text-decoration: none; 33 | font-size: 100%; 34 | list-style: none; 35 | } 36 | .ui-helper-clearfix:before, 37 | .ui-helper-clearfix:after { 38 | content: ""; 39 | display: table; 40 | border-collapse: collapse; 41 | } 42 | .ui-helper-clearfix:after { 43 | clear: both; 44 | } 45 | .ui-helper-zfix { 46 | width: 100%; 47 | height: 100%; 48 | top: 0; 49 | left: 0; 50 | position: absolute; 51 | opacity: 0; 52 | filter:Alpha(Opacity=0); /* support: IE8 */ 53 | } 54 | 55 | .ui-front { 56 | z-index: 100; 57 | } 58 | 59 | 60 | /* Interaction Cues 61 | ----------------------------------*/ 62 | .ui-state-disabled { 63 | cursor: default !important; 64 | pointer-events: none; 65 | } 66 | 67 | 68 | /* Icons 69 | ----------------------------------*/ 70 | .ui-icon { 71 | display: inline-block; 72 | vertical-align: middle; 73 | margin-top: -.25em; 74 | position: relative; 75 | text-indent: -99999px; 76 | overflow: hidden; 77 | background-repeat: no-repeat; 78 | } 79 | 80 | .ui-widget-icon-block { 81 | left: 50%; 82 | margin-left: -8px; 83 | display: block; 84 | } 85 | 86 | /* Misc visuals 87 | ----------------------------------*/ 88 | 89 | /* Overlays */ 90 | .ui-widget-overlay { 91 | position: fixed; 92 | top: 0; 93 | left: 0; 94 | width: 100%; 95 | height: 100%; 96 | } 97 | .ui-autocomplete { 98 | position: absolute; 99 | top: 0; 100 | left: 0; 101 | cursor: default; 102 | } 103 | .ui-menu { 104 | list-style: none; 105 | padding: 0; 106 | margin: 0; 107 | display: block; 108 | outline: 0; 109 | } 110 | .ui-menu .ui-menu { 111 | position: absolute; 112 | } 113 | .ui-menu .ui-menu-item { 114 | margin: 0; 115 | cursor: pointer; 116 | /* support: IE10, see #8844 */ 117 | list-style-image: url("data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7"); 118 | } 119 | .ui-menu .ui-menu-item-wrapper { 120 | position: relative; 121 | padding: 3px 1em 3px .4em; 122 | } 123 | .ui-menu .ui-menu-divider { 124 | margin: 5px 0; 125 | height: 0; 126 | font-size: 0; 127 | line-height: 0; 128 | border-width: 1px 0 0 0; 129 | } 130 | .ui-menu .ui-state-focus, 131 | .ui-menu .ui-state-active { 132 | margin: -1px; 133 | } 134 | 135 | /* icon support */ 136 | .ui-menu-icons { 137 | position: relative; 138 | } 139 | .ui-menu-icons .ui-menu-item-wrapper { 140 | padding-left: 2em; 141 | } 142 | 143 | /* left-aligned */ 144 | .ui-menu .ui-icon { 145 | position: absolute; 146 | top: 0; 147 | bottom: 0; 148 | left: .2em; 149 | margin: auto 0; 150 | } 151 | 152 | /* right-aligned */ 153 | .ui-menu .ui-menu-icon { 154 | left: auto; 155 | right: 0; 156 | } 157 | -------------------------------------------------------------------------------- /doc/jquery/jquery-ui.structure.min.css: -------------------------------------------------------------------------------- 1 | /*! jQuery UI - v1.12.1 - 2018-12-06 2 | * http://jqueryui.com 3 | * Copyright jQuery Foundation and other contributors; Licensed MIT */ 4 | 5 | .ui-helper-hidden{display:none}.ui-helper-hidden-accessible{border:0;clip:rect(0 0 0 0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.ui-helper-reset{margin:0;padding:0;border:0;outline:0;line-height:1.3;text-decoration:none;font-size:100%;list-style:none}.ui-helper-clearfix:before,.ui-helper-clearfix:after{content:"";display:table;border-collapse:collapse}.ui-helper-clearfix:after{clear:both}.ui-helper-zfix{width:100%;height:100%;top:0;left:0;position:absolute;opacity:0;filter:Alpha(Opacity=0)}.ui-front{z-index:100}.ui-state-disabled{cursor:default!important;pointer-events:none}.ui-icon{display:inline-block;vertical-align:middle;margin-top:-.25em;position:relative;text-indent:-99999px;overflow:hidden;background-repeat:no-repeat}.ui-widget-icon-block{left:50%;margin-left:-8px;display:block}.ui-widget-overlay{position:fixed;top:0;left:0;width:100%;height:100%}.ui-autocomplete{position:absolute;top:0;left:0;cursor:default}.ui-menu{list-style:none;padding:0;margin:0;display:block;outline:0}.ui-menu .ui-menu{position:absolute}.ui-menu .ui-menu-item{margin:0;cursor:pointer;list-style-image:url("data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7")}.ui-menu .ui-menu-item-wrapper{position:relative;padding:3px 1em 3px .4em}.ui-menu .ui-menu-divider{margin:5px 0;height:0;font-size:0;line-height:0;border-width:1px 0 0 0}.ui-menu .ui-state-focus,.ui-menu .ui-state-active{margin:-1px}.ui-menu-icons{position:relative}.ui-menu-icons .ui-menu-item-wrapper{padding-left:2em}.ui-menu .ui-icon{position:absolute;top:0;bottom:0;left:.2em;margin:auto 0}.ui-menu .ui-menu-icon{left:auto;right:0} -------------------------------------------------------------------------------- /doc/jquery/jszip-utils/dist/jszip-utils-ie.js: -------------------------------------------------------------------------------- 1 | /*! 2 | 3 | JSZipUtils - A collection of cross-browser utilities to go along with JSZip. 4 | 5 | 6 | (c) 2014 Stuart Knightley, David Duponchel 7 | Dual licenced under the MIT license or GPLv3. See https://raw.github.com/Stuk/jszip-utils/master/LICENSE.markdown. 8 | 9 | */ 10 | ;(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error("Cannot find module '"+o+"'")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o\r\n"+ 18 | "\r\n"; 32 | 33 | // inject VBScript 34 | document.write(IEBinaryToArray_ByteStr_Script); 35 | 36 | global.JSZipUtils._getBinaryFromXHR = function (xhr) { 37 | var binary = xhr.responseBody; 38 | var byteMapping = {}; 39 | for ( var i = 0; i < 256; i++ ) { 40 | for ( var j = 0; j < 256; j++ ) { 41 | byteMapping[ String.fromCharCode( i + (j << 8) ) ] = 42 | String.fromCharCode(i) + String.fromCharCode(j); 43 | } 44 | } 45 | var rawBytes = IEBinaryToArray_ByteStr(binary); 46 | var lastChr = IEBinaryToArray_ByteStr_Last(binary); 47 | return rawBytes.replace(/[\s\S]/g, function( match ) { 48 | return byteMapping[match]; 49 | }) + lastChr; 50 | }; 51 | 52 | // enforcing Stuk's coding style 53 | // vim: set shiftwidth=4 softtabstop=4: 54 | 55 | },{}]},{},[1]) 56 | ; 57 | -------------------------------------------------------------------------------- /doc/jquery/jszip-utils/dist/jszip-utils-ie.min.js: -------------------------------------------------------------------------------- 1 | /*! 2 | 3 | JSZipUtils - A collection of cross-browser utilities to go along with JSZip. 4 | 5 | 6 | (c) 2014 Stuart Knightley, David Duponchel 7 | Dual licenced under the MIT license or GPLv3. See https://raw.github.com/Stuk/jszip-utils/master/LICENSE.markdown. 8 | 9 | */ 10 | !function a(b,c,d){function e(g,h){if(!c[g]){if(!b[g]){var i="function"==typeof require&&require;if(!h&&i)return i(g,!0);if(f)return f(g,!0);throw new Error("Cannot find module '"+g+"'")}var j=c[g]={exports:{}};b[g][0].call(j.exports,function(a){var c=b[g][1][a];return e(c?c:a)},j,j.exports,a,b,c,d)}return c[g].exports}for(var f="function"==typeof require&&require,g=0;g\r\n\r\n";document.write(b),a.JSZipUtils._getBinaryFromXHR=function(a){for(var b=a.responseBody,c={},d=0;256>d;d++)for(var e=0;256>e;e++)c[String.fromCharCode(d+(e<<8))]=String.fromCharCode(d)+String.fromCharCode(e);var f=IEBinaryToArray_ByteStr(b),g=IEBinaryToArray_ByteStr_Last(b);return f.replace(/[\s\S]/g,function(a){return c[a]})+g}},{}]},{},[1]); 11 | -------------------------------------------------------------------------------- /doc/jquery/jszip-utils/dist/jszip-utils.js: -------------------------------------------------------------------------------- 1 | /*! 2 | 3 | JSZipUtils - A collection of cross-browser utilities to go along with JSZip. 4 | 5 | 6 | (c) 2014 Stuart Knightley, David Duponchel 7 | Dual licenced under the MIT license or GPLv3. See https://raw.github.com/Stuk/jszip-utils/master/LICENSE.markdown. 8 | 9 | */ 10 | !function(e){"object"==typeof exports?module.exports=e():"function"==typeof define&&define.amd?define(e):"undefined"!=typeof window?window.JSZipUtils=e():"undefined"!=typeof global?global.JSZipUtils=e():"undefined"!=typeof self&&(self.JSZipUtils=e())}(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error("Cannot find module '"+o+"'")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o 5 | 6 | (c) 2014 Stuart Knightley, David Duponchel 7 | Dual licenced under the MIT license or GPLv3. See https://raw.github.com/Stuk/jszip-utils/master/LICENSE.markdown. 8 | 9 | */ 10 | !function(a){"object"==typeof exports?module.exports=a():"function"==typeof define&&define.amd?define(a):"undefined"!=typeof window?window.JSZipUtils=a():"undefined"!=typeof global?global.JSZipUtils=a():"undefined"!=typeof self&&(self.JSZipUtils=a())}(function(){return function a(b,c,d){function e(g,h){if(!c[g]){if(!b[g]){var i="function"==typeof require&&require;if(!h&&i)return i(g,!0);if(f)return f(g,!0);throw new Error("Cannot find module '"+g+"'")}var j=c[g]={exports:{}};b[g][0].call(j.exports,function(a){var c=b[g][1][a];return e(c?c:a)},j,j.exports,a,b,c,d)}return c[g].exports}for(var f="function"==typeof require&&require,g=0;g 2 | 3 | 4 | 5 | 6 | Generated Documentation (Untitled) 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | JavaScript is disabled on your browser. 19 | 20 | index.html 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /doc/package-search-index.js: -------------------------------------------------------------------------------- 1 | packageSearchIndex = [{"l":"abi"},{"l":"abi.fields"},{"l":"All Packages","url":"allpackages-index.html"},{"l":"comparation"},{"l":"etherscan"},{"l":"etherscan.gson"},{"l":"graphviz"},{"l":"gson"},{"l":"javafx"},{"l":"opcodes"},{"l":"opcodes.arithmeticOpcodes"},{"l":"opcodes.arithmeticOpcodes.binaryArithmeticOpcodes"},{"l":"opcodes.arithmeticOpcodes.ternaryArithmeticOpcodes"},{"l":"opcodes.arithmeticOpcodes.unaryArithmeticOpcodes"},{"l":"opcodes.blockOpcodes"},{"l":"opcodes.controlFlowOpcodes"},{"l":"opcodes.environmentalOpcodes"},{"l":"opcodes.stackOpcodes"},{"l":"opcodes.systemOpcodes"},{"l":"parseTree"},{"l":"parseTree.cfg"},{"l":"parseTree.SymbolicExecution"},{"l":"rebuiltabi"},{"l":"rebuiltabi.fields"},{"l":"SolidityInfo"},{"l":"utils"}] -------------------------------------------------------------------------------- /doc/resources/glass.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SeUniVr/EtherSolve/59fe4412f7230d9ee1047b25fbcf30b63cb89488/doc/resources/glass.png -------------------------------------------------------------------------------- /doc/resources/x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SeUniVr/EtherSolve/59fe4412f7230d9ee1047b25fbcf30b63cb89488/doc/resources/x.png -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SeUniVr/EtherSolve/59fe4412f7230d9ee1047b25fbcf30b63cb89488/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Fri Apr 10 11:56:33 CEST 2020 2 | distributionUrl=https\://services.gradle.org/distributions/gradle-6.3-all.zip 3 | distributionBase=GRADLE_USER_HOME 4 | distributionPath=wrapper/dists 5 | zipStorePath=wrapper/dists 6 | zipStoreBase=GRADLE_USER_HOME 7 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | set DIRNAME=%~dp0 12 | if "%DIRNAME%" == "" set DIRNAME=. 13 | set APP_BASE_NAME=%~n0 14 | set APP_HOME=%DIRNAME% 15 | 16 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 17 | set DEFAULT_JVM_OPTS="-Xmx64m" 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windows variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | 53 | :win9xME_args 54 | @rem Slurp the command line arguments. 55 | set CMD_LINE_ARGS= 56 | set _SKIP=2 57 | 58 | :win9xME_args_slurp 59 | if "x%~1" == "x" goto execute 60 | 61 | set CMD_LINE_ARGS=%* 62 | 63 | :execute 64 | @rem Setup the command line 65 | 66 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 67 | 68 | @rem Execute Gradle 69 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 70 | 71 | :end 72 | @rem End local scope for the variables with windows NT shell 73 | if "%ERRORLEVEL%"=="0" goto mainEnd 74 | 75 | :fail 76 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 77 | rem the _cmd.exe /c_ return code! 78 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 79 | exit /b 1 80 | 81 | :mainEnd 82 | if "%OS%"=="Windows_NT" endlocal 83 | 84 | :omega 85 | -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | rootProject.name = 'EtherSolve' 2 | include 'Core' 3 | include 'Abi' 4 | include 'WebApp' 5 | include 'UI' 6 | include 'SecurityAnalysis' 7 | 8 | --------------------------------------------------------------------------------
JavaScript is disabled on your browser.
index.html